* [PATCH 6.12 000/602] 6.12.101-rc1 review
@ 2026-07-30 14:06 Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 001/602] platform/x86/intel-uncore-freq: Fix current_freq_khz after CPU hotplug Greg Kroah-Hartman
` (605 more replies)
0 siblings, 606 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, linux-kernel, torvalds, akpm, linux,
shuah, patches, lkft-triage, pavel, jonathanh, f.fainelli,
sudipm.mukherjee, rwarsow, conor, hargar, broonie, achill, sr
This is the start of the stable review cycle for the 6.12.101 release.
There are 602 patches in this series, all will be posted as a response
to this one. If anyone has any issues with these being applied, please
let me know.
Responses should be made by Sat, 01 Aug 2026 14:13:43 +0000.
Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.12.101-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.12.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 6.12.101-rc1
Nikunj A Dadhania <nikunj@amd.com>
KVM: SVM: Bump asid_generation on CPU online to avoid ASID collision after hotplug
David Howells <dhowells@redhat.com>
afs: Fix uninit var in afs_alloc_anon_key()
Pavitra Jha <jhapavitra98@gmail.com>
Bluetooth: hci_conn: Fix memory leak in hci_le_big_terminate()
Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Bluetooth: hci_conn: Fix not cleaning up PA_LINK connections
Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Bluetooth: hci_conn: Fix not cleaning up Broadcaster/Broadcast Source
Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Bluetooth: hci_conn: Fix running bis_cleanup for hci_conn->type PA_LINK
Nan Li <tonanli66@gmail.com>
afs: handle CB.InitCallBackState3 requests without a server record
David Howells <dhowells@redhat.com>
afs: Fix delayed allocation of a cell's anonymous key
Ivan Vecera <ivecera@redhat.com>
dpll: fix clock quality level reporting
Edward Adam Davis <eadavis@qq.com>
afs: Set vllist to NULL if addr parsing fails
Lukas Bulwahn <lukas.bulwahn@redhat.com>
net: ethernet: Remove accidental duplication in Kconfig file
Nicolas Escande <nico.escande@gmail.com>
wifi: nl80211: fix nl80211_start_radar_detection return value
David Howells <dhowells@redhat.com>
rxrpc: Fix locking issues with the peer record hash
David Howells <dhowells@redhat.com>
rxrpc: Disable IRQ, not BH, to take the lock for ->attend_link
Koen Koning <koen.koning@linux.intel.com>
gpu: Fix uninitialized buddy for built-in drivers
Gal Pressman <gal@nvidia.com>
net/mlx5e: Fix NULL pointer dereference in ioctl module EEPROM query
Guangshuo Li <lgs201920130244@gmail.com>
usb: musb: omap2430: Do not put borrowed of_node in probe
Johan Hovold <johan@kernel.org>
usb: musb: omap2430: clean up probe error handling
Johan Hovold <johan@kernel.org>
USB: gadget: fsl-udc: fix dev_printk() device
Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
USB: gadget: Use str_enable_disable-like helpers
David Howells <dhowells@redhat.com>
afs: Fix lack of locking around modifications of net->cells_dyn_ino
David Howells <dhowells@redhat.com>
afs: Fix dynamic lookup to fail on cell lookup failure
David Howells <dhowells@redhat.com>
afs: Simplify cell record handling
David Howells <dhowells@redhat.com>
afs: Fix afs_server ref accounting
David Howells <dhowells@redhat.com>
afs: Use the per-peer app data provided by rxrpc
David Howells <dhowells@redhat.com>
rxrpc: Allow the app to store private data on peer structs
David Howells <dhowells@redhat.com>
afs: Drop the net parameter from afs_unuse_cell()
David Howells <dhowells@redhat.com>
afs: Make afs_lookup_cell() take a trace note
David Howells <dhowells@redhat.com>
afs: Improve server refcount/active count tracing
Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Bluetooth: hci_core: Fix not accounting for BIS/CIS/PA links separately
Yang Li <yang.li@amlogic.com>
Bluetooth: Add PA_LINK to distinguish BIG sync and PA sync connections
Haoxiang Li <haoxiang_li2024@163.com>
net: ipa: fix SMEM state handle leaks in SMP2P init
Théo Lebrun <theo.lebrun@bootlin.com>
net: macb: drop in-flight Tx SKBs on close
Reinette Chatre <reinette.chatre@intel.com>
fs/resctrl: Fix double-add of pseudo-locked region's RMID to free list
Bryam Vargas <hexlabsecurity@proton.me>
ata: libata-core: Reject an invalid concurrent positioning ranges count
Dawei Feng <dawei.feng@seu.edu.cn>
octeontx2-pf: fix SQB pointer leak on init failure
Dawei Feng <dawei.feng@seu.edu.cn>
net/mlx5: HWS, fix matcher leak on resize target setup failure
Yevgeny Kliteynik <kliteyn@nvidia.com>
net/mlx5: HWS, Rearrange to prevent forward declaration
Wentao Liang <vulab@iscas.ac.cn>
ipmi: fix refcount leak in i_ipmi_request()
Breno Leitao <leitao@debian.org>
bootconfig: fix NULL-pointer arithmetic in xbc_snprint_cmdline()
Breno Leitao <leitao@debian.org>
bootconfig: move xbc_snprint_cmdline() to lib/bootconfig.c
Junrui Luo <moonafterrain@outlook.com>
octeontx2-af: cn10k: restrict VF LMTLINE sharing to its own PF
Sergio Paracuellos <sergio.paracuellos@gmail.com>
gpio: mt7621: avoid corruption of shared interrupt trigger state
Ankit Garg <nktgrg@google.com>
gve: fix header buffer corruption with header-split and HW-GRO
Maoyi Xie <maoyixie.tju@gmail.com>
net: ip6_tunnel: require CAP_NET_ADMIN in the device netns for changelink
Dexuan Cui <decui@microsoft.com>
net: mana: Validate the packet length reported by the NIC
Thomas Gleixner <tglx@kernel.org>
locking/rt: Fix the incorrect RCU protection in rt_spin_unlock()
Guangshuo Li <lgs201920130244@gmail.com>
mmc: vub300: fix use-after-free on probe failure
Johan Hovold <johan@kernel.org>
mmc: vub300: rename probe error labels
Johan Hovold <johan@kernel.org>
mmc: vub300: fix use-after-free on disconnect
Maoyi Xie <maoyixie.tju@gmail.com>
wifi: libertas_tf: fix use-after-free in lbtf_free_adapter()
Ingo Blechschmidt <iblech@speicherleck.de>
dm: avoid leaking the caller's thread keyring via the table device file
Christian Brauner <brauner@kernel.org>
cred: add scoped_with_kernel_creds()
Christian Brauner <brauner@kernel.org>
cred: add kernel_cred() helper
Christian Brauner <brauner@kernel.org>
cleanup: fix scoped_class()
Christian Brauner <brauner@kernel.org>
cleanup: add a scoped version of CLASS()
Mikulas Patocka <mpatocka@redhat.com>
dm-integrity: fix leaking uninitialized kernel memory
Connor Williamson <connordw@amazon.com>
block: remove redundant GD_NEED_PART_SCAN in add_disk_final()
Ming Lei <ming.lei@redhat.com>
block: add helper add_disk_final()
Tristan Madani <tristan@talencesecurity.com>
bpf: Reset register bounds before narrowing retval range in check_mem_access()
Amery Hung <ameryhung@gmail.com>
bpf: Refactor check_ctx_access()
Kumar Kartikeya Dwivedi <memxor@gmail.com>
bpf: Refactor {acquire,release}_reference_state
Souvik Banerjee <souvik@amlalabs.com>
ovl: use linked upper dentry in copy-up tmpfile
Michael Bommarito <michael.bommarito@gmail.com>
nvmet-auth: reject short AUTH_RECEIVE buffers
Damien Le Moal <dlemoal@kernel.org>
nvmet: Introduce nvmet_req_transfer_len()
Dmitry Safonov <0x7f454c46@gmail.com>
tcp: Decrement tcp_md5_needed static branch
Michael Bommarito <michael.bommarito@gmail.com>
tcp: defer md5sig_info kfree past RCU grace period in tcp_connect
Qianyu Luo <qianyuluo3@gmail.com>
xfrm: nat_keepalive: avoid double free on send error
Sebastian Andrzej Siewior <bigeasy@linutronix.de>
xfrm: Use nested-BH locking for nat_keepalive_sk_ipv[46]
Vincent Jardin <vjardin@free.fr>
i2c: imx: fix locked bus on SMBus block-read of 0 (atomic)
Stefan Eichenberger <stefan.eichenberger@toradex.com>
i2c: imx: separate atomic, dma and non-dma use case
Koichiro Den <den@valinux.co.jp>
dmaengine: dw-edma-pcie: Reject devices without driver data
Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
dmaengine: dw-edma: Fix confusing cleanup.h syntax
Abinash Singh <abinashlalotra@gmail.com>
dma: dw-edma: Fix build warning in dw_edma_pcie_probe()
Michael Bommarito <michael.bommarito@gmail.com>
thunderbolt: Prevent XDomain delayed work use-after-free on disconnect
Mika Westerberg <mika.westerberg@linux.intel.com>
thunderbolt: Remove XDomain from the bus without holding tb->lock
Mika Westerberg <mika.westerberg@linux.intel.com>
thunderbolt: Remove service debugfs entries during unregister
Mika Westerberg <mika.westerberg@linux.intel.com>
thunderbolt: Keep XDomain reference during the lifetime of a service
Muchun Song <muchun.song@linux.dev>
mm/sparse-vmemmap: fix DAX vmemmap accounting with optimization
David Hildenbrand (Arm) <david@kernel.org>
mm: prepare to move subsection_map_init() to mm/sparse-vmemmap.c
Florian Fuchs <fuchsfl@gmail.com>
mtd: maps: vmu-flash: fix fault in unaligned fixup
Muchun Song <muchun.song@linux.dev>
mm/mm_init: fix pageblock migratetype for ZONE_DEVICE compound pages
Bryam Vargas <hexlabsecurity@proton.me>
landlock: Fix LANDLOCK_SCOPE_SIGNAL bypass on the SIGIO path
Mickaël Salaün <mic@digikod.net>
landlock: Prepare to use credential instead of domain for fowner
Muchun Song <muchun.song@linux.dev>
mm/sparse-vmemmap: fix vmemmap accounting underflow
Deepanshu Kartikey <kartikey406@gmail.com>
mm/hugetlb: fix hugetlb cgroup rsvd charge/uncharge mismatch
Tanmay Shah <tanmay.shah@amd.com>
remoteproc: xlnx: Check remote core state
Chuck Lever <chuck.lever@oracle.com>
SUNRPC: Return an error from xdr_buf_to_bvec() on overflow
Chuck Lever <chuck.lever@oracle.com>
SUNRPC: Add helpers to convert xdr_buf byte ranges to scatterlists
Jeff Layton <jlayton@kernel.org>
sunrpc: allocate a separate bvec array for socket sends
Mike Snitzer <snitzer@kernel.org>
NFSD: pass nfsd_file to nfsd_iter_read()
Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com>
gpu/buddy: bail out of try_harder when alignment cannot be honoured
Joel Fernandes <joelagnelf@nvidia.com>
gpu: Move DRM buddy allocator one level up (part two)
Theodor Arsenij Larionov-Trichkine <theodorlarionov@gmail.com>
netfilter: nft_fib: reject fib expression on the netdev egress hook
Florian Westphal <fw@strlen.de>
netfilter: nf_tables: remove register tracking infrastructure
Yue Haibing <yuehaibing@huawei.com>
netfilter: nf_tables: Remove unused nft_reduce_is_readonly()
Jeremy Sowden <jeremy@azazel.net>
netfilter: bitwise: rename some boolean operation functions
Pablo Neira Ayuso <pablo@netfilter.org>
netfilter: nf_conntrack_sip: validate skb_dst() before accessing it
Florian Westphal <fw@strlen.de>
netfilter: nf_conntrack_sip: remove net variable shadowing
Cássio Gabriel <cassiogabrielcontato@gmail.com>
ASoC: mediatek: mt8183: Check runtime resume during probe
Chen-Yu Tsai <wenst@chromium.org>
ASoC: mediatek: mt8183-afe-pcm: use local `dev` pointer in driver callbacks
Chen-Yu Tsai <wenst@chromium.org>
ASoC: mediatek: mt8183-afe-pcm: Support >32 bit DMA addresses
Chen-Yu Tsai <wenst@chromium.org>
ASoC: mediatek: mt8183-afe-pcm: Shorten memif_data table using macros
Cássio Gabriel <cassiogabrielcontato@gmail.com>
ASoC: mediatek: mt8192: Check runtime resume during probe
Tang Bin <tangbin@cmss.chinamobile.com>
ASoC: mediatek: mt8192-afe-pcm: Simplify probe() with local dev variable
Abel Vesa <abel.vesa@oss.qualcomm.com>
arm64: dts: qcom: hamoa: Fix OPP tables for all DisplayPort controllers
Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
arm64: dts: qcom: correct RBR opp entry
Runyu Xiao <runyu.xiao@seu.edu.cn>
octeontx2-pf: clear stale mailbox IRQ state before request_irq()
Runyu Xiao <runyu.xiao@seu.edu.cn>
octeontx2-vf: clear stale mailbox IRQ state before request_irq()
Subbaraya Sundeep <sbhatta@marvell.com>
octeontx2: Annotate mmio regions as __iomem
Jason Wang <jasowang@redhat.com>
VDUSE: avoid leaking information to userspace
Eugenio Pérez <eperezma@redhat.com>
vduse: take out allocations from vduse_dev_alloc_coherent
Eugenio Pérez <eperezma@redhat.com>
vduse: remove unused vaddr parameter of vduse_domain_free_coherent
Sheng Zhao <sheng.zhao@bytedance.com>
vduse: Use fixed 4KB bounce pages for non-4KB page size
Li Xiasong <lixiasong1@huawei.com>
tipc: restrict socket queue dumps in enqueue tracepoints
David Howells <dhowells@redhat.com>
rxrpc: Fix socket notification race
David Howells <dhowells@redhat.com>
rxrpc: Fix notification vs call-release vs recvmsg
David Howells <dhowells@redhat.com>
rxrpc: Use irq-disabling spinlocks between app and I/O thread
David Howells <dhowells@redhat.com>
rxrpc: Don't need barrier for ->tx_bottom and ->acks_hard_ack
David Howells <dhowells@redhat.com>
rxrpc: Fix CPU time starvation in I/O thread
Jiacheng Yu <yujiacheng3@huawei.com>
fbcon: Use correct type for vc_resize() return value
Thomas Zimmermann <tzimmermann@suse.de>
fbcon: Rename struct fbcon_ops to struct fbcon_par
Darrick J. Wong <djwong@kernel.org>
xfs: don't replace the wrong part of the cow fork
Long Li <leo.lilong@huawei.com>
xfs: factor out xfs_attr3_leaf_init
Li Daming <d4n.for.sec@gmail.com>
rxrpc: serialize kernel accept preallocation with socket teardown
David Howells <dhowells@redhat.com>
rxrpc: Pull out certain app callback funcs into an ops table
Xu Rao <raoxu@uniontech.com>
ALSA: hda: Fix cached processing coefficient verbs
Zhang Heng <zhangheng@kylinos.cn>
ALSA: hda: conexant: Remove mic bias threshold override
Mingyu Wang <25181214217@stu.xidian.edu.cn>
i2c: i801: fix hardware state machine corruption in error path
Ricardo Robaina <rrobaina@redhat.com>
audit: fix recursive locking deadlock in audit_dupe_exe()
Ricardo Robaina <rrobaina@redhat.com>
audit: use 'unsigned int' instead of 'unsigned'
Jeff Layton <jlayton@kernel.org>
audit: widen ino fields to u64
NeilBrown <neil@brown.name>
VFS/audit: introduce kern_path_parent() for audit
Haoxiang Li <haoxiang_li2024@163.com>
i2c: davinci: Unregister cpufreq notifier on probe failure
Sebastian Alba Vives <sebasjosue84@gmail.com>
fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region()
Nicolin Chen <nicolinc@nvidia.com>
iommufd: Avoid partial fault group delivery in iommufd_fault_fops_read()
Nicolin Chen <nicolinc@nvidia.com>
iommufd: Break the loop on failure in iommufd_fault_fops_read()
Nicolin Chen <nicolinc@nvidia.com>
iommufd: Reject invalid read count in iommufd_fault_fops_read()
SJ Park <sj@kernel.org>
mm/damon/core: disallow overlapping input ranges for damon_set_regions()
SJ Park <sj@kernel.org>
mm/damon/core: validate ranges in damon_set_regions()
Miguel Ojeda <ojeda@kernel.org>
rust: allow `suspicious_runtime_symbol_definitions` lint for Rust >= 1.98
Eddie Phillips <eddiephillips@google.com>
gve: fix Rx queue stall on alloc failure
Coia Prant <coiaprant@gmail.com>
net: pcs: xpcs: fix SGMII state reading
Yitang Yang <yi1tang.yang@gmail.com>
io_uring/rw: fix missing ERESTARTSYS conversion in read paths
Harry Wentland <harry.wentland@amd.com>
drm/amd/display: Fix DTB DTO updates breaking live pixel rate sources
Eric Biggers <ebiggers@kernel.org>
fscrypt: Avoid dynamic allocation in fscrypt_get_devices()
Namjae Jeon <linkinjeon@kernel.org>
ksmbd: validate ACE size against SID sub-authorities
Namjae Jeon <linkinjeon@kernel.org>
ksmbd: bound DACL dedup walk to copied ACEs
Wentao Guan <guanwentao@uniontech.com>
ksmbd: restore DACL size on check_add_overflow() to avoid malformed ACL
Haofeng Li <lihaofeng@kylinos.cn>
ksmbd: validate num_subauth when copying ACE in set_ntacl_dacl
Youssef Samir <youssef.abdulrahman@oss.qualcomm.com>
net: qrtr: ns: Raise node count limit to 512
Jiayuan Chen <jiayuan.chen@linux.dev>
bpf: Fix same-register dst/src OOB read and pointer leak in sock_ops
Yang Wang <kevinyang.wang@amd.com>
drm/amd/pm: fix smu13 power limit range calculation
Asad Kamal <asad.kamal@amd.com>
drm/amdgpu: fix aperture mapping leak
Ce Sun <cesun102@amd.com>
drm/amdgpu: invoke pm_genpd_remove() before freeing genpd
Boyuan Zhang <boyuan.zhang@amd.com>
drm/amdgpu: fix division by zero with invalid uvd dimensions
Luca Coelho <luciano.coelho@intel.com>
drm/dp_mst: Handle torn-down topology gracefully in drm_dp_mst_topology_queue_probe()
Boyuan Zhang <boyuan.zhang@amd.com>
drm/amdgpu/vcn4: avoid rereading IB param length
Boyuan Zhang <boyuan.zhang@amd.com>
drm/amdgpu/vce: fix integer overflow in image size
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu/sdma4.4.2: replace BUG_ON() with WARN_ON()
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu/gfx9: replace BUG_ON() with WARN_ON()
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu/gfx9.4.3: replace BUG_ON() with WARN_ON()
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu/gfx8: drop unecessary BUG_ON()
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu/gfx12: replace BUG_ON() with WARN_ON()
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu/gfx11: replace BUG_ON() with WARN_ON()
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu/gfx10: replace BUG_ON() with WARN_ON()
Yang Wang <kevinyang.wang@amd.com>
drm/amd/pm: make pp_features read-only when scpm is enabled
Yang Wang <kevinyang.wang@amd.com>
drm/amd/pm: fix amdgpu_pm_info power display units
James Raphael Tiovalen <jamestiotio@gmail.com>
vxlan: mdb: Fix source list corruption on a failed replace
Stefano Garzarella <sgarzare@redhat.com>
vsock/virtio: collapse receive queue under memory pressure
Daehyeon Ko <4ncienth@gmail.com>
tipc: clear sock->sk on the failed-insert path in tipc_sk_create()
Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
tcp: initialize standalone TCP-AO response padding
Justin Lai <justinlai0215@realtek.com>
rtase: Workaround for TX hang caused by hardware packet parsing
Asim Viladi Oglu Manizada <manizada@pm.me>
pppoe: reload header pointer after dev_hard_header()
Kyle Zeng <kylebot@openai.com>
openvswitch: fix GSO userspace truncation underflow
Doruk Tan Ozturk <doruk@0sec.ai>
mctp: serial: handle zero-length frames to prevent rx buffer overflow
Doruk Tan Ozturk <doruk@0sec.ai>
mac802154: llsec: reject frames shorter than the authentication tag
Ibrahim Hashimov <security@auditcode.ai>
mac802154: hold an interface reference across the scan worker
Michael Bommarito <michael.bommarito@gmail.com>
ila: reload IPv6 header after pskb_may_pull in checksum adjust
Sergey Temerkhanov <sergey.temerkhanov@intel.com>
ice: use READ_ONCE() to access cached PHC time
Aleksandr Loktionov <aleksandr.loktionov@intel.com>
ice: reject out-of-range ptype in ice_parser_profile_init
James Montgomery <james_montgomery@disroot.org>
ksmbd: defer destroy_previous_session() until after NTLM authentication
Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
rbd: Reset positive result codes to zero in object map update path
Masami Hiramatsu (Google) <mhiramat@kernel.org>
selftests/ftrace: Reset triggers at top level before instance loop
Paul Greenwalt <paul.greenwalt@intel.com>
ice: fix PTP Call Trace during PTP release
Jann Horn <jannh@google.com>
proc: Fix broken error paths for namespace links
Fan Wu <fanwu01@zju.edu.cn>
net: hip04: fix RX buffer leak on build_skb failure
Shiming Cheng <shiming.cheng@mediatek.com>
net: gro: fix double aggregation of flush-marked skbs
David Lee <david.lee@trailofbits.com>
net/x25: fix use-after-free in x25_kill_by_neigh()
Manjunath Patil <manjunath.b.patil@oracle.com>
net/mlx5e: Use sender devcom for MPV master-up
Bryam Vargas <hexlabsecurity@proton.me>
net/iucv: fix use-after-free of a severed iucv_path
Hidayath Khan <hidayath@linux.ibm.com>
net/af_iucv: fix NULL deref in afiucv_hs_callback_syn()
Doruk Tan Ozturk <doruk@0sec.ai>
geneve: require CAP_NET_ADMIN in the device netns for changelink
Sungmin Kang <726ksm@gmail.com>
net: slip: serialize receive against buffer reallocation
Doruk Tan Ozturk <doruk@0sec.ai>
vxlan: require CAP_NET_ADMIN in the device netns for changelink
Breno Leitao <leitao@debian.org>
phonet: pep: fix use-after-free in pep_get_sb()
Lu Baolu <baolu.lu@linux.intel.com>
iommu/vt-d: Disallow SVA if page walk is not coherent
Zhang Yi <yi.zhang@huawei.com>
iomap: fix out-of-bounds bitmap_set() with zero-length range
Tengda Wu <wutengda@huaweicloud.com>
ftrace: Add global mutex to serialize trace_parser access
Eric Biggers <ebiggers@kernel.org>
fscrypt: Add missing superblock check in find_or_insert_direct_key()
Amir Goldstein <amir73il@gmail.com>
fs: preserve ACL_DONT_CACHE state in forget_cached_acl()
Christian Brauner <brauner@kernel.org>
binfmt_elf_fdpic: only honour the first PT_INTERP
Chancel Liu <chancel.liu@nxp.com>
ASoC: fsl_sai: Fix spurious BCLK on resume by clearing BYP
Shihuang Liu <shlomojune6@gmail.com>
amt: fix use-after-free in AMT delayed works
Douya Le <ldy3087146292@gmail.com>
libceph: remove debugfs files before client teardown
Douya Le <ldy3087146292@gmail.com>
libceph: reject zero bucket types in crush_decode
Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
libceph: Reject monmaps advertising zero monitors
Shuangpeng Bai <shuangpeng.kernel@gmail.com>
libceph: refresh auth->authorizer_buf{,_len} after authorizer update
Zhao Zhang <zzhan461@ucr.edu>
libceph: guard missing CRUSH type name lookup
Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
libceph: Fix multiplication overflow in decode_new_up_state_weight()
Douya Le <ldy3087146292@gmail.com>
libceph: bound get_version reply decode to front len
WenTao Liang <vulab@iscas.ac.cn>
ceph: fix refcount leak in ceph_readdir()
Bryam Vargas <hexlabsecurity@proton.me>
ceph: fix pre-auth out-of-bounds read on snaptrace in ceph_handle_caps()
Max Kellermann <max.kellermann@ionos.com>
ceph: add owner/capability checks for CEPH_IOC_SET_LAYOUT*
Zhiling Zou <roxy520tt@gmail.com>
sctp: close UDP tunnel sockets during netns teardown
Zhiling Zou <roxy520tt@gmail.com>
sctp: avoid auth_enable sysctl UAF during netns teardown
Jun Yang <junvyyang@tencent.com>
sctp: don't free the ASCONF's own transport in DEL-IP processing
Michael Bommarito <michael.bommarito@gmail.com>
mptcp: only set DATA_FIN when a mapping is present
Chenguang Zhao <zhaochenguang@kylinos.cn>
mptcp: decrement subflows counter on failed passive join
Will Deacon <will@kernel.org>
Revert "arm64: syscall: Ensure saved x0 is kept in-sync with tracer updates"
Will Deacon <will@kernel.org>
arm64: syscall: Ensure saved x0 is kept in-sync with tracer updates
Masami Hiramatsu (Google) <mhiramat@kernel.org>
tracing/probes: Prevent out-of-bounds write in __trace_probe_log_err()
Masami Hiramatsu (Google) <mhiramat@kernel.org>
tracing/probes: Fix potential underflow in LEN_OR_ZERO macro
Masami Hiramatsu (Google) <mhiramat@kernel.org>
tracing/probes: Avoid temporary buffer truncation in trace_probe_match_command_args()
Masami Hiramatsu (Google) <mhiramat@kernel.org>
tracing/eprobe: Fix exact system name matching in eprobe_dyn_event_match()
deepakraog <gaikwad.dcg@gmail.com>
tracing: Fix resource leak on mmiotrace trace_pipe close
Steven Rostedt <rostedt@goodmis.org>
tracing: Fix mmiotrace possible NULL dereferencing of hiter->dev
Xu Rao <raoxu@uniontech.com>
misc: nsm: pin the module while the device is open
Runyu Xiao <runyu.xiao@seu.edu.cn>
misc: nsm: only unlock nsm_dev on post-lock error paths
Guangshuo Li <lgs201920130244@gmail.com>
intel_th: fix MSC output device reference leak
Alexander Usyskin <alexander.usyskin@intel.com>
mei: bus: access mei_device under device_lock on cleanup
Jiangshan Yi <yijiangshan@kylinos.cn>
serial: 8250_mid: Fix NULL function pointer dereference on DNV/ICX-D/SNR platforms
Hugo Villeneuve <hvilleneuve@dimonoff.com>
serial: sc16is7xx: implement gpio get_direction() callback
Ben Hutchings <benh@debian.org>
uio_hv_generic: Bind to FCopy device by default
Ian Abbott <abbotti@mev.co.uk>
comedi: comedi_parport: deal with premature interrupt
Nathan Chancellor <nathan@kernel.org>
x86/boot/compressed: Disable jump tables
Tze Yee Ng <tze.yee.ng@altera.com>
firmware: stratix10-svc: fix memory leaks and list corruption bugs
Xu Rao <raoxu@uniontech.com>
cdrom: fix stack out-of-bounds read in CDROMVOLCTRL
Rong Bao <rong.bao@csmantle.top>
LoongArch: Retrieve CPU package ID from PPTT when available
Kanglong Wang <wangkanglong@loongson.cn>
LoongArch: Move jump_label_init() before parse_early_param()
Haoran Jiang <jianghaoran@kylinos.cn>
LoongArch: Fix oops during single-step debugging
Miguel Ojeda <ojeda@kernel.org>
objtool/rust: add one more `noreturn` Rust function for Rust 1.99.0
Alexandre Courbot <acourbot@nvidia.com>
rust: allow `clippy::unwrap_or_default` globally
Zixing Liu <liushuyu@aosc.io>
platform/loongarch: laptop: Explicitly reset bl_powered state when suspend
Christian Brauner <brauner@kernel.org>
binfmt_misc: set have_execfd only once the interpreter is opened
Christian Brauner <brauner@kernel.org>
exec: fix unsigned loop counter wrap in transfer_args_to_stack()
Chengfeng Ye <nicoyip.dev@gmail.com>
Bluetooth: RFCOMM: Fix session UAF in set_termios
Chengfeng Ye <nicoyip.dev@gmail.com>
Bluetooth: hci_sync: Protect UUID list traversal
MinJea Kim <qndkdrnl@gmail.com>
staging: rtl8723bs: fix inverted HT40 secondary channel offset
Moksh Panicker <mokshpanicker.7@gmail.com>
staging: rtl8723bs: fix OOB reads in rtw_get_wps_ie()
Fan Wu <fanwu01@zju.edu.cn>
wifi: brcmfmac: make release_scratchbuffers idempotent
Devin Wittmayer <lucid_duck@justthetip.ca>
wifi: mt76: mt7925: drop TXRX_NOTIFY on non-mmio buses
Devin Wittmayer <lucid_duck@justthetip.ca>
wifi: mt76: mt7921: drop TXRX_NOTIFY on non-mmio buses
Devin Wittmayer <lucid_duck@justthetip.ca>
wifi: mt76: mt7615: drop TXRX_NOTIFY on non-mmio buses
Huihui Huang <hhhuang@smu.edu.sg>
wifi: wilc1000: validate assoc response length before subtracting header
Doruk Tan Ozturk <doruk@0sec.ai>
wifi: mwifiex: fix NULL dereference when the AP has HT-cap but no HT-oper
Tristan Madani <tristan@talencesecurity.com>
wifi: ath6kl: fix OOB access from firmware ADDBA window size
Norbert Szetei <norbert@doyensec.com>
ALSA: timer: don't re-enter an instance callback that is still running
Norbert Szetei <norbert@doyensec.com>
ALSA: timer: drain a slave's callback before its master detaches it
Norbert Szetei <norbert@doyensec.com>
ALSA: seq: close a re-opened queue timer in the destructor
Johan Hovold <johan@kernel.org>
media: vpif_capture: fix OF node reference imbalance
Guangshuo Li <lgs201920130244@gmail.com>
media: vivid: fix cleanup bugs in vivid_init()
Hans Verkuil <hverkuil+cisco@kernel.org>
media: vivid: check for vb2_is_busy() when toggling caps
Hans Verkuil <hverkuil+cisco@kernel.org>
media: vivid: add vivid_update_reduced_fps()
Guangshuo Li <lgs201920130244@gmail.com>
media: vimc: fix reference leak on failed device registration
Guangshuo Li <lgs201920130244@gmail.com>
media: vidtv: fix reference leak on failed device registration
Zile Xiong <xiongzile99@gmail.com>
media: vb2: use ssize_t for vb2_read/vb2_write
Sakari Ailus <sakari.ailus@linux.intel.com>
media: v4l2-subdev: Fail {enable,disable}_streams and s_streaming nicely
Mirela Rabulea <mirela.rabulea@nxp.com>
media: v4l2-fwnode: Fix subdev owner overwritten in v4l2_async_register_subdev_sensor()
Pengpeng Hou <pengpeng@iscas.ac.cn>
media: v4l2-ctrls: validate HEVC active reference counts
Sergey Shtylyov <s.shtylyov@auroraos.dev>
media: v4l2-ctrls-request: add NULL check in v4l2_ctrl_request_complete()
Myeonghun Pak <mhun512@gmail.com>
media: ti: vpe: unwind v4l2 device registration on probe error
Hungyu Lin <dennylin0707@gmail.com>
media: tegra-video: vi: fix invalid u32 return value in format lookup
Valery Borovsky <vebohr@gmail.com>
media: sun4i-csi: Return queued buffers on start_streaming() failure
Myeonghun Pak <mhun512@gmail.com>
media: stm32: dcmi: unregister notifier on probe failure
Ma Ke <make24@iscas.ac.cn>
media: saa7134: Fix a possible memory leak in saa7134_video_init1
Valery Borovsky <vebohr@gmail.com>
media: rtl2832_sdr: Return queued buffers on start_streaming() failure
Deepanshu Kartikey <kartikey406@gmail.com>
media: rtl2832: fix use-after-free in rtl2832_remove()
Myeonghun Pak <mhun512@gmail.com>
media: radio-si476x: Unregister v4l2_device on probe failure
Bryan O'Donoghue <bryan.odonoghue@linaro.org>
media: qcom: camss: Fix RDI streaming for CSID GEN2
Valery Borovsky <vebohr@gmail.com>
media: pwc: Return queued buffers on start_streaming() failure
Valery Borovsky <vebohr@gmail.com>
media: pwc: Drain fill_buf on start_streaming() failure
Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
media: pci: dm1105: Free allocated workqueue
Guoniu Zhou <guoniu.zhou@nxp.com>
media: nxp: imx8-isi: Fix scale factor calculation for hardware rounding
Guoniu Zhou <guoniu.zhou@nxp.com>
media: nxp: imx8-isi: Fix potential out-of-bounds issues
Xiaolei Wang <xiaolei.wang@windriver.com>
media: nxp: imx8-isi: Fix missing v4l2_subdev_cleanup() in pipe init error path
Xiaolei Wang <xiaolei.wang@windriver.com>
media: nxp: imx8-isi: Clean up already-initialized pipes on probe failure
Xiaolei Wang <xiaolei.wang@windriver.com>
media: nxp: imx8-isi: Add missing v4l2_subdev_cleanup() in crossbar and pipe
David Carlier <devnexen@gmail.com>
media: nuvoton: npcm-video: fix memory leaks in probe and remove
David Carlier <devnexen@gmail.com>
media: nuvoton: npcm-video: fix error handling in npcm_video_init()
Valery Borovsky <vebohr@gmail.com>
media: msi2500: Return queued buffers on start_streaming() failure
Anand Moon <linux.amoon@gmail.com>
media: meson: vdec: Fix memory leak in error path of vdec_open
Guangshuo Li <lgs201920130244@gmail.com>
media: marvell-cam: fix missing pci_disable_device() on remove
Marco Nenciarini <mnencia@kcore.it>
media: intel/ipu6: Improve DWC PHY HSFREQRANGE band selection for overlapping ranges
Martin Hecht <mhecht73@gmail.com>
media: i2c: alvium: fix critical pointer access in alvium_ctrl_init
Wang Jun <1742789905@qq.com>
media: cx23885: add ioremap return check and cleanup
Johan Hovold <johan@kernel.org>
media: cx231xx: fix devres lifetime
Brandon Brnich <b-brnich@ti.com>
media: chips-media: wave5: Move src_buf Removal to finish_encode
Pengpeng Hou <pengpeng@iscas.ac.cn>
media: cedrus: skip invalid H.264 reference list entries
Samuel Holland <samuel@sholland.org>
media: cedrus: Fix missing cleanup in error path
Myeonghun Pak <mhun512@gmail.com>
media: cedrus: clean up media device on probe failure
Myeonghun Pak <mhun512@gmail.com>
media: cec: seco: unregister adapter on IR probe failure
David Carlier <devnexen@gmail.com>
media: aspeed: fix missing of_reserved_mem_device_release() on probe failure
Valery Borovsky <vebohr@gmail.com>
media: airspy: Return queued buffers on start_streaming() failure
Linmao Li <lilinmao@kylinos.cn>
drm/vc4: Prevent shader BO mappings from becoming writable
Ian Forbes <ian.forbes@broadcom.com>
drm/vmwgfx: Validate vmw_surface_metadata::array_size
Zhu Lingshan <lingshan.zhu@amd.com>
drm/amdgpu: fix bo->pin leaking in amdgpu_bo_create_reserved
Mario Limonciello <mario.limonciello@amd.com>
drm/amdgpu: Disable PCIe dynamic speed switching on Ryzen Pinnacle Ridge
Andriy Korud <a.korud@gmail.com>
drm/amd/display: dce100: skip non-DP stream encoders for DP MST
WenTao Liang <vulab@iscas.ac.cn>
drm/amd/display: set new_stream to NULL after release
Timur Kristóf <timur.kristof@gmail.com>
drm/amd/pm/ci: Don't disable MCLK DPM on Bonaire 0x6658 (R7 260X)
Mario Limonciello <mario.limonciello@amd.com>
drm/amdgpu: Fix VFCT bus number matching with soft filter
Osama Abdelkader <osama.abdelkader@gmail.com>
drm/panthor: return error on truncated firmware
Alex Deucher <alexander.deucher@amd.com>
drm/gfx10: Program DB_RING_CONTROL
Yang Wang <kevinyang.wang@amd.com>
drm/amd/pm: fix smu14 power limit range calculation
Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
drm/i915/gem: Fix NULL deref in I915_CONTEXT_PARAM_SSEU
Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
drm/i915/gem: Do not leak siblings[] on proto context error
Shahyan Soltani <shahyan.soltani@amd.com>
drm/amdgpu: fix lifetime issue of amdgpu_vm_get_task_info_pasid()
Jani Nikula <jani.nikula@intel.com>
drm/i915/bios: range check LFP Data Block panel_type2
Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
drm/i915: Return NULL on error in active_instance
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu/sdma5.0: replace BUG_ON() with WARN_ON()
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu/sdma5.2: replace BUG_ON() with WARN_ON()
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu/sdma6.0: replace BUG_ON() with WARN_ON()
Alex Deucher <alexander.deucher@amd.com>
drm/amdgpu/sdma7.0: replace BUG_ON() with WARN_ON()
Bryam Vargas <hexlabsecurity@proton.me>
drm/virtio: bound EDID block reads to the response buffer
WenTao Liang <vulab@iscas.ac.cn>
drm/amd/display: detect_link_and_local_sink: DP alt mode timeout path leaks prev_sink reference
Thomas Zimmermann <tzimmermann@suse.de>
drm/amd/display: Handle struct drm_plane_state.ignore_damage_clips
Yongqiang Sun <Yongqiang.Sun@amd.com>
drm/amdkfd: fix 32-bit overflow in CWSR total size calculation
David Francis <David.Francis@amd.com>
drm/amdkfd: Check bounds in allocate_event_notification_slot
David Francis <David.Francis@amd.com>
drm/amdkfd: Use kvcalloc to allocate arrays
Icenowy Zheng <zhengxingda@iscas.ac.cn>
drm/imagination: acquire vm_ctx->lock before mapping memory to GPU VM
Luigi Santivetti <luigi.santivetti@imgtec.com>
drm/imagination: fix error checking of pvr_vm_context_lookup()
Shuvam Pandey <shuvampandey1@gmail.com>
drm/imagination: Fix user array stride in pvr_set_uobj_array()
Brajesh Gupta <brajesh.gupta@imgtec.com>
drm/imagination: Fix double call to drm_sched_entity_fini()
Matthew Brost <matthew.brost@intel.com>
drm/xe: Fix PTE index in xe_vm_populate_pgtable() for chunked binds
Pavel Ondračka <pavel.ondracka@gmail.com>
drm/radeon: fix r100_copy_blit for large BOs
Wentao Liang <vulab@iscas.ac.cn>
drm/nouveau/acr: fix missing nvkm_done() in error path of nvkm_acr_oneinit()
Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
drm/i915/gem: Add missing nospec on parallel submit slot
Jani Nikula <jani.nikula@intel.com>
drm/displayid: fix Tiled Display Topology ID size
Junrui Luo <moonafterrain@outlook.com>
drm/nouveau: fix reversed error cleanup order in ucopy functions
Mario Limonciello <mario.limonciello@amd.com>
drm/amdgpu: validate CP_GFX_SHADOW chunk size in CS pass1
Timur Kristóf <timur.kristof@gmail.com>
drm/amdgpu: Fix amdgpu_bo_move() when old_mem and new_mem are both GTT
Timur Kristóf <timur.kristof@gmail.com>
drm/amdgpu/uvd: Place VCPU BO only in VRAM for UVD 4.x and older
Timur Kristóf <timur.kristof@gmail.com>
drm/amdgpu/uvd: Fix forcing MSG, FB BOs into VCPU segment when it isn't at 0 (v2)
Ashutosh Desai <ashutoshdesai993@gmail.com>
drm/dp/mst: fix OOB reads on 2-byte fields in sideband reply parsers
Alessio Belle <alessio.belle@imgtec.com>
drm/imagination: Fit paired fragment job in the correct CCCB
Ashutosh Desai <ashutoshdesai993@gmail.com>
drm/dp/mst: fix buffer overflows in sideband chunk accumulation
Ashutosh Desai <ashutoshdesai993@gmail.com>
drm/dp/mst: fix OOB reads in remote DPCD/I2C sideband reply parsers
Vitor Soares <vitor.soares@toradex.com>
drm/bridge: cdns-dsi: Replace deprecated UNIVERSAL_DEV_PM_OPS()
Alessio Belle <alessio.belle@imgtec.com>
drm/imagination: Count paired job fence as dependency in prepare_job()
Sergey Shtylyov <s.shtylyov@auroraos.dev>
drm/rockchip: cdn-dp: add missing check in cdn_dp_config_video()
Biju Das <biju.das.jz@bp.renesas.com>
drm: renesas: rzg2l_mipi_dsi: Increase reset deassertion delay
Chengfeng Ye <nicoyip.dev@gmail.com>
bpf, sockmap: Fix cork use-after-free in tcp_bpf_sendmsg()
Lorenzo Bianconi <lorenzo@kernel.org>
net: airoha: fix ETS channel derivation in airoha_tc_setup_qdisc_ets()
Cen Zhang (Microsoft) <blbllhy@gmail.com>
rds: tcp: unregister sysctl before tearing down listen socket
Marcin Szycik <marcin.szycik@linux.intel.com>
ice: fix LAG recipe to profile association
Vincent Chen <vincent.chen@sifive.com>
ice: allow creating VFs when !CONFIG_ICE_SWITCHDEV
Li RongQing <lirongqing@baidu.com>
net: ipv6: fix dif and sdif mismatch in raw6_icmp_error
Hariprasad Kelam <hkelam@marvell.com>
octeontx2-pf: tc: fix egress ratelimiting
Alexei Lazar <alazar@nvidia.com>
net/mlx5e: Reject unsupported CB Shaper TSA in ETS validation
Alexei Lazar <alazar@nvidia.com>
net/mlx5e: Report zero bandwidth for non-ETS traffic classes
Yael Chemla <ychemla@nvidia.com>
net/mlx5: E-Switch, fix zero num_dest in prio_tag egress vlan rule
Gal Pressman <gal@nvidia.com>
net/mlx5: Fix MCIA register buffer overflow on 32 dword reads
Gal Pressman <gal@nvidia.com>
net/mlx5: Refactor EEPROM query error handling to return status separately
Gal Pressman <gal@nvidia.com>
net/mlx5: Remove newline at the end of a netlink error message
Jiri Pirko <jiri@resnulli.us>
net/mlx5: DPLL, Add clock quality level op implementation
Jiri Pirko <jiri@resnulli.us>
dpll: add clock quality level attribute and op
Aldo Ariel Panzardo <qwe.aldo@gmail.com>
net: qrtr: restrict socket creation to the initial network namespace
Chenguang Zhao <zhaochenguang@kylinos.cn>
hinic: remove unused ethtool RSS user configuration buffers
Eric Dumazet <edumazet@google.com>
ppp: annotate data races in ppp_generic
Qingfang Deng <dqfext@gmail.com>
ppp: enable TX scatter-gather
Qingfang Deng <dqfext@gmail.com>
ppp: convert to percpu netstats
Qingfang Deng <dqfext@gmail.com>
ppp: use IFF_NO_QUEUE in virtual interfaces
Eric Dumazet <edumazet@google.com>
ipv4: icmp: fill flow parameters in icmp_route_lookup decoy lookup
Suman Ghosh <sumang@marvell.com>
octeontx2-vf: set TC flower flag on MCAM entry allocation
Yun Zhou <yun.zhou@windriver.com>
net: gre: fix lltx regression for GRE tunnels with SEQ/CSUM
vadik likholetov <vadikas@gmail.com>
net: stmmac: enable the MAC on link up for all supported speeds
Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@altera.com>
net: stmmac: reset residual action in L3L4 filters on delete
Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@altera.com>
net: stmmac: fix l3l4 filter rejecting unsupported offload requests
José Expósito <jose.exposito@redhat.com>
drm/tests: shmem: Set DMA mask to 64-bit in drm_gem_shmem
Cen Zhang (Microsoft) <blbllhy@gmail.com>
tipc: fix u16 MTU truncation in media and bearer MTU validation
Zhang Yi <yi.zhang@huawei.com>
iomap: correct the range of a partial dirty clear
Harshaka Narayana <harshaka.narayana@broadcom.com>
vmxnet3: fix BUG_ON in vmxnet3_get_hdr_len() for Geneve packets
Qing Luo <luoqing@kylinos.cn>
sctp: auth: verify auth requirement when auth_chunk is NULL
Michael Walle <mwalle@kernel.org>
net: dpaa: fix mode setting
Eric Dumazet <edumazet@google.com>
net: hsr: fix memory leak on slave unregistration by removing synced VLANs
Nikolay Aleksandrov <razor@blackwall.org>
net: bridge: vlan: fix vlan range dumps starting with pvid
Michael Bommarito <michael.bommarito@gmail.com>
amt: make the head writable before rewriting the L2 header
Michael Bommarito <michael.bommarito@gmail.com>
amt: re-read skb header pointers after every pull
Yichong Chen <chenyichong@uniontech.com>
ovl: fix trusted xattr escape prefix matching
Shelley Yang <shelley.yang@infineon.com>
wifi: brcmfmac: fix 802.1X-SHA256 call trace warning
Lorenzo Bianconi <lorenzo@kernel.org>
wifi: mt76: mt7996: fix possible NULL-pointer deref in mt7996_mcu_sta_bfer_eht()
Sean Wang <sean.wang@mediatek.com>
wifi: mt76: mt7925: fix crash in reset link replay
Lorenzo Bianconi <lorenzo@kernel.org>
wifi: mt76: mt7996: check pointer returned by mt76_connac_get_he_phy_cap()
Lorenzo Bianconi <lorenzo@kernel.org>
wifi: mt76: mt7925: fix possible NULL-pointer deref in mt7925_mcu_bss_he_tlv()
Lorenzo Bianconi <lorenzo@kernel.org>
wifi: mt76: connac: fix possible NULL-pointer deref in mt76_connac_mcu_uni_bss_he_tlv()
Ruoyu Wang <ruoyuw560@gmail.com>
wifi: mt76: mt7915: guard HE capability lookups
Guangshuo Li <lgs201920130244@gmail.com>
wifi: mt76: mt7925: guard link STA in decap offload
Helen Koike <koike@igalia.com>
tipc: fix infinite loop in __tipc_nl_compat_dumpit
Xiang Mei (Microsoft) <xmei5@asu.edu>
nexthop: initialize extack in nh_res_bucket_migrate()
Xiang Mei (Microsoft) <xmei5@asu.edu>
gtp: check skb_pull_data() return in gtp1u_send_echo_resp()
Matthieu Baerts (NGI0) <matttbe@kernel.org>
selftests: openvswitch: add config file
Matthieu Baerts (NGI0) <matttbe@kernel.org>
selftests: af_unix: add USER_NS config
Rishikesh Jethwani <rjethwani@purestorage.com>
tls: device: push pending open record on splice EOF
Myeonghun Pak <mhun512@gmail.com>
net: mctp i3c: clean up notifier and buses if driver register fails
Cen Zhang (Microsoft) <blbllhy@gmail.com>
sctp: validate stream count in sctp_process_strreset_inreq()
Nikhil P. Rao <nikhil.rao@amd.com>
pds_core: check for workqueue allocation failure
Nikhil P. Rao <nikhil.rao@amd.com>
pds_core: fix auxiliary device add/del races
Nikhil P. Rao <nikhil.rao@amd.com>
pds_core: order completion reads after the ownership check
Nikhil P. Rao <nikhil.rao@amd.com>
pds_core: yield the CPU while waiting for the adminq to drain
Nikhil P. Rao <nikhil.rao@amd.com>
pds_core: fix use-after-free on workqueue during remove
Nikhil P. Rao <nikhil.rao@amd.com>
pds_core: fix deadlock between reset thread and remove
HanQuan <eilaimemedsnaimel@gmail.com>
sctp: fix auth_chunk_list capacity check in sctp_auth_ep_add_chunkid
Chenguang Zhao <zhaochenguang@kylinos.cn>
net: txgbe: fix FDIR filter leak on remove
Prashanth Kumar KR <PrashanthKumar.K.R@amd.com>
amd-xgbe: fix MAC_AUTO_SW handling in CL37 AN
Nikhil P. Rao <nikhil.rao@amd.com>
pds_core: reject component parameter in legacy firmware update
Andrew Pope <andrew.pope@morsemicro.com>
wifi: mac80211: recalculate TIM when a station enters power save
Li RongQing <lirongqing@baidu.com>
iommu/intel: Fix out-of-bounds memset in dmar_latency_disable()
Pengpeng Hou <pengpeng@iscas.ac.cn>
iommu/amd: Bound the early ACPI HID map
HE WEI (ギカク) <skyexpoc@gmail.com>
wifi: mwifiex: bound uAP association event IEs to the event buffer
Ruoyu Wang <ruoyuw560@gmail.com>
wan: wanxl: Only reset hardware after BAR mapping
Ruoyu Wang <ruoyuw560@gmail.com>
nfp: Check resource mutex allocation
Xiang Mei <xmei5@asu.edu>
wifi: mac80211: tear down new links on vif update error path
Guanghui Feng <guanghuifeng@linux.alibaba.com>
iommu/amd: Wait for completion instead of returning early in iommu_completion_wait()
Guangshuo Li <lgs201920130244@gmail.com>
dpaa2-eth: put MAC endpoint device on disconnect
Guangshuo Li <lgs201920130244@gmail.com>
dpaa2-switch: put MAC endpoint device on disconnect
Zhixing Chen <running910@gmail.com>
gtp: parse extension headers before reading inner protocol
Aldo Ariel Panzardo <qwe.aldo@gmail.com>
rds: drop incoming messages that cross network namespace boundaries
Zhaolong Zhang <zhangzl68@chinatelecom.cn>
bonding: fix devconf_all NULL dereference when IPv6 is disabled
David Lee <david.lee@trailofbits.com>
net/packet: avoid fanout hook re-registration after unregister
Danielle Ratson <danieller@nvidia.com>
netlink: specs: rt-link: convert bridge port flag attributes to u8
Pengpeng Hou <pengpeng@iscas.ac.cn>
Bluetooth: btusb: validate Realtek vendor event length
Daniel Golle <daniel@makrotopia.org>
regulator: mt6358: use regmap helper to read fixed LDO calibration
Pengpeng Hou <pengpeng@iscas.ac.cn>
hwmon: occ: validate poll response sensor blocks
Yichong Chen <chenyichong@uniontech.com>
smb: client: validate DFS referral PathConsumed
Eugene Shalygin <eugene.shalygin@gmail.com>
hwmon: (asus-ec-sensors) add missed handle for ENOMEM
Eugene Shalygin <eugene.shalygin@gmail.com>
hwmon: (asus-ec-sensors) fix EC read intervals
Eugene Shalygin <eugene.shalygin@gmail.com>
hwmon: (asus-ec-sensors) fix looping over banks while reading from EC
Mostafa Saleh <smostafa@google.com>
drivers/virt: pkvm: Fix end calculation in mmio_guard_ioremap_hook()
Diego Fernando Mancera Gomez <diegomancera.dev@gmail.com>
usb: atm: ueagle-atm: reject descriptors that confuse probe and disconnect
Shahar Tzarfati <shahar.tzarfati@intel.com>
wifi: iwlwifi: mvm: fix read in wake packet notification handler
Pagadala Yesu Anjaneyulu <pagadala.yesu.anjaneyulu@intel.com>
wifi: iwlwifi: mvm: validate SAR GEO response payload size
Richard Fitzgerald <rf@opensource.cirrus.com>
ASoC: cs35l56: Use complete_all() to signal init_completion
Richard Fitzgerald <rf@opensource.cirrus.com>
ASoC: cs35l56: Fix potential probe() deadlock
Richard Fitzgerald <rf@opensource.cirrus.com>
ASoC: cs35l56: Don't use devres to unregister component
Shengjiu Wang <shengjiu.wang@nxp.com>
ASoC: bt-sco: fix duplicate DAPM widget names for wideband DAI
Guangshuo Li <lgs201920130244@gmail.com>
ALSA: hda: cs35l41: validate and free ACPI mute object
Denis Arefev <arefev@swemel.ru>
ALSA: hda: cs35l41: Fix NULL pointer dereference in cs35l41_get_acpi_mute_state()
Pengpeng Hou <pengpeng@iscas.ac.cn>
ASoC: tas2781: bound firmware description string parsing
Guanghui Yang <3497809730@qq.com>
btrfs: free mapping node on duplicate reloc root insert
Leo Martins <loemra.dev@gmail.com>
btrfs: don't propagate EXTENT_FLAG_LOGGING to split extent maps
You-Kai Zheng <ykzheng@synology.com>
btrfs: declare btrfs_ioctl_search_args_v2::buf as __u8
Tristan Madani <tristan@talencesecurity.com>
wifi: carl9170: fix buffer overflow in rx_stream failover path
Tristan Madani <tristan@talencesecurity.com>
wifi: carl9170: fix OOB read from off-by-two in TX status handler
Tristan Madani <tristan@talencesecurity.com>
wifi: carl9170: bound memcpy length in cmd callback to prevent OOB read
Tristan Madani <tristan@talencesecurity.com>
wifi: ath6kl: fix OOB read from firmware IE lengths in connect event
Tristan Madani <tristan@talencesecurity.com>
wifi: ath6kl: fix OOB read from firmware num_msg in TX complete handler
Ruoyu Wang <ruoyuw560@gmail.com>
firewire: net: Fix fragmented datagram reassembly
Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
wifi: ath12k: Flush the posted write after writing to PCIE_SOC_GLOBAL_RESET
Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
wifi: ath11k: Flush the posted write after writing to PCIE_SOC_GLOBAL_RESET
Dmitry Morgun <d.morgun@ispras.ru>
wifi: ath11k: fix potential buffer underflow in ath11k_hal_rx_msdu_list_get()
Tzung-Bi Shih <tzungbi@kernel.org>
watchdog: pretimeout: Fix UAF in watchdog_unregister_governor()
Guenter Roeck <linux@roeck-us.net>
hwmon: (nzxt-kraken3) Stop device IO before calling hid_hw_stop
Guenter Roeck <linux@roeck-us.net>
hwmon: (nzxt-smart2) Stop device IO before calling hid_hw_stop
Guenter Roeck <linux@roeck-us.net>
hwmon: (gigabyte_waterforce) Stop device IO before calling hid_hw_stop
Guenter Roeck <linux@roeck-us.net>
hwmon: (corsair-cpro) Stop device IO before calling hid_hw_stop
Edward Adam Davis <eadavis@qq.com>
hwmon: (corsair-psu) Stop device IO before calling hid_hw_stop
Gaole Zhang <gaole.zhang@oss.qualcomm.com>
wifi: ath11k: fix NULL pointer dereference in ath11k_hal_srng_access_begin
Cheng Yongkang <teel4res@gmail.com>
wifi: ath9k: hif_usb: don't dereference hif_dev after re-arming firmware request
Xincheng Zhang <zhangxincheng@ultrarisc.com>
usb: xhci-pci: Limit VIA VL805 DMA addressing to 36 bits
Xie Bo <xb@ultrarisc.com>
RISC-V: KVM: Serialize virtual interrupt pending state updates
Sasha Levin <sashal@kernel.org>
Revert "drm/amd/display: Add missing kdoc for ALLM parameters"
Doruk Tan Ozturk <doruk@0sec.ai>
crypto: rsa-pkcs1pad: Don't WARN on an empty digest
Chukun Pan <amadeus@jmu.edu.cn>
USB: serial: option: add TDTECH MT5710-CN
Johan Hovold <johan@kernel.org>
USB: serial: keyspan_pda: fix data loss on receive throttling
Sunho Park <shpark061104@gmail.com>
USB: serial: io_edgeport: cap received transmit credits
Tim Pambor <timpambor@gmail.com>
USB: serial: ftdi_sio: add support for E+H FXA291
Muhammad Bilal <meatuni001@gmail.com>
usb: gadget: uvc: clamp SEND_RESPONSE length to the response buffer
Fan Wu <fanwu01@zju.edu.cn>
usb: gadget: udc: bdc: free IRQ and drain func_wake_notify before teardown
Sonali Pradhan <sonalipradhan@google.com>
usb: gadget: f_ncm: validate datagram bounds in ncm_unwrap_ntb()
Johan Hovold <johan@kernel.org>
USB: gadget: fsl-udc: fix device name leak on probe failure
Johan Hovold <johan@kernel.org>
USB: gadget: snps-udc: fix device name leak on probe failure
Melbin K Mathew <mlbnkm1@gmail.com>
usb: gadget: printer: fix infinite loop in printer_read()
Fan Wu <fanwu01@zju.edu.cn>
usb: gadget: f_midi: cancel pending IN work before freeing the midi object
Jinchao Wang <wangjinchao600@gmail.com>
usb: gadget: dummy_hcd: prevent fifo_req reuse during giveback
Xu Yang <xu.yang_2@nxp.com>
usb: chipidea: fix usage_count leak when autosuspend_delay is negative
Huang Wei <huangwei@kylinos.cn>
USB: storage: add NO_ATA_1X quirk for Longmai USB Key
Chia-Lin Kao (AceLan) <acelan.kao@canonical.com>
usb: core: port: Deattach Type-C connector on component unbind
Huihui Huang <hhhuang@smu.edu.sg>
wifi: at76c50x-usb: avoid length underflow in at76_guess_freq()
Griffin Kroah-Hartman <griffin@kroah.com>
usb: core: sysfs: add lock to bos_descriptors_read()
Weiming Shi <bestswngs@gmail.com>
mpls: fix NULL deref in mpls_valid_fib_dump_req() on CONFIG_INET=n
Xin Long <lucien.xin@gmail.com>
sctp: fix auth_hmacs array size in struct sctp_cookie
Jamal Hadi Salim <jhs@mojatatu.com>
net/sched: act_tunnel_key: Defer dst_release to RCU callback
Emre Cecanpunar <emreleno@gmail.com>
drm/i915/selftests: Fix GT PM sort comparators
Xiang Mei (Microsoft) <xmei5@asu.edu>
ksmbd: validate compound request size before reading StructureSize2
Qihang <q.h.hack.winter@gmail.com>
ksmbd: pin conn during async oplock break notification
ZhangGuoDong <zhangguodong@kylinos.cn>
smb: move some duplicate definitions to common/cifsglob.h
Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
drm/xe/wopcm: fix WOPCM size for LNL+
Shuhao Fu <sfual@cse.ust.hk>
can: j1939: fix lockless local-destination check
Mark Harris <mark.hsj@gmail.com>
riscv: hwprobe: Avoid uninitialized read in hwprobe_get_cpus()
Vasily Gorbik <gor@linux.ibm.com>
s390/checksum: Fix csum_partial() without vector facility
Michal Luczaj <mhal@rbox.co>
bpf, sockmap: Reject unhashed UDP sockets on sockmap update
Shrikanth Hegde <sshegde@linux.ibm.com>
powerpc/vtime: Initialize starttime at boot for native accounting
Frederic Weisbecker <frederic@kernel.org>
powerpc/time: Prepare to stop elapsing in dynticks-idle
Rosen Penev <rosenp@gmail.com>
powerpc/85xx: Add fsl,ifc to common device ids
Pengpeng Hou <pengpeng@iscas.ac.cn>
drm/i915/gt: use correct selftest config symbol
Huiwen He <hehuiwen@kylinos.cn>
smb/client: handle overlapping allocated ranges in fallocate
Ruoyu Wang <ruoyuw560@gmail.com>
Bluetooth: hci_qca: Clear memdump state on invalid dump size
Pauli Virtanen <pav@iki.fi>
Bluetooth: mgmt: hold reference for hci_conn in mgmt_pending_cmds
Pauli Virtanen <pav@iki.fi>
Bluetooth: mgmt: fix locking in unpair_device/disconnect_sync
Cen Zhang <zzzccc427@gmail.com>
Bluetooth: MGMT: revalidate LOAD_CONN_PARAM queued update
Xiang Mei <xmei5@asu.edu>
Bluetooth: qca: fix NVM tag length underflow in TLV parser
Takashi Iwai <tiwai@suse.de>
ALSA: usb-audio: Skip DSD quirk for Musical Fidelity M6s DAC
Karol Wachowski <karol.wachowski@linux.intel.com>
accel/ivpu: Fix wrong register read in LNL failure diagnostics
Rosen Penev <rosenp@gmail.com>
ata: sata_dwc_460ex: fix infinite loop in NCQ tag completion bit-scanning
Rosen Penev <rosenp@gmail.com>
ata: sata_dwc_460ex: fix clear_interrupt_bit() clearing all pending interrupts
Rosen Penev <rosenp@gmail.com>
ata: sata_dwc_460ex: use platform_get_irq()
Rosen Penev <rosenp@gmail.com>
ata: sata_dwc_460ex: enable SATA interrupts only after IRQ handler is registered
David Jeffery <djeffery@redhat.com>
scsi: core: wake eh reliably when using scsi_schedule_eh
Robert Mader <robert.mader@collabora.com>
udmabuf: Ensure to perform cache synchronisation in begin_cpu_udmabuf()
Bryam Vargas <hexlabsecurity@proton.me>
net/iucv: take a reference on the socket found in afiucv_hs_rcv()
Weiming Shi <bestswngs@gmail.com>
ipv4: fib: free fib_alias with kfree_rcu() on insert error path
Norbert Szetei <norbert@doyensec.com>
ppp: defer channel free to an RCU grace period to fix pppol2tp RX UAF
Rafael J. Wysocki <rafael.j.wysocki@intel.com>
cpufreq: Make cpufreq_update_pressure() fall back to cpuinfo.max_freq
Pushpendra Singh <pushpendra.singh@oss.qualcomm.com>
firmware: arm_scmi: Rate-limit queue-full warnings in IRQ context
Uday Khare <udaykhare77@gmail.com>
ASoC: tas2562: fix deprecated 'shut-down' GPIO always cleared after lookup
Charles Keepax <ckeepax@opensource.cirrus.com>
ASoC: cs42l43: Correct report for forced microphone jack
Vijendar Mukunda <Vijendar.Mukunda@amd.com>
ASoC: amd: ps: fix wrong ACP version string in pci_request_regions()
Christian Hewitt <christianshewitt@gmail.com>
ASoC: meson: aiu: fifo-spdif: soft reset the S/PDIF datapath on start/stop
HE WEI (ギカク) <skyexpoc@gmail.com>
wifi: cfg80211: bound element ID read when checking non-inheritance
Runyu Xiao <runyu.xiao@seu.edu.cn>
wifi: brcmfmac: initialize SDIO data work before cleanup
Cen Zhang <zzzccc427@gmail.com>
wifi: mac80211: free AP_VLAN bc_buf SKBs outside IRQ lock
Zhao Li <enderaoelyther@gmail.com>
wifi: cfg80211: reject unsupported PMSR FTM location requests
Zhao Li <enderaoelyther@gmail.com>
wifi: cfg80211: validate PMSR FTM preamble range
Zhao Li <enderaoelyther@gmail.com>
wifi: cfg80211: validate PMSR measurement type data
Zhao Li <enderaoelyther@gmail.com>
wifi: nl80211: validate nested MBSSID IE blobs
Zhao Li <enderaoelyther@gmail.com>
wifi: cfg80211: derive S1G beacon TSF from S1G fields
Zhao Li <enderaoelyther@gmail.com>
wifi: nl80211: free RNR data on MBSSID mismatch
Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
wifi: cfg80211: convert pmsr_free_wk to wiphy_work to fix deadlock
Johannes Berg <johannes.berg@intel.com>
wifi: cfg80211: define and use wiphy guard
Felix Fietkau <nbd@nbd.name>
wifi: cfg80211: pass net_device to .set_monitor_channel
Xiang Mei <xmei5@asu.edu>
wifi: p54: validate RX frame length in p54_rx_eeprom_readback()
Dawei Feng <dawei.feng@seu.edu.cn>
wifi: libertas: fix memory leak in helper_firmware_cb()
Xiang Mei <xmei5@asu.edu>
wifi: mac80211: fix fils_discovery double free on alloc failure
Xiang Mei <xmei5@asu.edu>
wifi: mac80211: fix unsol_bcast_probe_resp double free on alloc failure
Bryam Vargas <hexlabsecurity@proton.me>
wifi: mac80211_hwsim: clamp virtio RX length before skb_put
Abdun Nihaal <nihaal@cse.iitm.ac.in>
wifi: ipw2100: fix potential memory leak in ipw2100_pci_init_one()
Cen Zhang <zzzccc427@gmail.com>
wifi: cfg80211: cancel sched scan results work on unregister
Xiang Mei (Microsoft) <xmei5@asu.edu>
xfrm: policy: preallocate inexact bins before xfrm_hash_rebuild reinsert
Xiang Mei (Microsoft) <xmei5@asu.edu>
xfrm6: clear dst.dev on error to avoid double netdev_put in xfrm6_fill_dst()
Aleksandrova Alyona <aga@itb.spb.ru>
RDMA/irdma: Prevent overflows in memory contiguity checks
Malaya Kumar Rout <malayarout91@gmail.com>
selftests/alsa: Fix memory leak in find_controls error path
Xue Lei <Xue.Lei@windriver.com>
mtd: fix double free and WARN_ON in add_mtd_device() error paths
Ruoyu Wang <ruoyuw560@gmail.com>
RDMA/siw: publish QP after initialization
Danila Chernetsov <listdansp@mail.ru>
RDMA/hns: Fix potential integer overflow in mhop hem cleanup
Ruoyu Wang <ruoyuw560@gmail.com>
RDMA/erdma: initialize ret for empty receive WR lists
Jacob Moroni <jmoroni@google.com>
RDMA/irdma: Prevent rereg_mr for non-mem regions
Jacob Moroni <jmoroni@google.com>
RDMA/umem: Add pinned revocable dmabuf import interface
Or Gerlitz <ogerlitz@ddn.com>
RDMA/cma: Fix hardware address comparison length in netevent callback
Unnathi Chalicheemala <unnathi.chalicheemala@oss.qualcomm.com>
firmware: arm_ffa: Fix NULL dereference in ffa_partition_info_get()
Filipe Manana <fdmanana@suse.com>
btrfs: fix root leak if its reloc root is unexpected in merge_reloc_roots()
Xiang Mei <xmei5@asu.edu>
btrfs: reject free space cache with more entries than pages
Pengpeng Hou <pengpeng@iscas.ac.cn>
mtd: nand: mtk-ecc: stop on ECC idle timeouts
Pengpeng Hou <pengpeng@iscas.ac.cn>
mtd: mtdswap: remove debugfs stats file on teardown
Michael Bommarito <michael.bommarito@gmail.com>
IB/mad: Drop unmatched RMPP responses before reassembly
Seth Forshee <sforshee@nvidia.com>
firmware: arm_ffa: Respect firmware advertised RX/TX buffer size limits
Sumit Gupta <sumitg@nvidia.com>
arm64: tegra: Fix CPU compatible string to cortex-a78ae on Tegra234
Harshal Dev <harshal.dev@oss.qualcomm.com>
soc: qcom: ice: Allow explicit votes on 'iface' clock for ICE
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: ims-pcu - fix logic error in packet reset
Seungjin Bae <eeodqql09@gmail.com>
Input: ims-pcu - fix heap-buffer-overflow in ims_pcu_process_data()
Chuck Lever <chuck.lever@oracle.com>
xprtrdma: Clear receive-side ownership pointers on release
Mikko Perttunen <mperttunen@nvidia.com>
crypto: tegra - Don't touch bo refcount in host1x bo pin/unpin
Mikko Perttunen <mperttunen@nvidia.com>
gpu: host1x: Fix use-after-free in host1x_bo_clear_cached_mappings
Sasha Levin <sashal@kernel.org>
Revert "arm64: dts: ti: k3-am62a7-sk: Add bootph-all tag to vqmmc"
Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
dmaengine: sh: rz-dmac: Move interrupt request after everything is set up
Oliver Hartkopp <socketcan@hartkopp.net>
can: isotp: serialize TX state transitions under so->rx_lock
Oliver Hartkopp <socketcan@hartkopp.net>
can: isotp: fix use-after-free race with concurrent NETDEV_UNREGISTER
Oliver Hartkopp <socketcan@hartkopp.net>
can: bcm: track a single source interface for ANYDEV timeout/throttle ops
Oliver Hartkopp <socketcan@hartkopp.net>
can: bcm: fix data race on rx_stamp/rx_ifindex in bcm_rx_handler()
Oliver Hartkopp <socketcan@hartkopp.net>
can: bcm: fix stale rx/tx ops after device removal
Oliver Hartkopp <socketcan@hartkopp.net>
can: bcm: add missing device refcount for CAN filter removal
Oliver Hartkopp <socketcan@hartkopp.net>
can: bcm: validate frame length in bcm_rx_setup() for RTR replies
Oliver Hartkopp <socketcan@hartkopp.net>
can: bcm: extend bcm_tx_lock usage for data and timer updates
Oliver Hartkopp <socketcan@hartkopp.net>
can: bcm: fix CAN frame rx/tx statistics
Oliver Hartkopp <socketcan@hartkopp.net>
can: bcm: add locking when updating filter and timer values
Phil Rosenthal <phil@phil.gs>
KVM: x86/mmu: Fix use-after-free on vendor module reload
Hyunwoo Kim <imv4bel@gmail.com>
KVM: nVMX: Hide shadow VMCS right after VMCLEAR
Venkatesh Srinivas <venkateshs@chromium.org>
KVM: x86: Only reset TSC Deadline Timer in apic_timer_expired on KVM_RUN
Sean Christopherson <seanjc@google.com>
KVM: x86: Check for invalid/obsolete root *after* making MMU pages available
Heiko Carstens <hca@linux.ibm.com>
seqlock: Allow UBSAN_ALIGNMENT to fail optimizing
Peter Zijlstra <peterz@infradead.org>
seqlock: Allow KASAN to fail optimizing
Peter Zijlstra <peterz@infradead.org>
seqlock: Cure some more scoped_seqlock() optimization fails
Kiryl Shutsemau <kas@kernel.org>
fs/proc/task_mmu: fix make_uffd_wp_huge_pte() prot-update race
Ryosuke Yasuoka <ryasuoka@redhat.com>
drm/virtio: fix deadlock in display_info_cb by removing hotplug from dequeue worker
Brian Witte <brianwitte@mailfence.com>
netfilter: nf_tables: revert commit_mutex usage in reset path
Brian Witte <brianwitte@mailfence.com>
netfilter: nft_quota: use atomic64_xchg for reset
Brian Witte <brianwitte@mailfence.com>
netfilter: nft_counter: serialize reset with spinlock
Daniel Borkmann <daniel@iogearbox.net>
selftests/bpf: Add tests for ld_{abs,ind} failure path in subprogs
Daniel Borkmann <daniel@iogearbox.net>
bpf: Fix ld_{abs,ind} failure path analysis in subprogs
Wayen Yan <win847@gmail.com>
net: airoha: Fix skb->priority underflow in airoha_dev_select_queue()
Lorenzo Bianconi <lorenzo@kernel.org>
net: airoha: Move airoha_eth driver in a dedicated folder
Guixiong Wei <weiguixiong@bytedance.com>
platform/x86/intel-uncore-freq: Fix current_freq_khz after CPU hotplug
-------------
Diffstat:
Documentation/gpu/drm-mm.rst | 10 +-
Documentation/netlink/specs/dpll.yaml | 41 +
Documentation/netlink/specs/rt_link.yaml | 40 +-
Makefile | 9 +-
arch/arm64/boot/dts/nvidia/tegra234.dtsi | 24 +-
arch/arm64/boot/dts/qcom/sc7180.dtsi | 4 +-
arch/arm64/boot/dts/qcom/sc7280.dtsi | 8 +-
arch/arm64/boot/dts/qcom/sc8180x.dtsi | 12 +-
arch/arm64/boot/dts/qcom/sc8280xp.dtsi | 32 +-
arch/arm64/boot/dts/qcom/sm6350.dtsi | 4 +-
arch/arm64/boot/dts/qcom/sm8150.dtsi | 4 +-
arch/arm64/boot/dts/qcom/sm8250.dtsi | 4 +-
arch/arm64/boot/dts/qcom/sm8350.dtsi | 4 +-
arch/arm64/boot/dts/qcom/sm8450.dtsi | 4 +-
arch/arm64/boot/dts/qcom/x1e80100.dtsi | 77 +-
arch/arm64/boot/dts/ti/k3-am62a7-sk.dts | 2 -
arch/arm64/mm/mmu.c | 5 +-
arch/loongarch/kernel/acpi.c | 27 +-
arch/loongarch/kernel/kgdb.c | 3 +-
arch/loongarch/kernel/setup.c | 3 +-
arch/loongarch/kernel/smp.c | 4 +-
arch/loongarch/mm/init.c | 5 +-
arch/powerpc/kernel/time.c | 43 +
arch/powerpc/mm/mem.c | 5 +-
arch/powerpc/platforms/85xx/common.c | 2 +
arch/riscv/include/asm/kvm_host.h | 10 +-
arch/riscv/kernel/sys_hwprobe.c | 1 +
arch/riscv/kvm/aia.c | 34 +-
arch/riscv/kvm/vcpu.c | 69 +-
arch/riscv/kvm/vcpu_onereg.c | 8 +-
arch/riscv/mm/init.c | 5 +-
arch/s390/lib/csum-partial.c | 2 +-
arch/s390/mm/init.c | 5 +-
arch/x86/boot/compressed/Makefile | 1 +
arch/x86/kernel/cpu/resctrl/rdtgroup.c | 12 +-
arch/x86/kvm/lapic.c | 2 +-
arch/x86/kvm/mmu/mmu.c | 11 +-
arch/x86/kvm/mmu/paging_tmpl.h | 10 +-
arch/x86/kvm/svm/svm.c | 7 +-
arch/x86/kvm/vmx/nested.c | 11 +-
arch/x86/mm/init_64.c | 5 +-
block/genhd.c | 42 +-
crypto/rsa-pkcs1pad.c | 2 +-
drivers/accel/ivpu/ivpu_hw_btrs.c | 2 +-
drivers/ata/libata-core.c | 18 +
drivers/ata/libata-scsi.c | 2 -
drivers/ata/libata.h | 9 +
drivers/ata/sata_dwc_460ex.c | 38 +-
drivers/block/rbd.c | 7 +-
drivers/bluetooth/btqca.c | 2 +-
drivers/bluetooth/btusb.c | 4 +-
drivers/bluetooth/hci_qca.c | 4 +
drivers/cdrom/cdrom.c | 1 +
drivers/char/ipmi/ipmi_msghandler.c | 8 +
drivers/comedi/drivers/comedi_parport.c | 13 +-
drivers/cpufreq/cpufreq.c | 3 +
drivers/crypto/tegra/tegra-se-main.c | 3 +-
drivers/dma-buf/udmabuf.c | 9 +-
drivers/dma/dw-edma/dw-edma-pcie.c | 63 +-
drivers/dma/sh/rz-dmac.c | 96 +-
drivers/dpll/dpll_netlink.c | 24 +
drivers/firewire/net.c | 37 +-
drivers/firmware/arm_ffa/driver.c | 29 +-
drivers/firmware/arm_scmi/notify.c | 6 +-
drivers/firmware/stratix10-svc.c | 10 +-
drivers/firmware/xilinx/zynqmp.c | 1 +
drivers/fpga/dfl-afu-main.c | 3 +
drivers/gpio/gpio-mt7621.c | 2 +
drivers/gpu/Kconfig | 13 +
drivers/gpu/Makefile | 4 +-
drivers/gpu/buddy.c | 1347 ++++++++++++++++++++
drivers/gpu/drm/Kconfig | 6 +-
drivers/gpu/drm/Makefile | 1 -
drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c | 2 +
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 45 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 11 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 13 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h | 12 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 54 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 58 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 17 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 25 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 77 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h | 18 +-
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 22 +-
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 13 +-
drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c | 13 +-
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 3 -
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 10 +-
drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c | 11 +-
drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c | 4 +-
drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c | 4 +-
drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 4 +-
drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c | 4 +-
drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c | 4 +-
drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 15 +-
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 12 +-
drivers/gpu/drm/amd/amdkfd/kfd_events.c | 3 +
drivers/gpu/drm/amd/amdkfd/kfd_queue.c | 23 +-
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 11 +-
.../amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c | 9 +-
.../amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 9 +-
.../gpu/drm/amd/display/dc/link/link_detection.c | 5 +-
.../display/dc/resource/dce100/dce100_resource.c | 7 +-
.../amd/display/modules/info_packet/info_packet.c | 2 -
drivers/gpu/drm/amd/pm/amdgpu_pm.c | 26 +-
drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c | 7 +-
.../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 11 +-
.../gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 15 +-
.../gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c | 28 +-
drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 11 +-
drivers/gpu/drm/display/drm_dp_mst_topology.c | 36 +-
drivers/gpu/drm/drm_buddy.c | 1279 +------------------
drivers/gpu/drm/drm_connector.c | 12 +-
drivers/gpu/drm/drm_displayid_internal.h | 2 +-
drivers/gpu/drm/i915/display/intel_bios.c | 36 +-
drivers/gpu/drm/i915/gem/i915_gem_context.c | 25 +-
drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 2 +-
drivers/gpu/drm/i915/gt/intel_engine_user.c | 2 +-
drivers/gpu/drm/i915/gt/selftest_gt_pm.c | 8 +-
drivers/gpu/drm/i915/i915_active.c | 7 +-
drivers/gpu/drm/i915/i915_scatterlist.c | 10 +-
drivers/gpu/drm/i915/i915_ttm_buddy_manager.c | 55 +-
drivers/gpu/drm/i915/i915_ttm_buddy_manager.h | 4 +-
.../gpu/drm/i915/selftests/intel_memory_region.c | 20 +-
drivers/gpu/drm/imagination/pvr_context.c | 22 +-
drivers/gpu/drm/imagination/pvr_drv.c | 13 +-
drivers/gpu/drm/imagination/pvr_queue.c | 65 +-
drivers/gpu/drm/imagination/pvr_queue.h | 2 +-
drivers/gpu/drm/imagination/pvr_vm.c | 2 +
drivers/gpu/drm/nouveau/nouveau_exec.c | 4 +-
drivers/gpu/drm/nouveau/nouveau_uvmm.c | 4 +-
drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c | 1 +
drivers/gpu/drm/panthor/panthor_fw.c | 1 +
drivers/gpu/drm/radeon/r100.c | 13 +-
drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c | 2 +-
drivers/gpu/drm/rockchip/cdn-dp-reg.c | 2 +
drivers/gpu/drm/tests/Makefile | 1 -
drivers/gpu/drm/tests/drm_exec_test.c | 2 -
drivers/gpu/drm/tests/drm_gem_shmem_test.c | 16 +-
drivers/gpu/drm/tests/drm_mm_test.c | 2 -
drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c | 4 +-
drivers/gpu/drm/ttm/tests/ttm_mock_manager.c | 18 +-
drivers/gpu/drm/ttm/tests/ttm_mock_manager.h | 4 +-
drivers/gpu/drm/vc4/vc4_bo.c | 10 +-
drivers/gpu/drm/virtio/virtgpu_kms.c | 5 +-
drivers/gpu/drm/virtio/virtgpu_vq.c | 6 +-
drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 22 +-
drivers/gpu/drm/xe/xe_pt.c | 14 +-
drivers/gpu/drm/xe/xe_res_cursor.h | 34 +-
drivers/gpu/drm/xe/xe_ttm_vram_mgr.c | 73 +-
drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h | 4 +-
drivers/gpu/drm/xe/xe_wopcm.c | 15 +-
drivers/gpu/host1x/bus.c | 4 +-
drivers/gpu/tests/Makefile | 4 +
.../drm_buddy_test.c => tests/gpu_buddy_test.c} | 316 ++---
.../{drm/lib/drm_random.c => tests/gpu_random.c} | 18 +-
.../{drm/lib/drm_random.h => tests/gpu_random.h} | 18 +-
drivers/hwmon/asus-ec-sensors.c | 18 +-
drivers/hwmon/corsair-cpro.c | 1 +
drivers/hwmon/corsair-psu.c | 1 +
drivers/hwmon/gigabyte_waterforce.c | 4 +-
drivers/hwmon/nzxt-kraken3.c | 6 +-
drivers/hwmon/nzxt-smart2.c | 2 +-
drivers/hwmon/occ/common.c | 38 +-
drivers/hwtracing/intel_th/core.c | 10 -
drivers/hwtracing/intel_th/msu.c | 2 +
drivers/i2c/busses/i2c-davinci.c | 4 +-
drivers/i2c/busses/i2c-i801.c | 2 +-
drivers/i2c/busses/i2c-imx.c | 126 +-
drivers/infiniband/core/cma.c | 2 +-
drivers/infiniband/core/mad.c | 30 +
drivers/infiniband/core/umem_dmabuf.c | 61 +
drivers/infiniband/hw/erdma/erdma_qp.c | 2 +-
drivers/infiniband/hw/hns/hns_roce_hem.c | 2 +-
drivers/infiniband/hw/irdma/verbs.c | 7 +-
drivers/infiniband/sw/siw/siw_verbs.c | 44 +-
drivers/input/misc/ims-pcu.c | 32 +-
drivers/iommu/amd/init.c | 6 +
drivers/iommu/amd/iommu.c | 22 +-
drivers/iommu/intel/perf.c | 2 +-
drivers/iommu/intel/svm.c | 2 +-
drivers/iommu/iommufd/fault.c | 12 +-
drivers/md/dm-integrity.c | 2 +-
drivers/md/dm.c | 11 +-
drivers/media/cec/platform/seco/seco-cec.c | 6 +-
drivers/media/common/videobuf2/videobuf2-core.c | 12 +-
drivers/media/dvb-frontends/rtl2832.c | 4 +-
drivers/media/dvb-frontends/rtl2832_sdr.c | 19 +-
drivers/media/i2c/alvium-csi2.c | 21 +-
drivers/media/pci/cx23885/cx23885-core.c | 14 +-
drivers/media/pci/dm1105/dm1105.c | 1 +
drivers/media/pci/intel/ipu6/ipu6-isys-dwc-phy.c | 24 +-
drivers/media/pci/saa7134/saa7134-video.c | 25 +-
drivers/media/platform/aspeed/aspeed-video.c | 1 +
.../platform/chips-media/wave5/wave5-vpu-enc.c | 29 +-
drivers/media/platform/marvell/cafe-driver.c | 1 +
drivers/media/platform/nuvoton/npcm-video.c | 34 +-
.../media/platform/nxp/imx8-isi/imx8-isi-core.c | 2 +
.../media/platform/nxp/imx8-isi/imx8-isi-core.h | 16 +
.../platform/nxp/imx8-isi/imx8-isi-crossbar.c | 1 +
drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c | 9 +-
drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c | 11 +-
.../media/platform/nxp/imx8-isi/imx8-isi-pipe.c | 20 +-
.../media/platform/qcom/camss/camss-csid-gen2.c | 47 +-
drivers/media/platform/st/stm32/stm32-dcmi.c | 1 +
drivers/media/platform/sunxi/sun4i-csi/sun4i_dma.c | 6 +-
drivers/media/platform/ti/davinci/vpif_capture.c | 2 +-
drivers/media/platform/ti/vpe/vpe.c | 3 +-
drivers/media/radio/radio-si476x.c | 1 +
drivers/media/test-drivers/vidtv/vidtv_bridge.c | 4 +-
drivers/media/test-drivers/vimc/vimc-core.c | 1 +
drivers/media/test-drivers/vivid/vivid-core.c | 6 +-
drivers/media/test-drivers/vivid/vivid-ctrls.c | 15 +-
drivers/media/test-drivers/vivid/vivid-vid-cap.c | 38 +-
drivers/media/test-drivers/vivid/vivid-vid-cap.h | 1 +
drivers/media/test-drivers/vivid/vivid-vid-out.c | 6 +
drivers/media/usb/airspy/airspy.c | 8 +-
drivers/media/usb/cx231xx/cx231xx-cards.c | 16 +-
drivers/media/usb/msi2500/msi2500.c | 32 +-
drivers/media/usb/pwc/pwc-if.c | 13 +-
drivers/media/v4l2-core/v4l2-ctrls-core.c | 13 +
drivers/media/v4l2-core/v4l2-ctrls-request.c | 14 +-
drivers/media/v4l2-core/v4l2-fwnode.c | 6 +-
drivers/media/v4l2-core/v4l2-subdev.c | 4 +
drivers/misc/mei/bus.c | 16 +-
drivers/misc/nsm.c | 3 +-
drivers/mmc/host/vub300.c | 36 +-
drivers/mtd/maps/vmu-flash.c | 8 +-
drivers/mtd/mtdcore.c | 23 +-
drivers/mtd/mtdswap.c | 5 +-
drivers/mtd/nand/ecc-mtk.c | 16 +-
drivers/net/amt.c | 101 +-
drivers/net/bonding/bond_main.c | 3 +-
drivers/net/ethernet/Kconfig | 1 +
drivers/net/ethernet/Makefile | 1 +
drivers/net/ethernet/airoha/Kconfig | 18 +
drivers/net/ethernet/airoha/Makefile | 6 +
.../net/ethernet/{mediatek => airoha}/airoha_eth.c | 5 +-
drivers/net/ethernet/amd/pds_core/adminq.c | 12 +-
drivers/net/ethernet/amd/pds_core/auxbus.c | 17 +-
drivers/net/ethernet/amd/pds_core/core.c | 22 +-
drivers/net/ethernet/amd/pds_core/devlink.c | 6 +
drivers/net/ethernet/amd/pds_core/main.c | 14 +-
drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 11 +-
drivers/net/ethernet/cadence/macb_main.c | 22 +-
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 1 +
.../net/ethernet/freescale/dpaa2/dpaa2-switch.c | 1 +
drivers/net/ethernet/freescale/fman/fman_dtsec.c | 17 +-
drivers/net/ethernet/google/gve/gve.h | 3 +
drivers/net/ethernet/google/gve/gve_rx_dqo.c | 64 +-
drivers/net/ethernet/hisilicon/hip04_eth.c | 11 +-
drivers/net/ethernet/huawei/hinic/hinic_dev.h | 2 -
drivers/net/ethernet/huawei/hinic/hinic_ethtool.c | 21 -
drivers/net/ethernet/intel/ice/ice_eswitch.c | 3 -
drivers/net/ethernet/intel/ice/ice_lag.c | 2 +-
drivers/net/ethernet/intel/ice/ice_parser.c | 3 +
drivers/net/ethernet/intel/ice/ice_ptp.c | 7 +-
drivers/net/ethernet/intel/ice/ice_sriov.c | 14 +-
drivers/net/ethernet/intel/ice/ice_vf_lib.c | 3 +-
drivers/net/ethernet/marvell/octeontx2/af/rvu.c | 14 +-
drivers/net/ethernet/marvell/octeontx2/af/rvu.h | 1 +
.../net/ethernet/marvell/octeontx2/af/rvu_cn10k.c | 9 +
.../ethernet/marvell/octeontx2/nic/otx2_flows.c | 1 +
.../net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 28 +-
.../net/ethernet/marvell/octeontx2/nic/otx2_tc.c | 29 +-
.../net/ethernet/marvell/octeontx2/nic/otx2_vf.c | 13 +-
drivers/net/ethernet/mediatek/Kconfig | 8 -
drivers/net/ethernet/mediatek/Makefile | 1 -
drivers/net/ethernet/mellanox/mlx5/core/dpll.c | 81 ++
.../ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c | 2 +-
drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 15 +
.../net/ethernet/mellanox/mlx5/core/en_ethtool.c | 19 +-
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 4 +-
.../ethernet/mellanox/mlx5/core/esw/acl/helper.c | 2 +-
.../net/ethernet/mellanox/mlx5/core/esw/bridge.c | 6 +-
.../net/ethernet/mellanox/mlx5/core/mlx5_core.h | 4 +-
drivers/net/ethernet/mellanox/mlx5/core/port.c | 39 +-
.../mellanox/mlx5/core/steering/hws/mlx5hws_bwc.c | 355 +++---
drivers/net/ethernet/microsoft/mana/mana_en.c | 13 +
.../ethernet/netronome/nfp/nfpcore/nfp_resource.c | 3 +
drivers/net/ethernet/realtek/rtase/rtase.h | 8 +
drivers/net/ethernet/realtek/rtase/rtase_main.c | 197 +++
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 92 +-
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 35 +
drivers/net/ethernet/wangxun/txgbe/txgbe_main.c | 1 +
drivers/net/geneve.c | 3 +
drivers/net/gtp.c | 17 +-
drivers/net/ipa/ipa_smp2p.c | 30 +-
drivers/net/mctp/mctp-i3c.c | 11 +-
drivers/net/mctp/mctp-serial.c | 2 +-
drivers/net/pcs/pcs-xpcs.c | 34 +-
drivers/net/ppp/ppp_generic.c | 154 ++-
drivers/net/ppp/pppoe.c | 2 +
drivers/net/ppp/pptp.c | 1 +
drivers/net/slip/slip.c | 4 +
drivers/net/vmxnet3/vmxnet3_drv.c | 22 +-
drivers/net/vxlan/vxlan_core.c | 3 +
drivers/net/vxlan/vxlan_mdb.c | 30 +-
drivers/net/wan/wanxl.c | 3 +-
drivers/net/wireless/ath/ath11k/dp_rx.c | 3 +
drivers/net/wireless/ath/ath11k/pci.c | 4 +
drivers/net/wireless/ath/ath11k/qmi.c | 11 +-
drivers/net/wireless/ath/ath12k/pci.c | 4 +
drivers/net/wireless/ath/ath6kl/txrx.c | 10 +-
drivers/net/wireless/ath/ath6kl/wmi.c | 20 +
drivers/net/wireless/ath/ath9k/hif_usb.c | 7 +-
drivers/net/wireless/ath/carl9170/rx.c | 7 +-
drivers/net/wireless/ath/carl9170/tx.c | 2 +-
drivers/net/wireless/ath/wil6210/cfg80211.c | 1 +
drivers/net/wireless/atmel/at76c50x-usb.c | 7 +-
.../broadcom/brcm80211/brcmfmac/cfg80211.c | 2 +-
.../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 8 +-
.../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 +-
drivers/net/wireless/intel/ipw2x00/ipw2100.c | 8 +-
drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 3 +-
drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 10 +
drivers/net/wireless/intersil/p54/txrx.c | 8 +
drivers/net/wireless/marvell/libertas/cfg.c | 1 +
drivers/net/wireless/marvell/libertas/firmware.c | 1 +
drivers/net/wireless/marvell/libertas_tf/main.c | 2 +-
drivers/net/wireless/marvell/mwifiex/tdls.c | 2 +-
drivers/net/wireless/marvell/mwifiex/uap_event.c | 24 +-
drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 6 +
.../net/wireless/mediatek/mt76/mt76_connac_mcu.c | 2 +
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 18 +-
drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 10 +-
drivers/net/wireless/mediatek/mt76/mt7925/mac.c | 13 +-
drivers/net/wireless/mediatek/mt76/mt7925/main.c | 3 +
drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 2 +
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 19 +-
drivers/net/wireless/microchip/wilc1000/cfg80211.c | 3 +-
drivers/net/wireless/microchip/wilc1000/hif.c | 5 +
drivers/net/wireless/virtual/mac80211_hwsim.c | 1 +
drivers/nvme/target/admin-cmd.c | 21 +
drivers/nvme/target/core.c | 37 +
drivers/nvme/target/discovery.c | 14 +
drivers/nvme/target/fabrics-cmd-auth.c | 38 +-
drivers/nvme/target/fabrics-cmd.c | 43 +
drivers/nvme/target/nvmet.h | 8 +
drivers/platform/loongarch/loongson-laptop.c | 1 +
.../uncore-frequency/uncore-frequency-common.c | 7 +-
drivers/regulator/mt6358-regulator.c | 2 +-
drivers/remoteproc/xlnx_r5_remoteproc.c | 50 +-
drivers/scsi/hosts.c | 2 +
drivers/scsi/scsi_error.c | 22 +-
drivers/scsi/scsi_priv.h | 1 +
drivers/soc/qcom/ice.c | 17 +-
drivers/staging/media/meson/vdec/vdec.c | 4 +-
drivers/staging/media/sunxi/cedrus/cedrus.c | 6 +-
drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 3 +
drivers/staging/media/tegra-video/vi.c | 4 +-
drivers/staging/rtl8723bs/core/rtw_ieee80211.c | 9 +-
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 2 +-
drivers/thunderbolt/debugfs.c | 2 +
drivers/thunderbolt/domain.c | 30 +
drivers/thunderbolt/icm.c | 5 +
drivers/thunderbolt/switch.c | 14 +
drivers/thunderbolt/tb.c | 59 +-
drivers/thunderbolt/tb.h | 2 +
drivers/thunderbolt/xdomain.c | 100 +-
drivers/tty/serial/8250/8250_mid.c | 14 +-
drivers/tty/serial/sc16is7xx.c | 12 +
drivers/uio/uio_hv_generic.c | 8 +-
drivers/usb/atm/ueagle-atm.c | 17 +
drivers/usb/chipidea/core.c | 1 +
drivers/usb/core/port.c | 2 +
drivers/usb/core/sysfs.c | 8 +-
drivers/usb/gadget/function/f_ecm.c | 4 +-
drivers/usb/gadget/function/f_midi.c | 1 +
drivers/usb/gadget/function/f_ncm.c | 20 +-
drivers/usb/gadget/function/f_printer.c | 23 +-
drivers/usb/gadget/function/u_serial.c | 3 +-
drivers/usb/gadget/function/uvc_v4l2.c | 2 +
drivers/usb/gadget/legacy/inode.c | 3 +-
drivers/usb/gadget/udc/aspeed-vhub/hub.c | 3 +-
drivers/usb/gadget/udc/at91_udc.c | 3 +-
drivers/usb/gadget/udc/bdc/bdc_core.c | 20 +
drivers/usb/gadget/udc/bdc/bdc_udc.c | 7 +-
drivers/usb/gadget/udc/cdns2/cdns2-gadget.c | 13 +-
drivers/usb/gadget/udc/dummy_hcd.c | 43 +-
drivers/usb/gadget/udc/fsl_udc_core.c | 94 +-
drivers/usb/gadget/udc/fsl_usb2_udc.h | 1 +
drivers/usb/gadget/udc/omap_udc.c | 3 +-
drivers/usb/gadget/udc/pxa27x_udc.c | 3 +-
drivers/usb/gadget/udc/snps_udc_core.c | 1 -
drivers/usb/host/xhci-pci.c | 1 +
drivers/usb/host/xhci.c | 15 +-
drivers/usb/host/xhci.h | 1 +
drivers/usb/musb/omap2430.c | 25 +-
drivers/usb/serial/ftdi_sio.c | 2 +
drivers/usb/serial/ftdi_sio_ids.h | 5 +
drivers/usb/serial/io_edgeport.c | 3 +-
drivers/usb/serial/keyspan_pda.c | 44 +-
drivers/usb/serial/option.c | 1 +
drivers/usb/storage/unusual_devs.h | 7 +
drivers/vdpa/vdpa_user/iova_domain.c | 157 ++-
drivers/vdpa/vdpa_user/iova_domain.h | 13 +-
drivers/vdpa/vdpa_user/vduse_dev.c | 16 +-
drivers/video/Kconfig | 1 +
drivers/video/fbdev/core/bitblit.c | 120 +-
drivers/video/fbdev/core/fbcon.c | 420 +++---
drivers/video/fbdev/core/fbcon.h | 6 +-
drivers/video/fbdev/core/fbcon_ccw.c | 146 +--
drivers/video/fbdev/core/fbcon_cw.c | 146 +--
drivers/video/fbdev/core/fbcon_rotate.c | 44 +-
drivers/video/fbdev/core/fbcon_rotate.h | 6 +-
drivers/video/fbdev/core/fbcon_ud.c | 162 +--
drivers/video/fbdev/core/softcursor.c | 18 +-
drivers/video/fbdev/core/tileblit.c | 28 +-
drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c | 2 +-
drivers/watchdog/watchdog_pretimeout.c | 2 +
fs/afs/addr_list.c | 50 +
fs/afs/cell.c | 532 ++++----
fs/afs/cmservice.c | 92 +-
fs/afs/dynroot.c | 14 +-
fs/afs/fs_probe.c | 32 +-
fs/afs/fsclient.c | 4 +-
fs/afs/internal.h | 98 +-
fs/afs/main.c | 13 +-
fs/afs/mntpt.c | 6 +-
fs/afs/proc.c | 16 +-
fs/afs/rxrpc.c | 19 +-
fs/afs/security.c | 49 +-
fs/afs/server.c | 621 ++++-----
fs/afs/server_list.c | 6 +-
fs/afs/super.c | 12 +-
fs/afs/vl_alias.c | 8 +-
fs/afs/vl_rotate.c | 2 +-
fs/binfmt_elf_fdpic.c | 4 +
fs/binfmt_misc.c | 5 +-
fs/btrfs/extent_map.c | 4 +-
fs/btrfs/free-space-cache.c | 3 +
fs/btrfs/relocation.c | 2 +
fs/ceph/caps.c | 1 +
fs/ceph/dir.c | 7 +-
fs/ceph/ioctl.c | 6 +
fs/crypto/inline_crypt.c | 57 +-
fs/crypto/keysetup_v1.c | 8 +-
fs/exec.c | 2 +-
fs/f2fs/super.c | 25 +-
fs/iomap/buffered-io.c | 34 +-
fs/namei.c | 43 +
fs/nfsd/nfs4xdr.c | 8 +-
fs/nfsd/vfs.c | 7 +-
fs/nfsd/vfs.h | 2 +-
fs/overlayfs/copy_up.c | 12 +-
fs/overlayfs/xattrs.c | 2 +-
fs/posix_acl.c | 7 +
fs/proc/namespaces.c | 4 +-
fs/proc/task_mmu.c | 14 +-
fs/smb/client/cifsglob.h | 19 +-
fs/smb/client/misc.c | 34 +-
fs/smb/client/smb2ops.c | 25 +-
fs/smb/common/cifsglob.h | 30 +
fs/smb/server/oplock.c | 6 +-
fs/smb/server/smb2misc.c | 5 +
fs/smb/server/smb2pdu.c | 9 +-
fs/smb/server/smb_common.h | 14 +-
fs/smb/server/smbacl.c | 42 +-
fs/xfs/libxfs/xfs_attr_leaf.c | 22 +
fs/xfs/libxfs/xfs_attr_leaf.h | 3 +
fs/xfs/scrub/cow_repair.c | 182 ++-
fs/xfs/scrub/trace.h | 28 +-
include/drm/drm_buddy.h | 174 +--
include/drm/drm_connector.h | 6 +-
include/linux/audit.h | 6 +-
include/linux/audit_arch.h | 12 +-
include/linux/bootconfig.h | 3 +
include/linux/cleanup.h | 9 +
include/linux/cred.h | 15 +
include/linux/dpll.h | 4 +
include/linux/firmware/xlnx-zynqmp.h | 13 +
include/linux/fscrypt.h | 18 +-
include/linux/gpu_buddy.h | 188 +++
include/linux/memory_hotplug.h | 8 +-
include/linux/mlx5/mlx5_ifc.h | 13 +-
include/linux/mmzone.h | 7 +-
include/linux/namei.h | 1 +
include/linux/ppp_channel.h | 3 +-
include/linux/seqlock.h | 10 +-
include/linux/sunrpc/svcsock.h | 3 +
include/linux/sunrpc/xdr.h | 19 +-
include/linux/vtime.h | 6 +
include/media/v4l2-async.h | 4 +-
include/media/videobuf2-core.h | 8 +-
include/net/af_rxrpc.h | 27 +-
include/net/bluetooth/hci.h | 1 +
include/net/bluetooth/hci_core.h | 40 +-
include/net/bluetooth/rfcomm.h | 3 +
include/net/cfg80211.h | 7 +-
include/net/netfilter/nf_tables.h | 37 -
include/net/netfilter/nft_fib.h | 2 -
include/net/netfilter/nft_meta.h | 3 -
include/net/sctp/structs.h | 3 +-
include/rdma/ib_umem.h | 19 +
include/scsi/scsi_host.h | 3 +
include/trace/events/afs.h | 63 +-
include/trace/events/rxrpc.h | 5 +-
include/uapi/linux/btrfs.h | 2 +-
include/uapi/linux/dpll.h | 24 +
include/uapi/linux/netfilter/nf_tables.h | 10 +-
init/Kconfig | 3 +
init/main.c | 45 -
io_uring/rw.c | 42 +-
kernel/audit.c | 2 +-
kernel/audit.h | 32 +-
kernel/audit_fsnotify.c | 39 +-
kernel/audit_tree.c | 2 +-
kernel/audit_watch.c | 42 +-
kernel/auditfilter.c | 17 +-
kernel/auditsc.c | 6 +-
kernel/bpf/verifier.c | 67 +-
kernel/locking/spinlock_rt.c | 27 +-
kernel/trace/ftrace.c | 13 +
kernel/trace/trace_eprobe.c | 3 +-
kernel/trace/trace_mmiotrace.c | 4 +-
kernel/trace/trace_probe.c | 13 +-
lib/bootconfig.c | 65 +
lib/compat_audit.c | 12 +-
mm/damon/core.c | 13 +
mm/hugetlb.c | 7 +-
mm/internal.h | 47 +
mm/memory_hotplug.c | 13 +-
mm/memremap.c | 4 +-
mm/mm_init.c | 36 +-
mm/sparse-vmemmap.c | 336 +++++
mm/sparse.c | 112 +-
net/bluetooth/hci_conn.c | 54 +-
net/bluetooth/hci_core.c | 27 +-
net/bluetooth/hci_event.c | 7 +-
net/bluetooth/hci_sync.c | 25 +-
net/bluetooth/iso.c | 6 +-
net/bluetooth/mgmt.c | 87 +-
net/bluetooth/rfcomm/core.c | 17 +
net/bluetooth/rfcomm/tty.c | 7 +-
net/bridge/br_netlink_tunnel.c | 3 +-
net/bridge/br_private.h | 6 +-
net/bridge/br_vlan.c | 10 +-
net/bridge/br_vlan_options.c | 3 +-
net/bridge/netfilter/nft_meta_bridge.c | 20 -
net/bridge/netfilter/nft_reject_bridge.c | 1 -
net/can/bcm.c | 528 ++++++--
net/can/isotp.c | 278 +++-
net/can/j1939/transport.c | 18 +-
net/ceph/auth_x.c | 9 +-
net/ceph/ceph_common.c | 4 +-
net/ceph/mon_client.c | 4 +-
net/ceph/osdmap.c | 12 +-
net/core/filter.c | 6 +-
net/core/gro.c | 4 +-
net/core/sock_map.c | 2 +
net/hsr/hsr_slave.c | 2 +
net/ipv4/fib_trie.c | 2 +-
net/ipv4/icmp.c | 18 +-
net/ipv4/ip_gre.c | 4 +-
net/ipv4/netfilter/nft_dup_ipv4.c | 1 -
net/ipv4/netfilter/nft_fib_ipv4.c | 2 -
net/ipv4/netfilter/nft_reject_ipv4.c | 1 -
net/ipv4/nexthop.c | 2 +-
net/ipv4/tcp_bpf.c | 2 +-
net/ipv4/tcp_ipv4.c | 3 +
net/ipv4/tcp_output.c | 8 +-
net/ipv6/ila/ila_common.c | 12 +
net/ipv6/ip6_gre.c | 4 +-
net/ipv6/ip6_tunnel.c | 3 +
net/ipv6/netfilter/nft_dup_ipv6.c | 1 -
net/ipv6/netfilter/nft_fib_ipv6.c | 2 -
net/ipv6/netfilter/nft_reject_ipv6.c | 1 -
net/ipv6/raw.c | 2 +-
net/ipv6/tcp_ipv6.c | 2 +
net/ipv6/xfrm6_policy.c | 1 +
net/iucv/af_iucv.c | 21 +-
net/l2tp/l2tp_ppp.c | 1 +
net/mac80211/cfg.c | 12 +-
net/mac80211/iface.c | 8 +-
net/mac80211/link.c | 4 +
net/mac80211/rx.c | 2 +
net/mac802154/llsec.c | 5 +
net/mac802154/scan.c | 11 +
net/mpls/af_mpls.c | 3 +
net/mptcp/options.c | 12 +-
net/mptcp/protocol.c | 1 +
net/netfilter/nf_conntrack_sip.c | 10 +-
net/netfilter/nf_tables_api.c | 315 +----
net/netfilter/nft_bitwise.c | 137 +-
net/netfilter/nft_byteorder.c | 11 -
net/netfilter/nft_cmp.c | 3 -
net/netfilter/nft_compat.c | 10 -
net/netfilter/nft_connlimit.c | 1 -
net/netfilter/nft_counter.c | 21 +-
net/netfilter/nft_ct.c | 46 -
net/netfilter/nft_dup_netdev.c | 1 -
net/netfilter/nft_dynset.c | 1 -
net/netfilter/nft_exthdr.c | 34 -
net/netfilter/nft_fib.c | 51 +-
net/netfilter/nft_fib_inet.c | 1 -
net/netfilter/nft_fib_netdev.c | 30 +-
net/netfilter/nft_flow_offload.c | 1 -
net/netfilter/nft_fwd_netdev.c | 2 -
net/netfilter/nft_hash.c | 36 -
net/netfilter/nft_immediate.c | 12 -
net/netfilter/nft_last.c | 1 -
net/netfilter/nft_limit.c | 2 -
net/netfilter/nft_log.c | 1 -
net/netfilter/nft_lookup.c | 12 -
net/netfilter/nft_masq.c | 3 -
net/netfilter/nft_meta.c | 45 -
net/netfilter/nft_nat.c | 2 -
net/netfilter/nft_numgen.c | 22 -
net/netfilter/nft_objref.c | 2 -
net/netfilter/nft_osf.c | 25 -
net/netfilter/nft_payload.c | 47 -
net/netfilter/nft_queue.c | 2 -
net/netfilter/nft_quota.c | 14 +-
net/netfilter/nft_range.c | 1 -
net/netfilter/nft_redir.c | 3 -
net/netfilter/nft_reject_inet.c | 1 -
net/netfilter/nft_reject_netdev.c | 1 -
net/netfilter/nft_rt.c | 1 -
net/netfilter/nft_socket.c | 26 -
net/netfilter/nft_synproxy.c | 1 -
net/netfilter/nft_tproxy.c | 1 -
net/netfilter/nft_tunnel.c | 26 -
net/netfilter/nft_xfrm.c | 27 -
net/openvswitch/actions.c | 19 +-
net/openvswitch/datapath.c | 25 +-
net/openvswitch/datapath.h | 2 +-
net/openvswitch/vport.c | 2 +-
net/packet/af_packet.c | 6 +-
net/phonet/pep.c | 2 +
net/qrtr/af_qrtr.c | 8 +
net/qrtr/ns.c | 4 +-
net/rds/recv.c | 15 +
net/rds/tcp.c | 4 +-
net/rxrpc/af_rxrpc.c | 24 +-
net/rxrpc/ar-internal.h | 14 +-
net/rxrpc/call_accept.c | 79 +-
net/rxrpc/call_event.c | 31 +-
net/rxrpc/call_object.c | 44 +-
net/rxrpc/conn_client.c | 20 +-
net/rxrpc/conn_event.c | 14 +-
net/rxrpc/conn_object.c | 8 +-
net/rxrpc/input.c | 7 +-
net/rxrpc/io_thread.c | 108 +-
net/rxrpc/peer_event.c | 10 +-
net/rxrpc/peer_object.c | 35 +-
net/rxrpc/recvmsg.c | 26 +-
net/rxrpc/rxperf.c | 10 +-
net/rxrpc/security.c | 4 +-
net/rxrpc/sendmsg.c | 8 +-
net/rxrpc/txbuf.c | 4 +-
net/sched/act_tunnel_key.c | 14 +-
net/sctp/auth.c | 2 +-
net/sctp/protocol.c | 21 +-
net/sctp/sm_make_chunk.c | 6 +
net/sctp/sm_statefuns.c | 2 +-
net/sctp/stream.c | 6 +-
net/sctp/sysctl.c | 9 +-
net/sunrpc/svcsock.c | 51 +-
net/sunrpc/xdr.c | 210 ++-
net/sunrpc/xprtrdma/rpc_rdma.c | 4 +
net/sunrpc/xprtrdma/verbs.c | 12 +-
net/tipc/netlink.c | 6 +-
net/tipc/netlink_compat.c | 4 +
net/tipc/socket.c | 7 +-
net/tls/tls_device.c | 6 +-
net/vmw_vsock/virtio_transport_common.c | 165 ++-
net/wireless/chan.c | 7 +-
net/wireless/core.c | 46 +-
net/wireless/core.h | 3 +-
net/wireless/mlme.c | 8 +-
net/wireless/nl80211.c | 251 ++--
net/wireless/pmsr.c | 29 +-
net/wireless/rdev-ops.h | 5 +-
net/wireless/reg.c | 53 +-
net/wireless/scan.c | 47 +-
net/wireless/sme.c | 12 +-
net/wireless/trace.h | 10 +-
net/wireless/util.c | 7 +-
net/wireless/wext-compat.c | 317 ++---
net/wireless/wext-sme.c | 43 +-
net/x25/af_x25.c | 8 +-
net/xfrm/xfrm_nat_keepalive.c | 45 +-
net/xfrm/xfrm_policy.c | 4 +-
rust/bindings/lib.rs | 4 +
rust/uapi/lib.rs | 4 +
security/landlock/fs.c | 51 +-
security/landlock/fs.h | 33 +-
security/landlock/task.c | 36 +-
sound/core/seq/seq_timer.c | 13 +-
sound/core/timer.c | 21 +-
sound/hda/hdac_regmap.c | 4 +-
sound/pci/hda/cs35l41_hda.c | 13 +-
sound/pci/hda/patch_conexant.c | 3 -
sound/soc/amd/ps/pci-ps.c | 2 +-
sound/soc/codecs/bt-sco.c | 10 +-
sound/soc/codecs/cs35l56-i2c.c | 4 +-
sound/soc/codecs/cs35l56-spi.c | 4 +-
sound/soc/codecs/cs35l56.c | 25 +-
sound/soc/codecs/cs42l43-jack.c | 3 +-
sound/soc/codecs/tas2562.c | 5 +-
sound/soc/codecs/tas2781-fmwlib.c | 63 +-
sound/soc/fsl/fsl_sai.c | 29 +-
sound/soc/mediatek/mt8183/mt8183-afe-pcm.c | 300 ++---
sound/soc/mediatek/mt8192/mt8192-afe-pcm.c | 27 +-
sound/soc/meson/aiu-fifo-spdif.c | 5 +
sound/usb/quirks.c | 2 +
tools/objtool/check.c | 1 +
tools/testing/selftests/alsa/mixer-test.c | 1 +
.../testing/selftests/bpf/progs/verifier_ld_ind.c | 142 +++
tools/testing/selftests/ftrace/ftracetest | 1 +
tools/testing/selftests/net/af_unix/config | 1 +
tools/testing/selftests/net/openvswitch/config | 16 +
715 files changed, 11519 insertions(+), 7953 deletions(-)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 001/602] platform/x86/intel-uncore-freq: Fix current_freq_khz after CPU hotplug
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 002/602] net: airoha: Move airoha_eth driver in a dedicated folder Greg Kroah-Hartman
` (604 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Srinivas Pandruvada,
Ilpo Järvinen, Guixiong Wei, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guixiong Wei <weiguixiong@bytedance.com>
commit 6b63520ed14b17bbe9c2103debbd2152dde1fba3 upstream.
When the last CPU of a legacy uncore die goes offline,
uncore_freq_remove_die_entry() clears control_cpu. During CPU hotplug
re-add, uncore_freq_add_entry() still populates sysfs attributes before
assigning the new control CPU. As a result, the current frequency read
returns -ENXIO and current_freq_khz is omitted from the recreated sysfs
group.
Assign control_cpu before the initial read paths and before
create_attr_group() so sysfs recreation uses the new online CPU. If
sysfs creation fails, restore control_cpu to -1 to keep the error path
state consistent.
Fixes: 4d73c6772ab7 ("platform/x86: intel-uncore-freq: Conditionally create attribute for read frequency")
Cc: stable@vger.kernel.org
Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Link: https://patch.msgid.link/20260602020752.3126-1-weiguixiong@bytedance.com
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Guixiong Wei <weiguixiong@bytedance.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
.../x86/intel/uncore-frequency/uncore-frequency-common.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
index e22b683a7a434c..2e4e2bcc3c6e71 100644
--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
+++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
@@ -240,15 +240,20 @@ int uncore_freq_add_entry(struct uncore_data *data, int cpu)
sprintf(data->name, "package_%02d_die_%02d", data->package_id, data->die_id);
}
+ /*
+ * Set the control CPU before any read path so entry recreation after CPU
+ * hotplug can populate read-only attributes from the new online CPU.
+ */
+ data->control_cpu = cpu;
uncore_read(data, &data->initial_min_freq_khz, UNCORE_INDEX_MIN_FREQ);
uncore_read(data, &data->initial_max_freq_khz, UNCORE_INDEX_MAX_FREQ);
ret = create_attr_group(data, data->name);
if (ret) {
+ data->control_cpu = -1;
if (data->domain_id != UNCORE_DOMAIN_ID_INVALID)
ida_free(&intel_uncore_ida, data->instance_id);
} else {
- data->control_cpu = cpu;
data->valid = true;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 002/602] net: airoha: Move airoha_eth driver in a dedicated folder
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 001/602] platform/x86/intel-uncore-freq: Fix current_freq_khz after CPU hotplug Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 003/602] net: airoha: Fix skb->priority underflow in airoha_dev_select_queue() Greg Kroah-Hartman
` (603 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Lorenzo Bianconi, Paolo Abeni,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <lorenzo@kernel.org>
[ Upstream commit fb3dda82fd38ca42140f29b3082324dcdc128293 ]
The airoha_eth driver has no codebase shared with mtk_eth_soc one.
Moreover, the upcoming features (flowtable hw offloading, PCS, ..) will
not reuse any code from MediaTek driver. Move the Airoha driver in a
dedicated folder.
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Stable-dep-of: 86e51aa24686 ("net: airoha: Fix skb->priority underflow in airoha_dev_select_queue()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/Kconfig | 2 ++
drivers/net/ethernet/Makefile | 1 +
drivers/net/ethernet/airoha/Kconfig | 18 ++++++++++++++++++
drivers/net/ethernet/airoha/Makefile | 6 ++++++
.../ethernet/{mediatek => airoha}/airoha_eth.c | 0
drivers/net/ethernet/mediatek/Kconfig | 8 --------
drivers/net/ethernet/mediatek/Makefile | 1 -
7 files changed, 27 insertions(+), 9 deletions(-)
create mode 100644 drivers/net/ethernet/airoha/Kconfig
create mode 100644 drivers/net/ethernet/airoha/Makefile
rename drivers/net/ethernet/{mediatek => airoha}/airoha_eth.c (100%)
diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
index 9a542e3c9b05d8..0875b5706b83ac 100644
--- a/drivers/net/ethernet/Kconfig
+++ b/drivers/net/ethernet/Kconfig
@@ -20,6 +20,8 @@ source "drivers/net/ethernet/actions/Kconfig"
source "drivers/net/ethernet/adaptec/Kconfig"
source "drivers/net/ethernet/aeroflex/Kconfig"
source "drivers/net/ethernet/agere/Kconfig"
+source "drivers/net/ethernet/airoha/Kconfig"
+source "drivers/net/ethernet/mellanox/Kconfig"
source "drivers/net/ethernet/alacritech/Kconfig"
source "drivers/net/ethernet/allwinner/Kconfig"
source "drivers/net/ethernet/alteon/Kconfig"
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
index 99fa180dedb805..67182339469a0d 100644
--- a/drivers/net/ethernet/Makefile
+++ b/drivers/net/ethernet/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_NET_VENDOR_ADAPTEC) += adaptec/
obj-$(CONFIG_GRETH) += aeroflex/
obj-$(CONFIG_NET_VENDOR_ADI) += adi/
obj-$(CONFIG_NET_VENDOR_AGERE) += agere/
+obj-$(CONFIG_NET_VENDOR_AIROHA) += airoha/
obj-$(CONFIG_NET_VENDOR_ALACRITECH) += alacritech/
obj-$(CONFIG_NET_VENDOR_ALLWINNER) += allwinner/
obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/
diff --git a/drivers/net/ethernet/airoha/Kconfig b/drivers/net/ethernet/airoha/Kconfig
new file mode 100644
index 00000000000000..b6a131845f13b2
--- /dev/null
+++ b/drivers/net/ethernet/airoha/Kconfig
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config NET_VENDOR_AIROHA
+ bool "Airoha devices"
+ depends on ARCH_AIROHA || COMPILE_TEST
+ help
+ If you have a Airoha SoC with ethernet, say Y.
+
+if NET_VENDOR_AIROHA
+
+config NET_AIROHA
+ tristate "Airoha SoC Gigabit Ethernet support"
+ depends on NET_DSA || !NET_DSA
+ select PAGE_POOL
+ help
+ This driver supports the gigabit ethernet MACs in the
+ Airoha SoC family.
+
+endif #NET_VENDOR_AIROHA
diff --git a/drivers/net/ethernet/airoha/Makefile b/drivers/net/ethernet/airoha/Makefile
new file mode 100644
index 00000000000000..73a6f3680a4c4c
--- /dev/null
+++ b/drivers/net/ethernet/airoha/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Airoha for the Mediatek SoCs built-in ethernet macs
+#
+
+obj-$(CONFIG_NET_AIROHA) += airoha_eth.o
diff --git a/drivers/net/ethernet/mediatek/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
similarity index 100%
rename from drivers/net/ethernet/mediatek/airoha_eth.c
rename to drivers/net/ethernet/airoha/airoha_eth.c
diff --git a/drivers/net/ethernet/mediatek/Kconfig b/drivers/net/ethernet/mediatek/Kconfig
index 95c4405b7d7bee..7bfd3f230ff507 100644
--- a/drivers/net/ethernet/mediatek/Kconfig
+++ b/drivers/net/ethernet/mediatek/Kconfig
@@ -7,14 +7,6 @@ config NET_VENDOR_MEDIATEK
if NET_VENDOR_MEDIATEK
-config NET_AIROHA
- tristate "Airoha SoC Gigabit Ethernet support"
- depends on NET_DSA || !NET_DSA
- select PAGE_POOL
- help
- This driver supports the gigabit ethernet MACs in the
- Airoha SoC family.
-
config NET_MEDIATEK_SOC_WED
depends on ARCH_MEDIATEK || COMPILE_TEST
def_bool NET_MEDIATEK_SOC != n
diff --git a/drivers/net/ethernet/mediatek/Makefile b/drivers/net/ethernet/mediatek/Makefile
index ddbb7f4a516cac..03e008fbc859b3 100644
--- a/drivers/net/ethernet/mediatek/Makefile
+++ b/drivers/net/ethernet/mediatek/Makefile
@@ -11,4 +11,3 @@ mtk_eth-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_debugfs.o
endif
obj-$(CONFIG_NET_MEDIATEK_SOC_WED) += mtk_wed_ops.o
obj-$(CONFIG_NET_MEDIATEK_STAR_EMAC) += mtk_star_emac.o
-obj-$(CONFIG_NET_AIROHA) += airoha_eth.o
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 003/602] net: airoha: Fix skb->priority underflow in airoha_dev_select_queue()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 001/602] platform/x86/intel-uncore-freq: Fix current_freq_khz after CPU hotplug Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 002/602] net: airoha: Move airoha_eth driver in a dedicated folder Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 004/602] bpf: Fix ld_{abs,ind} failure path analysis in subprogs Greg Kroah-Hartman
` (602 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Lorenzo Bianconi, Joe Damato,
Wayen Yan, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wayen Yan <win847@gmail.com>
[ Upstream commit 86e51aa24686cc95bb35613059e8b94b9b81e3f0 ]
In airoha_dev_select_queue(), the expression:
queue = (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES;
implicitly converts to unsigned arithmetic: when skb->priority is 0
(the default for unclassified traffic), (0u - 1u) wraps to UINT_MAX,
and UINT_MAX % 8 = 7, routing default best-effort packets to the
highest-priority QoS queue. This causes QoS inversion where the
majority of traffic on a PON gateway starves actual high-priority
flows (VoIP, gaming, etc.).
The "- 1" offset was a leftover from the ETS offload implementation
that has since been removed. The correct mapping is a direct modulo:
queue = skb->priority % AIROHA_NUM_QOS_QUEUES;
This maps priority 0 → queue 0 (lowest), priority 7 → queue 7
(highest), with higher priorities wrapping around. This is the
standard Linux sk_prio → HW queue mapping used by other drivers.
Fixes: 2b288b81560b ("net: airoha: Introduce ndo_select_queue callback")
Link: https://lore.kernel.org/netdev/178185573207.2378135.3729126358670287878@gmail.com/
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
Reviewed-by: Joe Damato <joe@dama.to>
Signed-off-by: Wayen Yan <win847@gmail.com>
Link: https://patch.msgid.link/178194366700.2485734.5368768965976693502@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 07f89e08b5faad..db4b87c17a2864 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -2505,7 +2505,7 @@ static u16 airoha_dev_select_queue(struct net_device *dev, struct sk_buff *skb,
*/
channel = netdev_uses_dsa(dev) ? skb_get_queue_mapping(skb) : port->id;
channel = channel % AIROHA_NUM_QOS_CHANNELS;
- queue = (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES; /* QoS queue */
+ queue = skb->priority % AIROHA_NUM_QOS_QUEUES;
queue = channel * AIROHA_NUM_QOS_QUEUES + queue;
return queue < dev->num_tx_queues ? queue : 0;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 004/602] bpf: Fix ld_{abs,ind} failure path analysis in subprogs
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (2 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 003/602] net: airoha: Fix skb->priority underflow in airoha_dev_select_queue() Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 005/602] selftests/bpf: Add tests for ld_{abs,ind} failure path " Greg Kroah-Hartman
` (601 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, STAR Labs SG, Daniel Borkmann,
Alexei Starovoitov, Philo Lu, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Borkmann <daniel@iogearbox.net>
commit ee861486e377edc55361c08dcbceab3f6b6577bd upstream.
Usage of ld_{abs,ind} instructions got extended into subprogs some time
ago via commit 09b28d76eac4 ("bpf: Add abnormal return checks."). These
are only allowed in subprograms when the latter are BTF annotated and
have scalar return types.
The code generator in bpf_gen_ld_abs() has an abnormal exit path (r0=0 +
exit) from legacy cBPF times. While the enforcement is on scalar return
types, the verifier must also simulate the path of abnormal exit if the
packet data load via ld_{abs,ind} failed.
This is currently not the case. Fix it by having the verifier simulate
both success and failure paths, and extend it in similar ways as we do
for tail calls. The success path (r0=unknown, continue to next insn) is
pushed onto stack for later validation and the r0=0 and return to the
caller is done on the fall-through side.
Fixes: 09b28d76eac4 ("bpf: Add abnormal return checks.")
Reported-by: STAR Labs SG <info@starlabs.sg>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/r/20260408191242.526279-2-daniel@iogearbox.net
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
[ Dropped visit_abnormal_return_insn changes: depends on 7.0 symbols from
e40f5a6bf88a ("bpf: correct stack liveness for tail calls");
Hunk1: adapted IS_ERR/PTR_ERR to !branch/-EFAULT to match push_stack()
NULL-on-failure convention. ]
Signed-off-by: Philo Lu <lulie@linux.alibaba.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
kernel/bpf/verifier.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 7f1144486a8c4a..8c3c4ab989a053 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -16100,6 +16100,23 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
mark_reg_unknown(env, regs, BPF_REG_0);
/* ld_abs load up to 32-bit skb data. */
regs[BPF_REG_0].subreg_def = env->insn_idx + 1;
+ /*
+ * See bpf_gen_ld_abs() which emits a hidden BPF_EXIT with r0=0
+ * which must be explored by the verifier when in a subprog.
+ */
+ if (env->cur_state->curframe) {
+ struct bpf_verifier_state *branch;
+
+ mark_reg_scratched(env, BPF_REG_0);
+ branch = push_stack(env, env->insn_idx + 1, env->insn_idx, false);
+ if (!branch)
+ return -EFAULT;
+ mark_reg_known_zero(env, regs, BPF_REG_0);
+ err = prepare_func_exit(env, &env->insn_idx);
+ if (err)
+ return err;
+ env->insn_idx--;
+ }
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 005/602] selftests/bpf: Add tests for ld_{abs,ind} failure path in subprogs
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (3 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 004/602] bpf: Fix ld_{abs,ind} failure path analysis in subprogs Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 006/602] netfilter: nft_counter: serialize reset with spinlock Greg Kroah-Hartman
` (600 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Daniel Borkmann, Alexei Starovoitov,
Philo Lu, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Borkmann <daniel@iogearbox.net>
commit e0fcb42bc6f41bab2895757d6610616b3820eff7 upstream.
Extend the verifier_ld_ind BPF selftests with subprogs containing
ld_{abs,ind} and craft the test in a way where the invalid register
read is rejected in the fixed case. Also add a success case each,
and add additional coverage related to the BTF return type enforcement.
# LDLIBS=-static PKG_CONFIG='pkg-config --static' ./vmtest.sh -- ./test_progs -t verifier_ld_ind
[...]
#611/1 verifier_ld_ind/ld_ind: check calling conv, r1:OK
#611/2 verifier_ld_ind/ld_ind: check calling conv, r1 @unpriv:OK
#611/3 verifier_ld_ind/ld_ind: check calling conv, r2:OK
#611/4 verifier_ld_ind/ld_ind: check calling conv, r2 @unpriv:OK
#611/5 verifier_ld_ind/ld_ind: check calling conv, r3:OK
#611/6 verifier_ld_ind/ld_ind: check calling conv, r3 @unpriv:OK
#611/7 verifier_ld_ind/ld_ind: check calling conv, r4:OK
#611/8 verifier_ld_ind/ld_ind: check calling conv, r4 @unpriv:OK
#611/9 verifier_ld_ind/ld_ind: check calling conv, r5:OK
#611/10 verifier_ld_ind/ld_ind: check calling conv, r5 @unpriv:OK
#611/11 verifier_ld_ind/ld_ind: check calling conv, r7:OK
#611/12 verifier_ld_ind/ld_ind: check calling conv, r7 @unpriv:OK
#611/13 verifier_ld_ind/ld_abs: subprog early exit on ld_abs failure:OK
#611/14 verifier_ld_ind/ld_ind: subprog early exit on ld_ind failure:OK
#611/15 verifier_ld_ind/ld_abs: subprog with both paths safe:OK
#611/16 verifier_ld_ind/ld_ind: subprog with both paths safe:OK
#611/17 verifier_ld_ind/ld_abs: reject void return subprog:OK
#611/18 verifier_ld_ind/ld_ind: reject void return subprog:OK
#611 verifier_ld_ind:OK
Summary: 1/18 PASSED, 0 SKIPPED, 0 FAILED
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/r/20260408191242.526279-4-daniel@iogearbox.net
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Philo Lu <lulie@linux.alibaba.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
.../selftests/bpf/progs/verifier_ld_ind.c | 142 ++++++++++++++++++
1 file changed, 142 insertions(+)
diff --git a/tools/testing/selftests/bpf/progs/verifier_ld_ind.c b/tools/testing/selftests/bpf/progs/verifier_ld_ind.c
index c925ba9a2e74c2..09e81b99eecb4e 100644
--- a/tools/testing/selftests/bpf/progs/verifier_ld_ind.c
+++ b/tools/testing/selftests/bpf/progs/verifier_ld_ind.c
@@ -107,4 +107,146 @@ __naked void ind_check_calling_conv_r7(void)
: __clobber_all);
}
+/*
+ * ld_{abs,ind} subprog that always sets r0=1 on the success path.
+ * bpf_gen_ld_abs() emits a hidden exit with r0=0 when the load helper
+ * fails. The verifier must model this failure return so that callers
+ * account for r0=0 as a possible return value.
+ */
+__naked __noinline __used
+static int ldabs_subprog(void)
+{
+ asm volatile (
+ "r6 = r1;"
+ ".8byte %[ld_abs];"
+ "r0 = 1;"
+ "exit;"
+ :
+ : __imm_insn(ld_abs, BPF_LD_ABS(BPF_W, 0))
+ : __clobber_all);
+}
+
+__naked __noinline __used
+static int ldind_subprog(void)
+{
+ asm volatile (
+ "r6 = r1;"
+ "r7 = 0;"
+ ".8byte %[ld_ind];"
+ "r0 = 1;"
+ "exit;"
+ :
+ : __imm_insn(ld_ind, BPF_LD_IND(BPF_W, BPF_REG_7, 0))
+ : __clobber_all);
+}
+
+SEC("socket")
+__description("ld_abs: subprog early exit on ld_abs failure")
+__failure __msg("R9 !read_ok")
+__naked void ld_abs_subprog_early_exit(void)
+{
+ asm volatile (
+ "call ldabs_subprog;"
+ "if r0 != 0 goto l_exit_%=;"
+ "r0 = r9;"
+ "l_exit_%=:"
+ "r0 = 0;"
+ "exit;"
+ ::: __clobber_all);
+}
+
+SEC("socket")
+__description("ld_ind: subprog early exit on ld_ind failure")
+__failure __msg("R9 !read_ok")
+__naked void ld_ind_subprog_early_exit(void)
+{
+ asm volatile (
+ "call ldind_subprog;"
+ "if r0 != 0 goto l_exit_%=;"
+ "r0 = r9;"
+ "l_exit_%=:"
+ "r0 = 0;"
+ "exit;"
+ ::: __clobber_all);
+}
+
+SEC("socket")
+__description("ld_abs: subprog with both paths safe")
+__success
+__naked void ld_abs_subprog_both_paths_safe(void)
+{
+ asm volatile (
+ "call ldabs_subprog;"
+ "r0 = 0;"
+ "exit;"
+ ::: __clobber_all);
+}
+
+SEC("socket")
+__description("ld_ind: subprog with both paths safe")
+__success
+__naked void ld_ind_subprog_both_paths_safe(void)
+{
+ asm volatile (
+ "call ldind_subprog;"
+ "r0 = 0;"
+ "exit;"
+ ::: __clobber_all);
+}
+
+/*
+ * ld_{abs,ind} in subprogs require scalar (int) return type in BTF.
+ * A test with void return must be rejected.
+ */
+__naked __noinline __used
+static void ldabs_void_subprog(void)
+{
+ asm volatile (
+ "r6 = r1;"
+ ".8byte %[ld_abs];"
+ "r0 = 1;"
+ "exit;"
+ :
+ : __imm_insn(ld_abs, BPF_LD_ABS(BPF_W, 0))
+ : __clobber_all);
+}
+
+SEC("socket")
+__description("ld_abs: reject void return subprog")
+__failure __msg("LD_ABS is only allowed in functions that return 'int'")
+__naked void ld_abs_void_subprog_reject(void)
+{
+ asm volatile (
+ "call ldabs_void_subprog;"
+ "r0 = 0;"
+ "exit;"
+ ::: __clobber_all);
+}
+
+__naked __noinline __used
+static void ldind_void_subprog(void)
+{
+ asm volatile (
+ "r6 = r1;"
+ "r7 = 0;"
+ ".8byte %[ld_ind];"
+ "r0 = 1;"
+ "exit;"
+ :
+ : __imm_insn(ld_ind, BPF_LD_IND(BPF_W, BPF_REG_7, 0))
+ : __clobber_all);
+}
+
+SEC("socket")
+__description("ld_ind: reject void return subprog")
+__failure __msg("LD_ABS is only allowed in functions that return 'int'")
+__naked void ld_ind_void_subprog_reject(void)
+{
+ asm volatile (
+ "call ldind_void_subprog;"
+ "r0 = 0;"
+ "exit;"
+ ::: __clobber_all);
+}
+
char _license[] SEC("license") = "GPL";
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 006/602] netfilter: nft_counter: serialize reset with spinlock
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (4 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 005/602] selftests/bpf: Add tests for ld_{abs,ind} failure path " Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 007/602] netfilter: nft_quota: use atomic64_xchg for reset Greg Kroah-Hartman
` (599 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Florian Westphal, Brian Witte,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Brian Witte <brianwitte@mailfence.com>
[ Upstream commit 779c60a5190c42689534172f4b49e927c9959e4e ]
Add a global static spinlock to serialize counter fetch+reset
operations, preventing concurrent dump-and-reset from underrunning
values.
The lock is taken before fetching the total so that two parallel
resets cannot both read the same counter values and then both
subtract them.
A global lock is used for simplicity since resets are infrequent.
If this becomes a bottleneck, it can be replaced with a per-net
lock later.
Fixes: bd662c4218f9 ("netfilter: nf_tables: Add locking for NFT_MSG_GETOBJ_RESET requests")
Fixes: 3d483faa6663 ("netfilter: nf_tables: Add locking for NFT_MSG_GETSETELEM_RESET requests")
Fixes: 3cb03edb4de3 ("netfilter: nf_tables: Add locking for NFT_MSG_GETRULE_RESET requests")
Suggested-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Brian Witte <brianwitte@mailfence.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/netfilter/nft_counter.c | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/net/netfilter/nft_counter.c b/net/netfilter/nft_counter.c
index 0d70325280cc57..169ae93688bcc5 100644
--- a/net/netfilter/nft_counter.c
+++ b/net/netfilter/nft_counter.c
@@ -32,6 +32,9 @@ struct nft_counter_percpu_priv {
static DEFINE_PER_CPU(struct u64_stats_sync, nft_counter_sync);
+/* control plane only: sync fetch+reset */
+static DEFINE_SPINLOCK(nft_counter_lock);
+
static inline void nft_counter_do_eval(struct nft_counter_percpu_priv *priv,
struct nft_regs *regs,
const struct nft_pktinfo *pkt)
@@ -148,13 +151,25 @@ static void nft_counter_fetch(struct nft_counter_percpu_priv *priv,
}
}
+static void nft_counter_fetch_and_reset(struct nft_counter_percpu_priv *priv,
+ struct nft_counter_tot *total)
+{
+ spin_lock(&nft_counter_lock);
+ nft_counter_fetch(priv, total);
+ nft_counter_reset(priv, total);
+ spin_unlock(&nft_counter_lock);
+}
+
static int nft_counter_do_dump(struct sk_buff *skb,
struct nft_counter_percpu_priv *priv,
bool reset)
{
struct nft_counter_tot total;
- nft_counter_fetch(priv, &total);
+ if (unlikely(reset))
+ nft_counter_fetch_and_reset(priv, &total);
+ else
+ nft_counter_fetch(priv, &total);
if (nla_put_be64(skb, NFTA_COUNTER_BYTES, cpu_to_be64(total.bytes),
NFTA_COUNTER_PAD) ||
@@ -162,9 +177,6 @@ static int nft_counter_do_dump(struct sk_buff *skb,
NFTA_COUNTER_PAD))
goto nla_put_failure;
- if (reset)
- nft_counter_reset(priv, &total);
-
return 0;
nla_put_failure:
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 007/602] netfilter: nft_quota: use atomic64_xchg for reset
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (5 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 006/602] netfilter: nft_counter: serialize reset with spinlock Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 008/602] netfilter: nf_tables: revert commit_mutex usage in reset path Greg Kroah-Hartman
` (598 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Pablo Neira Ayuso, Brian Witte,
Florian Westphal, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Brian Witte <brianwitte@mailfence.com>
[ Upstream commit 30c4d7fb59ac4c8d7fa7937df11eed10b368fa11 ]
Use atomic64_xchg() to atomically read and zero the consumed value
on reset, which is simpler than the previous read+sub pattern and
doesn't require lock serialization.
Fixes: bd662c4218f9 ("netfilter: nf_tables: Add locking for NFT_MSG_GETOBJ_RESET requests")
Fixes: 3d483faa6663 ("netfilter: nf_tables: Add locking for NFT_MSG_GETSETELEM_RESET requests")
Fixes: 3cb03edb4de3 ("netfilter: nf_tables: Add locking for NFT_MSG_GETRULE_RESET requests")
Suggested-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Brian Witte <brianwitte@mailfence.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/netfilter/nft_quota.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/net/netfilter/nft_quota.c b/net/netfilter/nft_quota.c
index df0798da2329b9..cb6c0e04ff6755 100644
--- a/net/netfilter/nft_quota.c
+++ b/net/netfilter/nft_quota.c
@@ -140,11 +140,16 @@ static int nft_quota_do_dump(struct sk_buff *skb, struct nft_quota *priv,
u64 consumed, consumed_cap, quota;
u32 flags = priv->flags;
- /* Since we inconditionally increment consumed quota for each packet
+ /* Since we unconditionally increment consumed quota for each packet
* that we see, don't go over the quota boundary in what we send to
* userspace.
*/
- consumed = atomic64_read(priv->consumed);
+ if (reset) {
+ consumed = atomic64_xchg(priv->consumed, 0);
+ clear_bit(NFT_QUOTA_DEPLETED_BIT, &priv->flags);
+ } else {
+ consumed = atomic64_read(priv->consumed);
+ }
quota = atomic64_read(&priv->quota);
if (consumed >= quota) {
consumed_cap = quota;
@@ -160,10 +165,6 @@ static int nft_quota_do_dump(struct sk_buff *skb, struct nft_quota *priv,
nla_put_be32(skb, NFTA_QUOTA_FLAGS, htonl(flags)))
goto nla_put_failure;
- if (reset) {
- atomic64_sub(consumed, priv->consumed);
- clear_bit(NFT_QUOTA_DEPLETED_BIT, &priv->flags);
- }
return 0;
nla_put_failure:
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 008/602] netfilter: nf_tables: revert commit_mutex usage in reset path
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (6 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 007/602] netfilter: nft_quota: use atomic64_xchg for reset Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 009/602] drm/virtio: fix deadlock in display_info_cb by removing hotplug from dequeue worker Greg Kroah-Hartman
` (597 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, syzbot+ff16b505ec9152e5f448,
Brian Witte, Florian Westphal, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Brian Witte <brianwitte@mailfence.com>
[ Upstream commit 7f261bb906bf527c4a6e2a646e2d5f3679f2a8bc ]
It causes circular lock dependency between commit_mutex, nfnl_subsys_ipset
and nlk_cb_mutex when nft reset, ipset list, and iptables-nft with '-m set'
rule run at the same time.
Previous patches made it safe to run individual reset handlers concurrently
so commit_mutex is no longer required to prevent this.
Fixes: bd662c4218f9 ("netfilter: nf_tables: Add locking for NFT_MSG_GETOBJ_RESET requests")
Fixes: 3d483faa6663 ("netfilter: nf_tables: Add locking for NFT_MSG_GETSETELEM_RESET requests")
Fixes: 3cb03edb4de3 ("netfilter: nf_tables: Add locking for NFT_MSG_GETRULE_RESET requests")
Link: https://lore.kernel.org/all/aUh_3mVRV8OrGsVo@strlen.de/
Reported-by: <syzbot+ff16b505ec9152e5f448@syzkaller.appspotmail.com>
Closes: https://syzkaller.appspot.com/bug?extid=ff16b505ec9152e5f448
Signed-off-by: Brian Witte <brianwitte@mailfence.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/netfilter/nf_tables_api.c | 248 ++++++----------------------------
1 file changed, 42 insertions(+), 206 deletions(-)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 838c9f49e4e01a..09969379c43a73 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -3719,23 +3719,6 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
return skb->len;
}
-static int nf_tables_dumpreset_rules(struct sk_buff *skb,
- struct netlink_callback *cb)
-{
- struct nftables_pernet *nft_net = nft_pernet(sock_net(skb->sk));
- int ret;
-
- /* Mutex is held is to prevent that two concurrent dump-and-reset calls
- * do not underrun counters and quotas. The commit_mutex is used for
- * the lack a better lock, this is not transaction path.
- */
- mutex_lock(&nft_net->commit_mutex);
- ret = nf_tables_dump_rules(skb, cb);
- mutex_unlock(&nft_net->commit_mutex);
-
- return ret;
-}
-
static int nf_tables_dump_rules_start(struct netlink_callback *cb)
{
struct nft_rule_dump_ctx *ctx = (void *)cb->ctx;
@@ -3755,16 +3738,10 @@ static int nf_tables_dump_rules_start(struct netlink_callback *cb)
return -ENOMEM;
}
}
- return 0;
-}
-
-static int nf_tables_dumpreset_rules_start(struct netlink_callback *cb)
-{
- struct nft_rule_dump_ctx *ctx = (void *)cb->ctx;
-
- ctx->reset = true;
+ if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == NFT_MSG_GETRULE_RESET)
+ ctx->reset = true;
- return nf_tables_dump_rules_start(cb);
+ return 0;
}
static int nf_tables_dump_rules_done(struct netlink_callback *cb)
@@ -3830,6 +3807,8 @@ static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,
u32 portid = NETLINK_CB(skb).portid;
struct net *net = info->net;
struct sk_buff *skb2;
+ bool reset = false;
+ char *buf;
if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
struct netlink_dump_control c = {
@@ -3843,47 +3822,16 @@ static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,
return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
}
- skb2 = nf_tables_getrule_single(portid, info, nla, false);
- if (IS_ERR(skb2))
- return PTR_ERR(skb2);
-
- return nfnetlink_unicast(skb2, net, portid);
-}
-
-static int nf_tables_getrule_reset(struct sk_buff *skb,
- const struct nfnl_info *info,
- const struct nlattr * const nla[])
-{
- struct nftables_pernet *nft_net = nft_pernet(info->net);
- u32 portid = NETLINK_CB(skb).portid;
- struct net *net = info->net;
- struct sk_buff *skb2;
- char *buf;
-
- if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
- struct netlink_dump_control c = {
- .start= nf_tables_dumpreset_rules_start,
- .dump = nf_tables_dumpreset_rules,
- .done = nf_tables_dump_rules_done,
- .module = THIS_MODULE,
- .data = (void *)nla,
- };
-
- return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
- }
-
- if (!try_module_get(THIS_MODULE))
- return -EINVAL;
- rcu_read_unlock();
- mutex_lock(&nft_net->commit_mutex);
- skb2 = nf_tables_getrule_single(portid, info, nla, true);
- mutex_unlock(&nft_net->commit_mutex);
- rcu_read_lock();
- module_put(THIS_MODULE);
+ if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_GETRULE_RESET)
+ reset = true;
+ skb2 = nf_tables_getrule_single(portid, info, nla, reset);
if (IS_ERR(skb2))
return PTR_ERR(skb2);
+ if (!reset)
+ return nfnetlink_unicast(skb2, net, portid);
+
buf = kasprintf(GFP_ATOMIC, "%.*s:%u",
nla_len(nla[NFTA_RULE_TABLE]),
(char *)nla_data(nla[NFTA_RULE_TABLE]),
@@ -6107,6 +6055,10 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
nla_nest_end(skb, nest);
nlmsg_end(skb, nlh);
+ if (dump_ctx->reset && args.iter.count > args.iter.skip)
+ audit_log_nft_set_reset(table, cb->seq,
+ args.iter.count - args.iter.skip);
+
rcu_read_unlock();
if (args.iter.err && args.iter.err != -EMSGSIZE)
@@ -6122,26 +6074,6 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
return -ENOSPC;
}
-static int nf_tables_dumpreset_set(struct sk_buff *skb,
- struct netlink_callback *cb)
-{
- struct nftables_pernet *nft_net = nft_pernet(sock_net(skb->sk));
- struct nft_set_dump_ctx *dump_ctx = cb->data;
- int ret, skip = cb->args[0];
-
- mutex_lock(&nft_net->commit_mutex);
-
- ret = nf_tables_dump_set(skb, cb);
-
- if (cb->args[0] > skip)
- audit_log_nft_set_reset(dump_ctx->ctx.table, cb->seq,
- cb->args[0] - skip);
-
- mutex_unlock(&nft_net->commit_mutex);
-
- return ret;
-}
-
static int nf_tables_dump_set_start(struct netlink_callback *cb)
{
struct nft_set_dump_ctx *dump_ctx = cb->data;
@@ -6385,8 +6317,13 @@ static int nf_tables_getsetelem(struct sk_buff *skb,
{
struct netlink_ext_ack *extack = info->extack;
struct nft_set_dump_ctx dump_ctx;
+ int rem, err = 0, nelems = 0;
+ struct net *net = info->net;
struct nlattr *attr;
- int rem, err = 0;
+ bool reset = false;
+
+ if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_GETSETELEM_RESET)
+ reset = true;
if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
struct netlink_dump_control c = {
@@ -6396,7 +6333,7 @@ static int nf_tables_getsetelem(struct sk_buff *skb,
.module = THIS_MODULE,
};
- err = nft_set_dump_ctx_init(&dump_ctx, skb, info, nla, false);
+ err = nft_set_dump_ctx_init(&dump_ctx, skb, info, nla, reset);
if (err)
return err;
@@ -6407,75 +6344,21 @@ static int nf_tables_getsetelem(struct sk_buff *skb,
if (!nla[NFTA_SET_ELEM_LIST_ELEMENTS])
return -EINVAL;
- err = nft_set_dump_ctx_init(&dump_ctx, skb, info, nla, false);
+ err = nft_set_dump_ctx_init(&dump_ctx, skb, info, nla, reset);
if (err)
return err;
nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
- err = nft_get_set_elem(&dump_ctx.ctx, dump_ctx.set, attr, false);
- if (err < 0) {
- NL_SET_BAD_ATTR(extack, attr);
- break;
- }
- }
-
- return err;
-}
-
-static int nf_tables_getsetelem_reset(struct sk_buff *skb,
- const struct nfnl_info *info,
- const struct nlattr * const nla[])
-{
- struct nftables_pernet *nft_net = nft_pernet(info->net);
- struct netlink_ext_ack *extack = info->extack;
- struct nft_set_dump_ctx dump_ctx;
- int rem, err = 0, nelems = 0;
- struct nlattr *attr;
-
- if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
- struct netlink_dump_control c = {
- .start = nf_tables_dump_set_start,
- .dump = nf_tables_dumpreset_set,
- .done = nf_tables_dump_set_done,
- .module = THIS_MODULE,
- };
-
- err = nft_set_dump_ctx_init(&dump_ctx, skb, info, nla, true);
- if (err)
- return err;
-
- c.data = &dump_ctx;
- return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
- }
-
- if (!nla[NFTA_SET_ELEM_LIST_ELEMENTS])
- return -EINVAL;
-
- if (!try_module_get(THIS_MODULE))
- return -EINVAL;
- rcu_read_unlock();
- mutex_lock(&nft_net->commit_mutex);
- rcu_read_lock();
-
- err = nft_set_dump_ctx_init(&dump_ctx, skb, info, nla, true);
- if (err)
- goto out_unlock;
-
- nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
- err = nft_get_set_elem(&dump_ctx.ctx, dump_ctx.set, attr, true);
+ err = nft_get_set_elem(&dump_ctx.ctx, dump_ctx.set, attr, reset);
if (err < 0) {
NL_SET_BAD_ATTR(extack, attr);
break;
}
nelems++;
}
- audit_log_nft_set_reset(dump_ctx.ctx.table, nft_base_seq(info->net), nelems);
-
-out_unlock:
- rcu_read_unlock();
- mutex_unlock(&nft_net->commit_mutex);
- rcu_read_lock();
- module_put(THIS_MODULE);
+ if (reset)
+ audit_log_nft_set_reset(dump_ctx.ctx.table, nft_base_seq(net),
+ nelems);
return err;
}
@@ -8182,19 +8065,6 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)
return skb->len;
}
-static int nf_tables_dumpreset_obj(struct sk_buff *skb,
- struct netlink_callback *cb)
-{
- struct nftables_pernet *nft_net = nft_pernet(sock_net(skb->sk));
- int ret;
-
- mutex_lock(&nft_net->commit_mutex);
- ret = nf_tables_dump_obj(skb, cb);
- mutex_unlock(&nft_net->commit_mutex);
-
- return ret;
-}
-
static int nf_tables_dump_obj_start(struct netlink_callback *cb)
{
struct nft_obj_dump_ctx *ctx = (void *)cb->ctx;
@@ -8211,16 +8081,10 @@ static int nf_tables_dump_obj_start(struct netlink_callback *cb)
if (nla[NFTA_OBJ_TYPE])
ctx->type = ntohl(nla_get_be32(nla[NFTA_OBJ_TYPE]));
- return 0;
-}
-
-static int nf_tables_dumpreset_obj_start(struct netlink_callback *cb)
-{
- struct nft_obj_dump_ctx *ctx = (void *)cb->ctx;
-
- ctx->reset = true;
+ if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET)
+ ctx->reset = true;
- return nf_tables_dump_obj_start(cb);
+ return 0;
}
static int nf_tables_dump_obj_done(struct netlink_callback *cb)
@@ -8282,42 +8146,16 @@ nf_tables_getobj_single(u32 portid, const struct nfnl_info *info,
static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info,
const struct nlattr * const nla[])
{
- u32 portid = NETLINK_CB(skb).portid;
- struct sk_buff *skb2;
-
- if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
- struct netlink_dump_control c = {
- .start = nf_tables_dump_obj_start,
- .dump = nf_tables_dump_obj,
- .done = nf_tables_dump_obj_done,
- .module = THIS_MODULE,
- .data = (void *)nla,
- };
-
- return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
- }
-
- skb2 = nf_tables_getobj_single(portid, info, nla, false);
- if (IS_ERR(skb2))
- return PTR_ERR(skb2);
-
- return nfnetlink_unicast(skb2, info->net, portid);
-}
-
-static int nf_tables_getobj_reset(struct sk_buff *skb,
- const struct nfnl_info *info,
- const struct nlattr * const nla[])
-{
- struct nftables_pernet *nft_net = nft_pernet(info->net);
u32 portid = NETLINK_CB(skb).portid;
struct net *net = info->net;
struct sk_buff *skb2;
+ bool reset = false;
char *buf;
if (info->nlh->nlmsg_flags & NLM_F_DUMP) {
struct netlink_dump_control c = {
- .start = nf_tables_dumpreset_obj_start,
- .dump = nf_tables_dumpreset_obj,
+ .start = nf_tables_dump_obj_start,
+ .dump = nf_tables_dump_obj,
.done = nf_tables_dump_obj_done,
.module = THIS_MODULE,
.data = (void *)nla,
@@ -8326,18 +8164,16 @@ static int nf_tables_getobj_reset(struct sk_buff *skb,
return nft_netlink_dump_start_rcu(info->sk, skb, info->nlh, &c);
}
- if (!try_module_get(THIS_MODULE))
- return -EINVAL;
- rcu_read_unlock();
- mutex_lock(&nft_net->commit_mutex);
- skb2 = nf_tables_getobj_single(portid, info, nla, true);
- mutex_unlock(&nft_net->commit_mutex);
- rcu_read_lock();
- module_put(THIS_MODULE);
+ if (NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_GETOBJ_RESET)
+ reset = true;
+ skb2 = nf_tables_getobj_single(portid, info, nla, reset);
if (IS_ERR(skb2))
return PTR_ERR(skb2);
+ if (!reset)
+ return nfnetlink_unicast(skb2, net, NETLINK_CB(skb).portid);
+
buf = kasprintf(GFP_ATOMIC, "%.*s:%u",
nla_len(nla[NFTA_OBJ_TABLE]),
(char *)nla_data(nla[NFTA_OBJ_TABLE]),
@@ -9540,7 +9376,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
.policy = nft_rule_policy,
},
[NFT_MSG_GETRULE_RESET] = {
- .call = nf_tables_getrule_reset,
+ .call = nf_tables_getrule,
.type = NFNL_CB_RCU,
.attr_count = NFTA_RULE_MAX,
.policy = nft_rule_policy,
@@ -9594,7 +9430,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
.policy = nft_set_elem_list_policy,
},
[NFT_MSG_GETSETELEM_RESET] = {
- .call = nf_tables_getsetelem_reset,
+ .call = nf_tables_getsetelem,
.type = NFNL_CB_RCU,
.attr_count = NFTA_SET_ELEM_LIST_MAX,
.policy = nft_set_elem_list_policy,
@@ -9640,7 +9476,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
.policy = nft_obj_policy,
},
[NFT_MSG_GETOBJ_RESET] = {
- .call = nf_tables_getobj_reset,
+ .call = nf_tables_getobj,
.type = NFNL_CB_RCU,
.attr_count = NFTA_OBJ_MAX,
.policy = nft_obj_policy,
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 009/602] drm/virtio: fix deadlock in display_info_cb by removing hotplug from dequeue worker
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (7 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 008/602] netfilter: nf_tables: revert commit_mutex usage in reset path Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 010/602] fs/proc/task_mmu: fix make_uffd_wp_huge_pte() prot-update race Greg Kroah-Hartman
` (596 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Dmitry Osipenko, Ryosuke Yasuoka,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryosuke Yasuoka <ryasuoka@redhat.com>
[ Upstream commit d1b894c5bbb3fee0012bd14356286dc2384e8213 ]
A probe-time deadlock can occur between the dequeue worker and
drm_client_register(). During probe, drm_client_register() holds
clientlist_mutex and calls the fbdev hotplug callback, which triggers an
atomic commit that ends up sleeping in virtio_gpu_queue_ctrl_sgs()
waiting for virtqueue space. The dequeue worker that would free that
space calls virtio_gpu_cmd_get_display_info_cb(), which invokes
drm_kms_helper_hotplug_event() -> drm_client_dev_hotplug(), attempting
to acquire the same clientlist_mutex. Since wake_up() is only called
after the resp_cb loop, the probe thread is never woken and both threads
deadlock.
Fix this by removing the hotplug notification from
virtio_gpu_cmd_get_display_info_cb(). The display data (outputs[i].info)
is still updated synchronously in the callback.
For the init path, drm_client_register() already fires an initial
hotplug when the client is registered, which picks up the connector
state updated by display_info_cb.
For the runtime config_changed path, add a wait_event_timeout() in
config_changed_work_func() so that display_info_cb updates the connector
data before the hotplug notification is sent. Also replace
drm_helper_hpd_irq_event() with drm_kms_helper_hotplug_event() since
virtio-gpu never calls drm_kms_helper_poll_init() and thus
drm_helper_hpd_irq_event() always returns false without doing anything.
Fixes: 27655b9bb9f0 ("drm/client: Send hotplug event after registering a client")
Closes: https://syzkaller.appspot.com/bug?id=d6dd6f86d3aaf7eebe7406e45c1c6e549453f224
Closes: https://syzkaller.appspot.com/bug?id=908bd910da5dd79b88de4cf7baf376cc873a922e
Suggested-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Signed-off-by: Ryosuke Yasuoka <ryasuoka@redhat.com>
Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Link: https://patch.msgid.link/20260713-virtiogpu_syzbot-v2-1-2958fa37d46d@redhat.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/virtio/virtgpu_kms.c | 5 ++++-
drivers/gpu/drm/virtio/virtgpu_vq.c | 3 ---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c
index 7dfb2006c561ca..ec31a41d33d678 100644
--- a/drivers/gpu/drm/virtio/virtgpu_kms.c
+++ b/drivers/gpu/drm/virtio/virtgpu_kms.c
@@ -48,7 +48,10 @@ static void virtio_gpu_config_changed_work_func(struct work_struct *work)
virtio_gpu_cmd_get_edids(vgdev);
virtio_gpu_cmd_get_display_info(vgdev);
virtio_gpu_notify(vgdev);
- drm_helper_hpd_irq_event(vgdev->ddev);
+ wait_event_timeout(vgdev->resp_wq,
+ !vgdev->display_info_pending,
+ 5 * HZ);
+ drm_kms_helper_hotplug_event(vgdev->ddev);
}
events_clear |= VIRTIO_GPU_EVENT_DISPLAY;
}
diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
index 0d3d0d09f39b9f..bcc070b478d30e 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -669,9 +669,6 @@ static void virtio_gpu_cmd_get_display_info_cb(struct virtio_gpu_device *vgdev,
vgdev->display_info_pending = false;
spin_unlock(&vgdev->display_info_lock);
wake_up(&vgdev->resp_wq);
-
- if (!drm_helper_hpd_irq_event(vgdev->ddev))
- drm_kms_helper_hotplug_event(vgdev->ddev);
}
static void virtio_gpu_cmd_get_capset_info_cb(struct virtio_gpu_device *vgdev,
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 010/602] fs/proc/task_mmu: fix make_uffd_wp_huge_pte() prot-update race
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (8 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 009/602] drm/virtio: fix deadlock in display_info_cb by removing hotplug from dequeue worker Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 011/602] seqlock: Cure some more scoped_seqlock() optimization fails Greg Kroah-Hartman
` (595 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Kiryl Shutsemau, Sashiko AI review,
Lorenzo Stoakes, Dev Jain, David Hildenbrand, Michal Hocko,
Mike Rapoport, Peter Xu, Suren Baghdasaryan, Vlastimil Babka,
Balbir Singh, Andrew Morton, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kiryl Shutsemau <kas@kernel.org>
commit 04718f7c9290f95385f0dd328758753dc1c36dec upstream.
Patch series "userfaultfd/pagemap: pre-existing fixes".
These are pre-existing bug fixes that were carried at the front of the
userfaultfd RWP working-set-tracking series up to v5 [1]. Per review
feedback that fixes should not sit in the middle of a feature series, they
are split out and sent on their own; the RWP series is reposted rebased on
top of this.
All six were flagged by the Sashiko AI review of the RWP series and carry
Reported-by: Sashiko AI review <sashiko-bot@kernel.org>. They are
independent of RWP, apply to mm-new directly, and carry Cc: stable@.
1: fs/proc/task_mmu: a missing huge_ptep_modify_prot_start() in
make_uffd_wp_huge_pte() can lose hardware Dirty/Accessed updates
when PAGEMAP_SCAN write-protects a hugetlb PTE.
2: fs/proc/task_mmu: pagemap_scan_hugetlb_entry() compares the range
against HPAGE_SIZE rather than the hstate page size, so it never
write-protects gigantic hugetlb pages.
3: fs/proc/task_mmu: PAGEMAP_SCAN with PM_SCAN_WP_MATCHING over an
unpopulated hugetlb range self-deadlocks -- pagemap_scan_pte_hole()
calls uffd_wp_range() while walk_hugetlb_range() holds the hugetlb
vma lock for read, and hugetlb_change_protection() then takes it
for write. Install the marker inline instead.
4: mm/huge_memory: change_non_present_huge_pmd() drops pmd_swp_uffd_wp
on a device-private PMD permission downgrade, silently losing the
uffd-wp marker.
5: userfaultfd: must_wait() applies pte_write() to a locklessly read
PTE without checking pte_present(), so swap/migration entries
decode random offset bits and a thread can stay parked on a stale
fault.
6: userfaultfd: __VMA_UFFD_FLAGS feeds VMA_UFFD_MINOR_BIT (41) to
mk_vma_flags() unconditionally, an out-of-bounds write into the
single-word vma_flags_t on 32-bit. Build the mask from config-gated
per-mode masks so an unavailable bit is never materialised.
This patch (of 6):
make_uffd_wp_huge_pte() arms the UFFD_WP bit on a present HugeTLB PTE by
calling huge_ptep_modify_prot_commit() with a ptent snapshot that was
fetched without the corresponding huge_ptep_modify_prot_start(). The
start helper is what atomically clears the entry so the kernel-owned
snapshot stays consistent until the commit; without it, the hardware may
set Dirty or Accessed in the live PTE between the original read and the
commit, and huge_ptep_modify_prot_commit() (whose generic implementation
just calls set_huge_pte_at()) then writes the stale snapshot back over the
live hardware bits, losing the update.
The non-hugetlb sibling make_uffd_wp_pte() does this correctly via
ptep_modify_prot_start() / ptep_modify_prot_commit(). Mirror that pattern
for the present-PTE branch. The migration case stays as-is -- migration
entries are non-present, so there's no hardware update to race against.
Link: https://lore.kernel.org/20260529172331.356655-1-kas@kernel.org
Link: https://lore.kernel.org/20260529172331.356655-2-kas@kernel.org
Link: https://lore.kernel.org/all/20260526130509.2748441-1-kirill@shutemov.name/ [1]
Fixes: 52526ca7fdb9 ("fs/proc/task_mmu: implement IOCTL to get and optionally clear info about PTEs")
Signed-off-by: Kiryl Shutsemau <kas@kernel.org>
Reported-by: Sashiko AI review <sashiko-bot@kernel.org>
Reviewed-by: Lorenzo Stoakes <ljs@kernel.org>
Reviewed-by: Dev Jain <dev.jain@arm.com>
Cc: David Hildenbrand <david@kernel.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Peter Xu <peterx@redhat.com>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: Balbir Singh <balbirs@nvidia.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
[ kas: adapt to the pre-softleaf idiom; apply the
huge_ptep_modify_prot_start()/commit() fix to the present-PTE
(!huge_pte_none()) branch ]
Signed-off-by: Kiryl Shutsemau (Meta) <kas@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/proc/task_mmu.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 673b7d0fcfd8fa..bc127f1ad4bb28 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -2254,15 +2254,19 @@ static void make_uffd_wp_huge_pte(struct vm_area_struct *vma,
psize = huge_page_size(hstate_vma(vma));
- if (is_hugetlb_entry_migration(ptent))
+ if (is_hugetlb_entry_migration(ptent)) {
set_huge_pte_at(vma->vm_mm, addr, ptep,
pte_swp_mkuffd_wp(ptent), psize);
- else if (!huge_pte_none(ptent))
- huge_ptep_modify_prot_commit(vma, addr, ptep, ptent,
- huge_pte_mkuffd_wp(ptent));
- else
+ } else if (!huge_pte_none(ptent)) {
+ pte_t old_pte, new_pte;
+
+ old_pte = huge_ptep_modify_prot_start(vma, addr, ptep);
+ new_pte = huge_pte_mkuffd_wp(old_pte);
+ huge_ptep_modify_prot_commit(vma, addr, ptep, old_pte, new_pte);
+ } else {
set_huge_pte_at(vma->vm_mm, addr, ptep,
make_pte_marker(PTE_MARKER_UFFD_WP), psize);
+ }
}
#endif /* CONFIG_HUGETLB_PAGE */
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 011/602] seqlock: Cure some more scoped_seqlock() optimization fails
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (9 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 010/602] fs/proc/task_mmu: fix make_uffd_wp_huge_pte() prot-update race Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 012/602] seqlock: Allow KASAN to fail optimizing Greg Kroah-Hartman
` (594 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Arnd Bergmann,
Peter Zijlstra (Intel), Ingo Molnar, Oleg Nesterov
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Zijlstra <peterz@infradead.org>
commit 90dfeef1cd38dff19f8b3a752d13bfd79f0f7694 upstream.
Arnd reported an x86 randconfig using gcc-15 tripped over
__scoped_seqlock_bug(). Turns out GCC chose not to inline the
scoped_seqlock helper functions and as such was not able to optimize
properly.
[ mingo: Clang fails the build too in some circumstances. ]
Reported-by: Arnd Bergmann <arnd@arndb.de>
Tested-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Link: https://patch.msgid.link/20251204104332.GG2528459@noisy.programming.kicks-ass.net
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/seqlock.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -1201,7 +1201,7 @@ struct ss_tmp {
spinlock_t *lock_irqsave;
};
-static inline void __scoped_seqlock_cleanup(struct ss_tmp *sst)
+static __always_inline void __scoped_seqlock_cleanup(struct ss_tmp *sst)
{
if (sst->lock)
spin_unlock(sst->lock);
@@ -1226,7 +1226,7 @@ static inline void __scoped_seqlock_bug(
extern void __scoped_seqlock_bug(void);
#endif
-static inline void
+static __always_inline void
__scoped_seqlock_next(struct ss_tmp *sst, seqlock_t *lock, enum ss_state target)
{
switch (sst->state) {
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 012/602] seqlock: Allow KASAN to fail optimizing
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (10 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 011/602] seqlock: Cure some more scoped_seqlock() optimization fails Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 013/602] seqlock: Allow UBSAN_ALIGNMENT " Greg Kroah-Hartman
` (593 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, kernel test robot,
Peter Zijlstra (Intel)
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Zijlstra <peterz@infradead.org>
commit b94d45b6bbb42571ec225d3be0e7457c8765a5b4 upstream.
Some KASAN builds are failing to properly optimize this code --
luckily we don't care about core quality for KASAN builds, so just
exclude it.
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Closes: https://lore.kernel.org/oe-kbuild-all/202510251641.idrNXhv5-lkp@intel.com/
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/seqlock.h | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -1211,11 +1211,14 @@ static __always_inline void __scoped_seq
extern void __scoped_seqlock_invalid_target(void);
-#if defined(CONFIG_CC_IS_GCC) && CONFIG_GCC_VERSION < 90000
+#if (defined(CONFIG_CC_IS_GCC) && CONFIG_GCC_VERSION < 90000) || defined(CONFIG_KASAN)
/*
* For some reason some GCC-8 architectures (nios2, alpha) have trouble
* determining that the ss_done state is impossible in __scoped_seqlock_next()
* below.
+ *
+ * Similarly KASAN is known to confuse compilers enough to break this. But we
+ * don't care about code quality for KASAN builds anyway.
*/
static inline void __scoped_seqlock_bug(void) { }
#else
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 013/602] seqlock: Allow UBSAN_ALIGNMENT to fail optimizing
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (11 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 012/602] seqlock: Allow KASAN to fail optimizing Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 014/602] KVM: x86: Check for invalid/obsolete root *after* making MMU pages available Greg Kroah-Hartman
` (592 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Arnd Bergmann, Heiko Carstens,
Peter Zijlstra (Intel)
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Heiko Carstens <hca@linux.ibm.com>
commit 88331c4ec23a28c1006ec532fa64763d4c695e90 upstream.
With gcc-15 and gcc-16 with UBSAN_ALIGNMENT enabled the compiler fails to
inline and optimize __scoped_seqlock_bug() away on s390:
s390x-16.1.0-ld: kernel/sched/build_policy.o: in function `__scoped_seqlock_next':
/.../seqlock.h:1286:(.text+0x22030): undefined reference to `__scoped_seqlock_bug'
Fix this by adding UBSAN_ALIGNMENT to the list of config options where a
not inlined empty __scoped_seqlock_bug() is allowed.
Closes: https://lore.kernel.org/r/20260515092057.810542-1-arnd@kernel.org/
Reported-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://patch.msgid.link/20260519110315.1385307-1-hca@linux.ibm.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/seqlock.h | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -1211,14 +1211,15 @@ static __always_inline void __scoped_seq
extern void __scoped_seqlock_invalid_target(void);
-#if (defined(CONFIG_CC_IS_GCC) && CONFIG_GCC_VERSION < 90000) || defined(CONFIG_KASAN)
+#if (defined(CONFIG_CC_IS_GCC) && CONFIG_GCC_VERSION < 90000) || \
+ defined(CONFIG_KASAN) || defined(CONFIG_UBSAN_ALIGNMENT)
/*
* For some reason some GCC-8 architectures (nios2, alpha) have trouble
* determining that the ss_done state is impossible in __scoped_seqlock_next()
* below.
*
- * Similarly KASAN is known to confuse compilers enough to break this. But we
- * don't care about code quality for KASAN builds anyway.
+ * Similarly KASAN and UBSAN_ALIGNMENT are known to confuse compilers enough
+ * to break this. But we don't care about code quality for such builds anyway.
*/
static inline void __scoped_seqlock_bug(void) { }
#else
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 014/602] KVM: x86: Check for invalid/obsolete root *after* making MMU pages available
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (12 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 013/602] seqlock: Allow UBSAN_ALIGNMENT " Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 015/602] KVM: x86: Only reset TSC Deadline Timer in apic_timer_expired on KVM_RUN Greg Kroah-Hartman
` (591 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Hyunwoo Kim, Sean Christopherson,
Paolo Bonzini
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <seanjc@google.com>
commit 2abd5287f08319fa35764566b15c6e22cb1068db upstream.
Check for a "stale" page fault, i.e. for an invalid and/or obsolete root,
after making MMU pages available for the shadow MMU. If reclaiming shadow
pages zaps an in-use root, i.e. marks it invalid, then KVM will attempt to
map memory into an invalid root. On its own, populating an invalid root is
"fine", but because child shadow pages inherit their parent's role, any
children created during the map/fetch will be created as invalid pages,
thus violating KVM's invariant that invalid pages are never on the list of
active MMU pages.
Note, the underlying flaw has existed since KVM first started tracking
invalid roots in 2008 (commit 2e53d63acba7, "KVM: MMU: ignore zapped root
pagetables"), but the true badness only came along in 2020 (Linux 5.9)
with the invariant that invalid shadow pages can't be on the list of
active pages.
Note #2, inheriting role.invalid when creating child shadow pages is also
far from ideal; that flaw will be addressed separately.
Reported-by: Hyunwoo Kim <imv4bel@gmail.com>
Fixes: f95eec9bed76 ("KVM: x86/mmu: Don't put invalid SPs back on the list of active pages")
Cc: stable@vger.kernel.org
Signed-off-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/x86/kvm/mmu/mmu.c | 9 +++++----
arch/x86/kvm/mmu/paging_tmpl.h | 10 ++++++----
2 files changed, 11 insertions(+), 8 deletions(-)
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -4601,16 +4601,17 @@ static int direct_page_fault(struct kvm_
orig_pfn = fault->pfn;
- r = RET_PF_RETRY;
write_lock(&vcpu->kvm->mmu_lock);
- if (is_page_fault_stale(vcpu, fault))
- goto out_unlock;
-
r = make_mmu_pages_available(vcpu);
if (r)
goto out_unlock;
+ if (is_page_fault_stale(vcpu, fault)) {
+ r = RET_PF_RETRY;
+ goto out_unlock;
+ }
+
r = direct_map(vcpu, fault);
out_unlock:
--- a/arch/x86/kvm/mmu/paging_tmpl.h
+++ b/arch/x86/kvm/mmu/paging_tmpl.h
@@ -839,15 +839,17 @@ static int FNAME(page_fault)(struct kvm_
orig_pfn = fault->pfn;
- r = RET_PF_RETRY;
write_lock(&vcpu->kvm->mmu_lock);
- if (is_page_fault_stale(vcpu, fault))
- goto out_unlock;
-
r = make_mmu_pages_available(vcpu);
if (r)
goto out_unlock;
+
+ if (is_page_fault_stale(vcpu, fault)) {
+ r = RET_PF_RETRY;
+ goto out_unlock;
+ }
+
r = FNAME(fetch)(vcpu, fault, &walker);
out_unlock:
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 015/602] KVM: x86: Only reset TSC Deadline Timer in apic_timer_expired on KVM_RUN
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (13 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 014/602] KVM: x86: Check for invalid/obsolete root *after* making MMU pages available Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 016/602] KVM: nVMX: Hide shadow VMCS right after VMCLEAR Greg Kroah-Hartman
` (590 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Venkatesh Srinivas, James Houghton,
Chao Gao, Paolo Bonzini, David Matlack, Sean Christopherson,
Jim Mattson
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Venkatesh Srinivas <venkateshs@chromium.org>
commit e800decd9c0ac4349bcd8f8f9b29fd21fe93165e upstream.
On Intel platforms with a VMX preemption timer and APICv, if a VMM
calls KVM_GET_LAPIC before KVM_GET_MSRS to save the vCPU state, it is
possible to lose a pending timer interrupt.
If the thread running these ioctls is migrated to another core after
calling KVM_GET_LAPIC but before KVM_GET_MSRS and the guest is using
their LAPIC timer in TSC-deadline mode, not only does the save LAPIC
state not carry the pending interrupt, the TSCDEADLINE MSR will be
zeroed.
After migration across CPUs, KVM_GET_MSRS calls vcpu_load, posting the
interrupt and clearing the MSR:
vcpu_load() ->
kvm_arch_vcpu_load() ->
kvm_lapic_restart_hv_timer() ->
start_hv_timer() ->
apic_timer_expired() ->
kvm_apic_inject_pending_timer_irqs()
. post interrupt into the LAPIC state
. clear IA32_TSCDEADLINE
The saved LAPIC state will be missing the pending interrupt and the saved
MSR will be zero. Oops.
Fix by only posting an interrupt when we're attempting to enter the guest
(vcpu->wants_to_run == true), not for vcpu_load from other paths.
Assisted-by: gemini:gemini-3.1-pro-preview
Debugged-by: David Matlack <dmatlack@google.com>
Debugged-by: Sean Christopherson <seanjc@google.com>
Debugged-by: Jim Mattson <jmattson@google.com>
Debugged-by: James Houghton <jthoughton@google.com>
Signed-off-by: Venkatesh Srinivas <venkateshs@chromium.org>
Message-ID: <20260715234234.15382-2-venkateshs@chromium.org>
Reviewed-by: James Houghton <jthoughton@google.com>
Reviewed-by: Chao Gao <chao.gao@intel.com>
Cc: stable@vger.kernel.org
Fixes: ae95f566b3d2 ("KVM: X86: TSCDEADLINE MSR emulation fastpath", 2020-05-15)
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/x86/kvm/lapic.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1923,7 +1923,7 @@ static void apic_timer_expired(struct kv
if (apic_lvtt_tscdeadline(apic) || ktimer->hv_timer_in_use)
ktimer->expired_tscdeadline = ktimer->tscdeadline;
- if (!from_timer_fn && apic->apicv_active) {
+ if (!from_timer_fn && apic->apicv_active && vcpu->wants_to_run) {
WARN_ON(kvm_get_running_vcpu() != vcpu);
kvm_apic_inject_pending_timer_irqs(apic);
return;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 016/602] KVM: nVMX: Hide shadow VMCS right after VMCLEAR
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (14 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 015/602] KVM: x86: Only reset TSC Deadline Timer in apic_timer_expired on KVM_RUN Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 017/602] KVM: x86/mmu: Fix use-after-free on vendor module reload Greg Kroah-Hartman
` (589 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Hyunwoo Kim, Paolo Bonzini
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hyunwoo Kim <imv4bel@gmail.com>
commit 622ebfac01ba4f9c0060cebd41257fe46fc4a0b3 upstream.
free_nested() frees the shadow VMCS while vmcs01 still points to it. But
because it is asynchronous with respect to loaded_vmcs_clear(), the vCPU
might migrate before the pointer is cleared and __loaded_vmcs_clear()
may then execute VMCLEAR.
The VMCS needs to stay attached until its explicit VMCLEAR completes, but
then it can be hidden and the page safely freed.
Fixes: 355f4fb1405e ("kvm: nVMX: VMCLEAR an active shadow VMCS after last use")
Cc: stable@vger.kernel.org
Signed-off-by: Hyunwoo Kim <imv4bel@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/x86/kvm/vmx/nested.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -325,6 +325,7 @@ static void vmx_switch_vmcs(struct kvm_v
static void free_nested(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
+ struct vmcs *shadow_vmcs;
if (WARN_ON_ONCE(vmx->loaded_vmcs != &vmx->vmcs01))
vmx_switch_vmcs(vcpu, &vmx->vmcs01);
@@ -342,9 +343,15 @@ static void free_nested(struct kvm_vcpu
vmx->nested.current_vmptr = INVALID_GPA;
if (enable_shadow_vmcs) {
vmx_disable_shadow_vmcs(vmx);
- vmcs_clear(vmx->vmcs01.shadow_vmcs);
- free_vmcs(vmx->vmcs01.shadow_vmcs);
+
+ /*
+ * Keep the pointer visible until after VMCLEAR, so migration
+ * can clear an active shadow VMCS on the old CPU.
+ */
+ shadow_vmcs = vmx->vmcs01.shadow_vmcs;
+ vmcs_clear(shadow_vmcs);
vmx->vmcs01.shadow_vmcs = NULL;
+ free_vmcs(shadow_vmcs);
}
kfree(vmx->nested.cached_vmcs12);
vmx->nested.cached_vmcs12 = NULL;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 017/602] KVM: x86/mmu: Fix use-after-free on vendor module reload
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (15 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 016/602] KVM: nVMX: Hide shadow VMCS right after VMCLEAR Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 018/602] can: bcm: add locking when updating filter and timer values Greg Kroah-Hartman
` (588 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Phil Rosenthal, Paolo Bonzini
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Phil Rosenthal <phil@phil.gs>
commit 52f2f7c30126037975389aa04d24c506a5177c35 upstream.
mmu_destroy_caches() destroys pte_list_desc_cache and
mmu_page_header_cache, but leaves both pointers unchanged. The pointers
live in kvm.ko, and therefore survive when a vendor module is unloaded
while kvm.ko remains loaded.
If creation of pte_list_desc_cache fails during a subsequent vendor
module load, its assignment sets pte_list_desc_cache to NULL and the
error path calls mmu_destroy_caches(). mmu_page_header_cache still
points to the cache destroyed during the preceding vendor module
unload. Passing that stale pointer to kmem_cache_destroy() causes a
slab use-after-free.
Reproduce the issue on a v7.1.3 kernel with CONFIG_KASAN=y,
CONFIG_KASAN_GENERIC=y, CONFIG_KVM=m, and CONFIG_KVM_INTEL=m. A
one-shot test hook forces pte_list_desc_cache to NULL on the second
invocation of kvm_mmu_vendor_module_init():
1. Load kvm.ko and kvm-intel.ko, creating both caches.
2. Unload only kvm_intel, leaving kvm.ko loaded.
3. Reload kvm_intel and force initialization through the -ENOMEM path.
KASAN reports:
BUG: KASAN: slab-use-after-free in
kvm_mmu_vendor_module_init+0x5b/0x170 [kvm]
...
kmem_cache_destroy+0x21/0x1d0
kvm_mmu_vendor_module_init+0x5b/0x170 [kvm]
...
Allocated by task 16817:
__kmem_cache_create_args+0x12c/0x3b0
__kmem_cache_create.constprop.0+0xb6/0xf0 [kvm]
kvm_mmu_vendor_module_init+0x13b/0x170 [kvm]
...
Freed by task 16820:
kmem_cache_destroy+0x117/0x1d0
kvm_mmu_vendor_module_exit+0x21/0x30 [kvm]
Clear both pointers immediately after destroying their caches so that
the stored state reflects the caches' lifetime and repeated cleanup is
safe.
With the fix applied, the same injected vendor module reload fails with
-ENOMEM as expected and produces no KASAN report.
Fixes: cb498ea2ce1d ("KVM: Portability: Combine kvm_init and kvm_init_x86")
Cc: stable@vger.kernel.org
Signed-off-by: Phil Rosenthal <phil@phil.gs>
Message-ID: <20260718-kvm-mmu-cache-uaf-v3-1-e103b93c74e1@phil.gs>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/x86/kvm/mmu/mmu.c | 2 ++
1 file changed, 2 insertions(+)
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -7230,7 +7230,9 @@ static struct shrinker *mmu_shrinker;
static void mmu_destroy_caches(void)
{
kmem_cache_destroy(pte_list_desc_cache);
+ pte_list_desc_cache = NULL;
kmem_cache_destroy(mmu_page_header_cache);
+ mmu_page_header_cache = NULL;
}
static void kvm_wake_nx_recovery_thread(struct kvm *kvm)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 018/602] can: bcm: add locking when updating filter and timer values
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (16 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 017/602] KVM: x86/mmu: Fix use-after-free on vendor module reload Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 019/602] can: bcm: fix CAN frame rx/tx statistics Greg Kroah-Hartman
` (587 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, syzbot+75e5e4ae00c3b4bb544e,
Oliver Hartkopp, stable, Marc Kleine-Budde, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oliver Hartkopp <socketcan@hartkopp.net>
commit 749179c2e25b95d22499ed29096b3e02d6dfd2b4 upstream.
KCSAN detected a simultaneous access to timer values that can be
overwritten in bcm_rx_setup() when updating timer and filter content
while bcm_rx_handler(), bcm_rx_timeout_handler() or bcm_rx_thr_handler()
run concurrently on incoming CAN traffic.
Protect the timer (ival1/ival2/kt_ival1/kt_ival2/kt_lastmsg) and filter
(nframes/flags/frames/last_frames) updates in bcm_rx_setup() with a new
per-op bcm_rx_update_lock, taken with the matching scope in the RX
handlers. memcpy_from_msg() is staged into a temporary buffer before the
lock is taken, since it can sleep and must not run under a spinlock.
hrtimer_cancel() is always called without bcm_rx_update_lock held, since
bcm_rx_timeout_handler()/bcm_rx_thr_handler() take the same lock and a
running callback would otherwise deadlock against the canceller.
Also close a related race: bcm_rx_setup() cleared the RTR flag in the
stored reply frame's can_id as a separate, unprotected step after the
frame content was already installed, so a concurrent bcm_rx_handler()
could transmit a stale reply with CAN_RTR_FLAG still set. Fold that
normalization into the initial frame preparation instead (on the staged
buffer for updates, directly on op->frames pre-registration for new
ops), so the installed frame is always atomically self-consistent.
bcm_rx_handler()'s RX_RTR_FRAME check now takes a lock-protected
snapshot of op->flags before deciding whether to call bcm_can_tx(),
but does not hold the lock across that call.
Also take a lock-protected snapshot of the currframe in bcm_can_tx()
to avoid partly overwrites by content updates in bcm_tx_setup().
Finally check if a TX_RESET_MULTI_IDX/SETTIMER might have reset
op->currframe between the two locked sections in bcm_can_tx().
Omit calling hrtimer_forward() with zero interval in bcm_rx_thr_handler().
kt_ival2 may have been concurrently cleared by bcm_rx_setup() before it
cancels this timer, so check kt_ival2 inside the bcm_rx_update_lock.
Fixes: c2aba69d0c36 ("can: bcm: add locking for bcm_op runtime updates")
Reported-by: syzbot+75e5e4ae00c3b4bb544e@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/linux-can/6975d5cf.a00a0220.33ccc7.0022.GAE@google.com/
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://patch.msgid.link/20260714-bcm_fixes-v15-3-562f7e3e42da@hartkopp.net
Cc: stable@kernel.org
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/can/bcm.c | 176 ++++++++++++++++++++++++++++++++++++++------------
1 file changed, 133 insertions(+), 43 deletions(-)
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 03626d1ee665f1..388720ae177213 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -128,6 +128,7 @@ struct bcm_op {
struct sock *sk;
struct net_device *rx_reg_dev;
spinlock_t bcm_tx_lock; /* protect currframe/count in runtime updates */
+ spinlock_t bcm_rx_update_lock; /* protect filter/timer data updates */
};
struct bcm_sock {
@@ -292,21 +293,27 @@ static int bcm_proc_show(struct seq_file *m, void *v)
* bcm_can_tx - send the (next) CAN frame to the appropriate CAN interface
* of the given bcm tx op
*/
-static void bcm_can_tx(struct bcm_op *op)
+static void bcm_can_tx(struct bcm_op *op, struct canfd_frame *cf)
{
struct sk_buff *skb;
struct net_device *dev;
- struct canfd_frame *cf;
+ struct canfd_frame cframe;
+ bool cyclic = !cf;
+ unsigned int idx = 0;
int err;
/* no target device? => exit */
if (!op->ifindex)
return;
- /* read currframe under lock protection */
- spin_lock_bh(&op->bcm_tx_lock);
- cf = op->frames + op->cfsiz * op->currframe;
- spin_unlock_bh(&op->bcm_tx_lock);
+ if (cyclic) {
+ /* read currframe under lock protection */
+ spin_lock_bh(&op->bcm_tx_lock);
+ idx = op->currframe;
+ memcpy(&cframe, op->frames + op->cfsiz * idx, op->cfsiz);
+ cf = &cframe;
+ spin_unlock_bh(&op->bcm_tx_lock);
+ }
dev = dev_get_by_index(sock_net(op->sk), op->ifindex);
if (!dev) {
@@ -335,14 +342,20 @@ static void bcm_can_tx(struct bcm_op *op)
if (!err)
op->frames_abs++;
- op->currframe++;
+ /* only advance the cyclic sequence if nothing reset currframe while
+ * we were sending - a concurrent TX_RESET_MULTI_IDX means this
+ * frame's bookkeeping belongs to a sequence that no longer exists
+ */
+ if (!cyclic || op->currframe == idx) {
+ op->currframe++;
- /* reached last frame? */
- if (op->currframe >= op->nframes)
- op->currframe = 0;
+ /* reached last frame? */
+ if (op->currframe >= op->nframes)
+ op->currframe = 0;
- if (op->count > 0)
- op->count--;
+ if (op->count > 0)
+ op->count--;
+ }
spin_unlock_bh(&op->bcm_tx_lock);
out:
@@ -455,7 +468,7 @@ static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer)
struct bcm_msg_head msg_head;
if (op->kt_ival1 && (op->count > 0)) {
- bcm_can_tx(op);
+ bcm_can_tx(op, NULL);
if (!op->count && (op->flags & TX_COUNTEVT)) {
/* create notification to user */
@@ -472,7 +485,7 @@ static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer)
}
} else if (op->kt_ival2) {
- bcm_can_tx(op);
+ bcm_can_tx(op, NULL);
}
return bcm_tx_set_expiry(op, &op->timer) ?
@@ -616,6 +629,8 @@ static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
struct bcm_msg_head msg_head;
+ spin_lock_bh(&op->bcm_rx_update_lock);
+
/* if user wants to be informed, when cyclic CAN-Messages come back */
if ((op->flags & RX_ANNOUNCE_RESUME) && op->last_frames) {
/* clear received CAN frames to indicate 'nothing received' */
@@ -632,6 +647,8 @@ static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
msg_head.can_id = op->can_id;
msg_head.nframes = 0;
+ spin_unlock_bh(&op->bcm_rx_update_lock);
+
bcm_send_to_user(op, &msg_head, NULL, 0);
return HRTIMER_NORESTART;
@@ -680,15 +697,26 @@ static int bcm_rx_thr_flush(struct bcm_op *op)
static enum hrtimer_restart bcm_rx_thr_handler(struct hrtimer *hrtimer)
{
struct bcm_op *op = container_of(hrtimer, struct bcm_op, thrtimer);
+ enum hrtimer_restart ret;
- if (bcm_rx_thr_flush(op)) {
+ spin_lock_bh(&op->bcm_rx_update_lock);
+
+ /* kt_ival2 may have been concurrently cleared by bcm_rx_setup()
+ * before it cancels this timer - never forward with a zero
+ * interval in that case.
+ */
+ if (bcm_rx_thr_flush(op) && op->kt_ival2) {
hrtimer_forward_now(hrtimer, op->kt_ival2);
- return HRTIMER_RESTART;
+ ret = HRTIMER_RESTART;
} else {
/* rearm throttle handling */
op->kt_lastmsg = 0;
- return HRTIMER_NORESTART;
+ ret = HRTIMER_NORESTART;
}
+
+ spin_unlock_bh(&op->bcm_rx_update_lock);
+
+ return ret;
}
/*
@@ -698,8 +726,10 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)
{
struct bcm_op *op = (struct bcm_op *)data;
const struct canfd_frame *rxframe = (struct canfd_frame *)skb->data;
+ struct canfd_frame rtrframe;
unsigned int i;
unsigned char traffic_flags;
+ bool rtr_frame;
if (op->can_id != rxframe->can_id)
return;
@@ -723,9 +753,18 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)
/* update statistics */
op->frames_abs++;
- if (op->flags & RX_RTR_FRAME) {
+ /* snapshot the flag under lock: op->flags/op->frames may be updated
+ * concurrently by bcm_rx_setup().
+ */
+ spin_lock_bh(&op->bcm_rx_update_lock);
+ rtr_frame = op->flags & RX_RTR_FRAME;
+ if (rtr_frame)
+ memcpy(&rtrframe, op->frames, op->cfsiz);
+ spin_unlock_bh(&op->bcm_rx_update_lock);
+
+ if (rtr_frame) {
/* send reply for RTR-request (placed in op->frames[0]) */
- bcm_can_tx(op);
+ bcm_can_tx(op, &rtrframe);
return;
}
@@ -737,6 +776,8 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)
traffic_flags |= RX_OWN;
}
+ spin_lock_bh(&op->bcm_rx_update_lock);
+
if (op->flags & RX_FILTER_ID) {
/* the easiest case */
bcm_rx_update_and_send(op, op->last_frames, rxframe,
@@ -772,6 +813,8 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)
rx_starttimer:
bcm_rx_starttimer(op);
+
+ spin_unlock_bh(&op->bcm_rx_update_lock);
}
/*
@@ -1115,7 +1158,7 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
list_add_rcu(&op->list, &bo->tx_ops);
if (op->flags & TX_ANNOUNCE)
- bcm_can_tx(op);
+ bcm_can_tx(op, NULL);
if (op->flags & STARTTIMER)
bcm_tx_start_timer(op);
@@ -1129,6 +1172,24 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
return err;
}
+static void bcm_rx_setup_rtr_check(struct bcm_msg_head *msg_head,
+ struct bcm_op *op, void *new_frames)
+{
+ /* funny feature in RX(!)_SETUP only for RTR-mode:
+ * copy can_id into frame BUT without RTR-flag to
+ * prevent a full-load-loopback-test ... ;-]
+ * normalize this on the staged buffer, before it is
+ * ever installed into op->frames.
+ */
+ if (msg_head->flags & RX_RTR_FRAME) {
+ struct canfd_frame *frame0 = new_frames;
+
+ if ((msg_head->flags & TX_CP_CAN_ID) ||
+ frame0->can_id == op->can_id)
+ frame0->can_id = op->can_id & ~CAN_RTR_FLAG;
+ }
+}
+
/*
* bcm_rx_setup - create or update a bcm rx op (for bcm_sendmsg)
*/
@@ -1163,6 +1224,8 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
/* check the given can_id */
op = bcm_find_op(&bo->rx_ops, msg_head, ifindex);
if (op) {
+ void *new_frames = NULL;
+
/* update existing BCM operation */
/*
@@ -1174,19 +1237,48 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
return -E2BIG;
if (msg_head->nframes) {
- /* update CAN frames content */
- err = memcpy_from_msg(op->frames, msg,
+ /* get new CAN frames content before locking */
+ new_frames = kmalloc(msg_head->nframes * op->cfsiz,
+ GFP_KERNEL);
+ if (!new_frames)
+ return -ENOMEM;
+
+ err = memcpy_from_msg(new_frames, msg,
msg_head->nframes * op->cfsiz);
- if (err < 0)
+ if (err < 0) {
+ kfree(new_frames);
return err;
+ }
- /* clear last_frames to indicate 'nothing received' */
- memset(op->last_frames, 0, msg_head->nframes * op->cfsiz);
+ bcm_rx_setup_rtr_check(msg_head, op, new_frames);
}
+ spin_lock_bh(&op->bcm_rx_update_lock);
op->nframes = msg_head->nframes;
op->flags = msg_head->flags;
+ if (msg_head->nframes) {
+ /* update CAN frames content */
+ memcpy(op->frames, new_frames,
+ msg_head->nframes * op->cfsiz);
+
+ /* clear last_frames to indicate 'nothing received' */
+ memset(op->last_frames, 0,
+ msg_head->nframes * op->cfsiz);
+ }
+
+ if (msg_head->flags & SETTIMER) {
+ op->ival1 = msg_head->ival1;
+ op->ival2 = msg_head->ival2;
+ op->kt_ival1 = bcm_timeval_to_ktime(msg_head->ival1);
+ op->kt_ival2 = bcm_timeval_to_ktime(msg_head->ival2);
+ op->kt_lastmsg = 0;
+ }
+ spin_unlock_bh(&op->bcm_rx_update_lock);
+
+ /* free temporary frames / kfree(NULL) is safe */
+ kfree(new_frames);
+
/* Only an update -> do not call can_rx_register() */
do_rx_register = 0;
@@ -1197,6 +1289,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
return -ENOMEM;
spin_lock_init(&op->bcm_tx_lock);
+ spin_lock_init(&op->bcm_rx_update_lock);
op->can_id = msg_head->can_id;
op->nframes = msg_head->nframes;
op->cfsiz = CFSIZ(msg_head->flags);
@@ -1238,6 +1331,8 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
kfree(op);
return err;
}
+
+ bcm_rx_setup_rtr_check(msg_head, op, op->frames);
}
/* bcm_can_tx / bcm_tx_timeout_handler needs this */
@@ -1265,29 +1360,22 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
/* check flags */
if (op->flags & RX_RTR_FRAME) {
- struct canfd_frame *frame0 = op->frames;
-
/* no timers in RTR-mode */
hrtimer_cancel(&op->thrtimer);
hrtimer_cancel(&op->timer);
-
- /*
- * funny feature in RX(!)_SETUP only for RTR-mode:
- * copy can_id into frame BUT without RTR-flag to
- * prevent a full-load-loopback-test ... ;-]
- */
- if ((op->flags & TX_CP_CAN_ID) ||
- (frame0->can_id == op->can_id))
- frame0->can_id = op->can_id & ~CAN_RTR_FLAG;
-
} else {
if (op->flags & SETTIMER) {
- /* set timer value */
- op->ival1 = msg_head->ival1;
- op->ival2 = msg_head->ival2;
- op->kt_ival1 = bcm_timeval_to_ktime(msg_head->ival1);
- op->kt_ival2 = bcm_timeval_to_ktime(msg_head->ival2);
+ /* set timers (locked) for newly created op */
+ if (do_rx_register) {
+ spin_lock_bh(&op->bcm_rx_update_lock);
+ op->ival1 = msg_head->ival1;
+ op->ival2 = msg_head->ival2;
+ op->kt_ival1 = bcm_timeval_to_ktime(msg_head->ival1);
+ op->kt_ival2 = bcm_timeval_to_ktime(msg_head->ival2);
+ op->kt_lastmsg = 0;
+ spin_unlock_bh(&op->bcm_rx_update_lock);
+ }
/* disable an active timer due to zero value? */
if (!op->kt_ival1)
@@ -1297,9 +1385,11 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
* In any case cancel the throttle timer, flush
* potentially blocked msgs and reset throttle handling
*/
- op->kt_lastmsg = 0;
hrtimer_cancel(&op->thrtimer);
+
+ spin_lock_bh(&op->bcm_rx_update_lock);
bcm_rx_thr_flush(op);
+ spin_unlock_bh(&op->bcm_rx_update_lock);
}
if ((op->flags & STARTTIMER) && op->kt_ival1)
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 019/602] can: bcm: fix CAN frame rx/tx statistics
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (17 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 018/602] can: bcm: add locking when updating filter and timer values Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 020/602] can: bcm: extend bcm_tx_lock usage for data and timer updates Greg Kroah-Hartman
` (586 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Oliver Hartkopp, stable,
Marc Kleine-Budde, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oliver Hartkopp <socketcan@hartkopp.net>
commit e6c24ba95fc3f1b5e1dcd28b1c6e59ef61a9daa5 upstream.
KCSAN detected a data race within the bcm_rx_handler() when two CAN frames
have been simultaneously received and processed in a single rx op by two
different CPUs.
Use atomic operations with (signed) long data types to access the
statistics in the hot path to fix the KCSAN complaint.
Additionally simplify the update and check of statistics overflow by
using the atomic operations in separate bcm_update_[rx|tx]_stats()
functions. The rx variant runs under bcm_rx_update_lock to prevent
races when resetting the two rx counters; the tx variant runs under
bcm_tx_lock and only needs to guard its own counter's overflow.
As the rx path resets its values already at LONG_MAX / 100, there is
no conflict between the two locking domains (bcm_rx_update_lock vs.
bcm_tx_lock) even for ops that use both paths.
The rx statistics update and the frames_filtered update in
bcm_rx_changed() were previously performed in two separate
bcm_rx_update_lock sections. For an rx op subscribed on all interfaces
(ifindex == 0), bcm_rx_handler() can run concurrently on different
CPUs, so a counter reset by one CPU between these two sections could
leave frames_filtered larger than frames_abs on another CPU, producing
a bogus (even negative) reduction percentage in procfs. Update the
statistics in the same critical section as bcm_rx_changed() to close
this gap, which also removes the now unneeded extra lock/unlock pair
around the traffic_flags calculation.
Fixes: ffd980f976e7 ("[CAN]: Add broadcast manager (bcm) protocol")
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://patch.msgid.link/20260714-bcm_fixes-v15-4-562f7e3e42da@hartkopp.net
Cc: stable@kernel.org
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/can/bcm.c | 69 ++++++++++++++++++++++++++++++++++-----------------
1 file changed, 46 insertions(+), 23 deletions(-)
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 388720ae177213..9982f1b9ac4620 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -111,7 +111,7 @@ struct bcm_op {
int ifindex;
canid_t can_id;
u32 flags;
- unsigned long frames_abs, frames_filtered;
+ atomic_long_t frames_abs, frames_filtered;
struct bcm_timeval ival1, ival2;
struct hrtimer timer, thrtimer;
ktime_t rx_stamp, kt_ival1, kt_ival2, kt_lastmsg;
@@ -228,10 +228,13 @@ static int bcm_proc_show(struct seq_file *m, void *v)
list_for_each_entry_rcu(op, &bo->rx_ops, list) {
- unsigned long reduction;
+ long reduction, frames_filtered, frames_abs;
+
+ frames_filtered = atomic_long_read(&op->frames_filtered);
+ frames_abs = atomic_long_read(&op->frames_abs);
/* print only active entries & prevent division by zero */
- if (!op->frames_abs)
+ if (!frames_abs)
continue;
seq_printf(m, "rx_op: %03X %-5s ", op->can_id,
@@ -253,9 +256,9 @@ static int bcm_proc_show(struct seq_file *m, void *v)
(long long)ktime_to_us(op->kt_ival2));
seq_printf(m, "# recv %ld (%ld) => reduction: ",
- op->frames_filtered, op->frames_abs);
+ frames_filtered, frames_abs);
- reduction = 100 - (op->frames_filtered * 100) / op->frames_abs;
+ reduction = 100 - (frames_filtered * 100) / frames_abs;
seq_printf(m, "%s%ld%%\n",
(reduction == 100) ? "near " : "", reduction);
@@ -279,7 +282,8 @@ static int bcm_proc_show(struct seq_file *m, void *v)
seq_printf(m, "t2=%lld ",
(long long)ktime_to_us(op->kt_ival2));
- seq_printf(m, "# sent %ld\n", op->frames_abs);
+ seq_printf(m, "# sent %ld\n",
+ atomic_long_read(&op->frames_abs));
}
seq_putc(m, '\n');
@@ -289,6 +293,24 @@ static int bcm_proc_show(struct seq_file *m, void *v)
}
#endif /* CONFIG_PROC_FS */
+static void bcm_update_rx_stats(struct bcm_op *op)
+{
+ /* prevent overflow of the reduction% calculation in bcm_proc_show() */
+ if (atomic_long_inc_return(&op->frames_abs) > LONG_MAX / 100) {
+ atomic_long_set(&op->frames_filtered, 0);
+ atomic_long_set(&op->frames_abs, 0);
+ }
+}
+
+static void bcm_update_tx_stats(struct bcm_op *op)
+{
+ /* tx_op has no reduction% calculation - use the full range and
+ * just keep the displayed counter non-negative on overflow
+ */
+ if (atomic_long_inc_return(&op->frames_abs) == LONG_MAX)
+ atomic_long_set(&op->frames_abs, 0);
+}
+
/*
* bcm_can_tx - send the (next) CAN frame to the appropriate CAN interface
* of the given bcm tx op
@@ -340,7 +362,7 @@ static void bcm_can_tx(struct bcm_op *op, struct canfd_frame *cf)
spin_lock_bh(&op->bcm_tx_lock);
if (!err)
- op->frames_abs++;
+ bcm_update_tx_stats(op);
/* only advance the cyclic sequence if nothing reset currframe while
* we were sending - a concurrent TX_RESET_MULTI_IDX means this
@@ -499,12 +521,9 @@ static void bcm_rx_changed(struct bcm_op *op, struct canfd_frame *data)
{
struct bcm_msg_head head;
- /* update statistics */
- op->frames_filtered++;
-
- /* prevent statistics overflow */
- if (op->frames_filtered > ULONG_MAX/100)
- op->frames_filtered = op->frames_abs = 0;
+ /* update statistics (frames_filtered <= frames_abs) */
+ if (atomic_long_read(&op->frames_abs))
+ atomic_long_inc(&op->frames_filtered);
/* this element is not throttled anymore */
data->flags &= ~RX_THR;
@@ -750,24 +769,30 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)
op->rx_stamp = skb->tstamp;
/* save originator for recvfrom() */
op->rx_ifindex = skb->dev->ifindex;
- /* update statistics */
- op->frames_abs++;
- /* snapshot the flag under lock: op->flags/op->frames may be updated
- * concurrently by bcm_rx_setup().
- */
+ /* op->flags/op->frames may be updated concurrently by bcm_rx_setup() */
spin_lock_bh(&op->bcm_rx_update_lock);
+
rtr_frame = op->flags & RX_RTR_FRAME;
- if (rtr_frame)
+ if (rtr_frame) {
+ bcm_update_rx_stats(op);
+ /* snapshot RTR content under lock */
memcpy(&rtrframe, op->frames, op->cfsiz);
- spin_unlock_bh(&op->bcm_rx_update_lock);
+ spin_unlock_bh(&op->bcm_rx_update_lock);
- if (rtr_frame) {
/* send reply for RTR-request (placed in op->frames[0]) */
bcm_can_tx(op, &rtrframe);
return;
}
+ /* update statistics in the same critical section as bcm_rx_changed()
+ * below: frames_filtered must never be checked/incremented against a
+ * frames_abs snapshot from a concurrent bcm_rx_handler() call on
+ * another CPU for the same (wildcard) op, or frames_filtered can end
+ * up larger than frames_abs.
+ */
+ bcm_update_rx_stats(op);
+
/* compute flags to distinguish between own/local/remote CAN traffic */
traffic_flags = 0;
if (skb->sk) {
@@ -776,8 +801,6 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)
traffic_flags |= RX_OWN;
}
- spin_lock_bh(&op->bcm_rx_update_lock);
-
if (op->flags & RX_FILTER_ID) {
/* the easiest case */
bcm_rx_update_and_send(op, op->last_frames, rxframe,
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 020/602] can: bcm: extend bcm_tx_lock usage for data and timer updates
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (18 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 019/602] can: bcm: fix CAN frame rx/tx statistics Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 021/602] can: bcm: validate frame length in bcm_rx_setup() for RTR replies Greg Kroah-Hartman
` (585 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Oliver Hartkopp, stable,
Marc Kleine-Budde, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oliver Hartkopp <socketcan@hartkopp.net>
commit 12ce799f7ab1e05bd8fbf79e46f403bfe5597ebc upstream.
Stage new CAN frame content for an existing tx op into a kmalloc()'d
buffer and validate it there, mirroring the approach already used in
bcm_rx_setup(). Only copy the validated data into op->frames while
holding op->bcm_tx_lock, so bcm_can_tx() and bcm_tx_timeout_handler()
can no longer observe a partially updated or unvalidated frame.
Add a missing error path for memcpy_from_msg() when copying CAN frame
data from userspace.
Also move the kt_ival1/kt_ival2/ival1/ival2 updates in bcm_tx_setup()
under op->bcm_tx_lock, and read kt_ival1/kt_ival2/count under the same
lock in bcm_tx_set_expiry() and bcm_tx_timeout_handler(), closing the
torn 64-bit ktime_t read on 32-bit platforms.
Fixes: c2aba69d0c36 ("can: bcm: add locking for bcm_op runtime updates")
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://patch.msgid.link/20260714-bcm_fixes-v15-6-562f7e3e42da@hartkopp.net
Cc: stable@kernel.org
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/can/bcm.c | 104 ++++++++++++++++++++++++++++++++++++--------------
1 file changed, 75 insertions(+), 29 deletions(-)
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 9982f1b9ac4620..e8fb31b24bb2ae 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -127,7 +127,7 @@ struct bcm_op {
struct canfd_frame last_sframe;
struct sock *sk;
struct net_device *rx_reg_dev;
- spinlock_t bcm_tx_lock; /* protect currframe/count in runtime updates */
+ spinlock_t bcm_tx_lock; /* protect tx data and timer updates */
spinlock_t bcm_rx_update_lock; /* protect filter/timer data updates */
};
@@ -466,12 +466,18 @@ static bool bcm_tx_set_expiry(struct bcm_op *op, struct hrtimer *hrt)
{
ktime_t ival;
+ spin_lock_bh(&op->bcm_tx_lock);
+
if (op->kt_ival1 && op->count)
ival = op->kt_ival1;
- else if (op->kt_ival2)
+ else if (op->kt_ival2) {
ival = op->kt_ival2;
- else
+ } else {
+ spin_unlock_bh(&op->bcm_tx_lock);
return false;
+ }
+
+ spin_unlock_bh(&op->bcm_tx_lock);
hrtimer_set_expires(hrt, ktime_add(ktime_get(), ival));
return true;
@@ -488,25 +494,47 @@ static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer)
{
struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer);
struct bcm_msg_head msg_head;
+ bool tx_ival1, tx_ival2;
+
+ /* snapshot kt_ival1/kt_ival2/count under lock to avoid torn
+ * ktime_t reads racing with concurrent bcm_tx_setup() updates
+ */
+ spin_lock_bh(&op->bcm_tx_lock);
+ tx_ival1 = op->kt_ival1 && (op->count > 0);
+ tx_ival2 = !!op->kt_ival2;
+ spin_unlock_bh(&op->bcm_tx_lock);
+
+ if (tx_ival1) {
+ u32 flags, count;
+ struct bcm_timeval ival1, ival2;
- if (op->kt_ival1 && (op->count > 0)) {
bcm_can_tx(op, NULL);
- if (!op->count && (op->flags & TX_COUNTEVT)) {
+ /* snapshot variables under lock to avoid torn reads racing
+ * with concurrent bcm_tx_setup() updates
+ */
+ spin_lock_bh(&op->bcm_tx_lock);
+ flags = op->flags;
+ count = op->count;
+ ival1 = op->ival1;
+ ival2 = op->ival2;
+ spin_unlock_bh(&op->bcm_tx_lock);
+
+ if (!count && (flags & TX_COUNTEVT)) {
/* create notification to user */
memset(&msg_head, 0, sizeof(msg_head));
msg_head.opcode = TX_EXPIRED;
- msg_head.flags = op->flags;
- msg_head.count = op->count;
- msg_head.ival1 = op->ival1;
- msg_head.ival2 = op->ival2;
+ msg_head.flags = flags;
+ msg_head.count = count;
+ msg_head.ival1 = ival1;
+ msg_head.ival2 = ival2;
msg_head.can_id = op->can_id;
msg_head.nframes = 0;
bcm_send_to_user(op, &msg_head, NULL, 0);
}
- } else if (op->kt_ival2) {
+ } else if (tx_ival2) {
bcm_can_tx(op, NULL);
}
@@ -1030,6 +1058,8 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
/* check the given can_id */
op = bcm_find_op(&bo->tx_ops, msg_head, ifindex);
if (op) {
+ void *new_frames;
+
/* update existing BCM operation */
/*
@@ -1040,11 +1070,23 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
if (msg_head->nframes > op->nframes)
return -E2BIG;
- /* update CAN frames content */
+ /* get new CAN frames content into a staging buffer before
+ * locking: validate and normalize the frames there so that
+ * bcm_can_tx() / bcm_tx_timeout_handler() never observe a
+ * partially updated or unvalidated frame in op->frames
+ */
+ new_frames = kmalloc(msg_head->nframes * op->cfsiz, GFP_KERNEL);
+ if (!new_frames)
+ return -ENOMEM;
+
for (i = 0; i < msg_head->nframes; i++) {
- cf = op->frames + op->cfsiz * i;
+ cf = new_frames + op->cfsiz * i;
err = memcpy_from_msg((u8 *)cf, msg, op->cfsiz);
+ if (err < 0) {
+ kfree(new_frames);
+ return err;
+ }
if (op->flags & CAN_FD_FRAME) {
if (cf->len > 64)
@@ -1054,36 +1096,38 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
err = -EINVAL;
}
- if (err < 0)
+ if (err < 0) {
+ kfree(new_frames);
return err;
+ }
if (msg_head->flags & TX_CP_CAN_ID) {
/* copy can_id into frame */
cf->can_id = msg_head->can_id;
}
}
+
+ spin_lock_bh(&op->bcm_tx_lock);
+
+ /* update CAN frames content */
+ memcpy(op->frames, new_frames, msg_head->nframes * op->cfsiz);
+
op->flags = msg_head->flags;
- /* only lock for unlikely count/nframes/currframe changes */
if (op->nframes != msg_head->nframes ||
- op->flags & TX_RESET_MULTI_IDX ||
- op->flags & SETTIMER) {
-
- spin_lock_bh(&op->bcm_tx_lock);
+ op->flags & TX_RESET_MULTI_IDX) {
+ /* potentially update changed nframes */
+ op->nframes = msg_head->nframes;
+ /* restart multiple frame transmission */
+ op->currframe = 0;
+ }
- if (op->nframes != msg_head->nframes ||
- op->flags & TX_RESET_MULTI_IDX) {
- /* potentially update changed nframes */
- op->nframes = msg_head->nframes;
- /* restart multiple frame transmission */
- op->currframe = 0;
- }
+ if (op->flags & SETTIMER)
+ op->count = msg_head->count;
- if (op->flags & SETTIMER)
- op->count = msg_head->count;
+ spin_unlock_bh(&op->bcm_tx_lock);
- spin_unlock_bh(&op->bcm_tx_lock);
- }
+ kfree(new_frames);
} else {
/* insert new BCM operation for the given can_id */
@@ -1160,10 +1204,12 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
if (op->flags & SETTIMER) {
/* set timer values */
+ spin_lock_bh(&op->bcm_tx_lock);
op->ival1 = msg_head->ival1;
op->ival2 = msg_head->ival2;
op->kt_ival1 = bcm_timeval_to_ktime(msg_head->ival1);
op->kt_ival2 = bcm_timeval_to_ktime(msg_head->ival2);
+ spin_unlock_bh(&op->bcm_tx_lock);
/* disable an active timer due to zero values? */
if (!op->kt_ival1 && !op->kt_ival2)
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 021/602] can: bcm: validate frame length in bcm_rx_setup() for RTR replies
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (19 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 020/602] can: bcm: extend bcm_tx_lock usage for data and timer updates Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 022/602] can: bcm: add missing device refcount for CAN filter removal Greg Kroah-Hartman
` (584 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Oliver Hartkopp, stable,
Marc Kleine-Budde, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oliver Hartkopp <socketcan@hartkopp.net>
commit 62ec41f364648be79d54d94d0d240ee326948afd upstream.
bcm_tx_setup() validates cf->len against the CAN/CAN FD DLC limits
before installing frames for TX_SETUP, but bcm_rx_setup() never did
the same for the RTR-reply frame configured via RX_SETUP with
RX_RTR_FRAME.
Fixes: ffd980f976e7 ("[CAN]: Add broadcast manager (bcm) protocol")
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://patch.msgid.link/20260714-bcm_fixes-v15-7-562f7e3e42da@hartkopp.net
Cc: stable@kernel.org
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/can/bcm.c | 59 +++++++++++++++++++++++++++++++++++----------------
1 file changed, 41 insertions(+), 18 deletions(-)
diff --git a/net/can/bcm.c b/net/can/bcm.c
index e8fb31b24bb2ae..2c12a5441eac48 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -1241,22 +1241,37 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
return err;
}
-static void bcm_rx_setup_rtr_check(struct bcm_msg_head *msg_head,
- struct bcm_op *op, void *new_frames)
+static int bcm_rx_setup_rtr_check(struct bcm_msg_head *msg_head,
+ struct bcm_op *op, void *new_frames)
{
+ struct canfd_frame *frame0 = new_frames;
+
+ if (!(msg_head->flags & RX_RTR_FRAME))
+ return 0;
+
+ /* this frame is sent out as-is by bcm_can_tx() whenever a matching
+ * remote request is received, so validate its length the same way
+ * bcm_tx_setup() validates TX_SETUP frames before installing it
+ */
+ if (msg_head->flags & CAN_FD_FRAME) {
+ if (frame0->len > 64)
+ return -EINVAL;
+ } else {
+ if (frame0->len > 8)
+ return -EINVAL;
+ }
+
/* funny feature in RX(!)_SETUP only for RTR-mode:
* copy can_id into frame BUT without RTR-flag to
* prevent a full-load-loopback-test ... ;-]
* normalize this on the staged buffer, before it is
* ever installed into op->frames.
*/
- if (msg_head->flags & RX_RTR_FRAME) {
- struct canfd_frame *frame0 = new_frames;
+ if ((msg_head->flags & TX_CP_CAN_ID) ||
+ frame0->can_id == op->can_id)
+ frame0->can_id = op->can_id & ~CAN_RTR_FLAG;
- if ((msg_head->flags & TX_CP_CAN_ID) ||
- frame0->can_id == op->can_id)
- frame0->can_id = op->can_id & ~CAN_RTR_FLAG;
- }
+ return 0;
}
/*
@@ -1319,7 +1334,11 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
return err;
}
- bcm_rx_setup_rtr_check(msg_head, op, new_frames);
+ err = bcm_rx_setup_rtr_check(msg_head, op, new_frames);
+ if (err < 0) {
+ kfree(new_frames);
+ return err;
+ }
}
spin_lock_bh(&op->bcm_rx_update_lock);
@@ -1392,16 +1411,12 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
if (msg_head->nframes) {
err = memcpy_from_msg(op->frames, msg,
msg_head->nframes * op->cfsiz);
- if (err < 0) {
- if (op->frames != &op->sframe)
- kfree(op->frames);
- if (op->last_frames != &op->last_sframe)
- kfree(op->last_frames);
- kfree(op);
- return err;
- }
+ if (err < 0)
+ goto free_op;
- bcm_rx_setup_rtr_check(msg_head, op, op->frames);
+ err = bcm_rx_setup_rtr_check(msg_head, op, op->frames);
+ if (err < 0)
+ goto free_op;
}
/* bcm_can_tx / bcm_tx_timeout_handler needs this */
@@ -1503,6 +1518,14 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
}
return msg_head->nframes * op->cfsiz + MHSIZ;
+
+free_op:
+ if (op->frames != &op->sframe)
+ kfree(op->frames);
+ if (op->last_frames != &op->last_sframe)
+ kfree(op->last_frames);
+ kfree(op);
+ return err;
}
/*
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 022/602] can: bcm: add missing device refcount for CAN filter removal
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (20 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 021/602] can: bcm: validate frame length in bcm_rx_setup() for RTR replies Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 023/602] can: bcm: fix stale rx/tx ops after device removal Greg Kroah-Hartman
` (583 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, sashiko-bot, Oliver Hartkopp, stable,
Marc Kleine-Budde, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oliver Hartkopp <socketcan@hartkopp.net>
commit d59948293ea34b6337ce2b5febab8510de70048c upstream.
sashiko-bot remarked a problem with a concurrent device unregistration
in isotp.c which also is present in the bcm.c code. A former fix for raw.c
commit c275a176e4b6 ("can: raw: add missing refcount for memory leak fix")
introduced a netdevice_tracker which solves the issue for bcm.c too.
bcm_release(), bcm_delete_rx_op() and bcm_notifier() relied on
dev_get_by_index(ifindex) to re-find the device for an rx_op before
unregistering its filter. If a concurrent NETDEV_UNREGISTER has already
unlisted the device from the ifindex table, that lookup fails and
can_rx_unregister() is silently skipped, leaving a stale CAN filter
pointing at the soon-to-be-freed bcm_op/socket.
Hold a netdev_hold()/netdev_put() tracked reference on op->rx_reg_dev
from the moment the rx filter is registered in bcm_rx_setup() until it
is unregistered in bcm_rx_unreg(), and use that reference directly in
bcm_release() and bcm_delete_rx_op() instead of re-looking the device
up by ifindex.
Reported-by: sashiko-bot@kernel.org
Closes: https://sashiko.dev/#/patchset/20260707094716.63578-1-socketcan@hartkopp.net
Fixes: ffd980f976e7 ("[CAN]: Add broadcast manager (bcm) protocol")
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://patch.msgid.link/20260714-bcm_fixes-v15-8-562f7e3e42da@hartkopp.net
Cc: stable@kernel.org
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/can/bcm.c | 44 ++++++++++++++++++++++++--------------------
1 file changed, 24 insertions(+), 20 deletions(-)
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 2c12a5441eac48..e0aacfdcad8864 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -931,6 +931,7 @@ static void bcm_rx_unreg(struct net_device *dev, struct bcm_op *op)
/* mark as removed subscription */
op->rx_reg_dev = NULL;
+ dev_put(dev);
} else
printk(KERN_ERR "can-bcm: bcm_rx_unreg: registered device "
"mismatch %p %p\n", op->rx_reg_dev, dev);
@@ -961,17 +962,14 @@ static int bcm_delete_rx_op(struct list_head *ops, struct bcm_msg_head *mh,
* Only remove subscriptions that had not
* been removed due to NETDEV_UNREGISTER
* in bcm_notifier()
+ *
+ * op->rx_reg_dev is a tracked reference taken
+ * when the subscription was registered, so it
+ * stays valid here even if a concurrent
+ * NETDEV_UNREGISTER already unlisted the dev.
*/
- if (op->rx_reg_dev) {
- struct net_device *dev;
-
- dev = dev_get_by_index(sock_net(op->sk),
- op->ifindex);
- if (dev) {
- bcm_rx_unreg(dev, op);
- dev_put(dev);
- }
- }
+ if (op->rx_reg_dev)
+ bcm_rx_unreg(op->rx_reg_dev, op);
} else
can_rx_unregister(sock_net(op->sk), NULL,
op->can_id,
@@ -1494,7 +1492,15 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
bcm_rx_handler, op,
"bcm", sk);
- op->rx_reg_dev = dev;
+ /* keep a reference so that a later
+ * unregister can safely reach the device even
+ * if a concurrent NETDEV_UNREGISTER has
+ * already unlisted it by ifindex
+ */
+ if (!err) {
+ op->rx_reg_dev = dev;
+ dev_hold(dev);
+ }
dev_put(dev);
} else {
/* the requested device is gone - do not
@@ -1867,16 +1873,14 @@ static int bcm_release(struct socket *sock)
* Only remove subscriptions that had not
* been removed due to NETDEV_UNREGISTER
* in bcm_notifier()
+ *
+ * op->rx_reg_dev is a tracked reference taken
+ * when the subscription was registered, so it
+ * stays valid here even if a concurrent
+ * NETDEV_UNREGISTER already unlisted the device.
*/
- if (op->rx_reg_dev) {
- struct net_device *dev;
-
- dev = dev_get_by_index(net, op->ifindex);
- if (dev) {
- bcm_rx_unreg(dev, op);
- dev_put(dev);
- }
- }
+ if (op->rx_reg_dev)
+ bcm_rx_unreg(op->rx_reg_dev, op);
} else
can_rx_unregister(net, NULL, op->can_id,
REGMASK(op->can_id),
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 023/602] can: bcm: fix stale rx/tx ops after device removal
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (21 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 022/602] can: bcm: add missing device refcount for CAN filter removal Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 024/602] can: bcm: fix data race on rx_stamp/rx_ifindex in bcm_rx_handler() Greg Kroah-Hartman
` (582 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, sashiko-bot, Oliver Hartkopp, stable,
Marc Kleine-Budde, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oliver Hartkopp <socketcan@hartkopp.net>
commit 3b762c0d950383ab7a002686c9136b9aa55d2d70 upstream.
RX: an RX_SETUP update(!) for an existing op skipped can_rx_register()
unconditionally, even when a concurrent NETDEV_UNREGISTER had already
torn down its registration (op->rx_reg_dev == NULL). This silently
did not re-enable frame delivery for that updated filter. bcm_rx_setup()
now re-registers in that case, while leaving rx_ops with ifindex = 0
(all CAN devices) which never carry a tracked rx_reg_dev registered as-is.
TX: bcm_notify() only handled bo->rx_ops on NETDEV_UNREGISTER, leaving
tx_ops with an active cyclic transmission re-arming its hrtimer
indefinitely to execute bcm_tx_timeout_handler(). Cancelling the hrtimer
prevents the runaway timer and any injection into a later reused ifindex,
since nothing else calls bcm_can_tx() for the op until an explicit
TX_SETUP update re-arms it.
Unlike bcm_rx_unreg(), which clears the tracked rx_reg_dev for rx_ops,
the ifindex is intentionally left unchanged for tx_ops. bcm_tx_setup()
always rejects ifindex 0, so clearing it would strand the op: neither a
later TX_SETUP (bcm_find_op()) nor TX_DELETE (bcm_delete_tx_op()) could
ever find it again, since both require an exact ifindex match.
Reported-by: sashiko-bot@kernel.org
Closes: https://lore.kernel.org/linux-can/20260708094536.DDF821F00A3A@smtp.kernel.org/
Closes: https://lore.kernel.org/linux-can/20260708154039.347ED1F000E9@smtp.kernel.org/
Fixes: ffd980f976e7 ("[CAN]: Add broadcast manager (bcm) protocol")
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://patch.msgid.link/20260714-bcm_fixes-v15-9-562f7e3e42da@hartkopp.net
Cc: stable@kernel.org
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/can/bcm.c | 54 +++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 44 insertions(+), 10 deletions(-)
diff --git a/net/can/bcm.c b/net/can/bcm.c
index e0aacfdcad8864..dd176d80f4cfbf 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -1281,6 +1281,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
struct bcm_sock *bo = bcm_sk(sk);
struct bcm_op *op;
int do_rx_register;
+ int new_op = 0;
int err = 0;
if ((msg_head->flags & RX_FILTER_ID) || (!(msg_head->nframes))) {
@@ -1365,8 +1366,15 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
/* free temporary frames / kfree(NULL) is safe */
kfree(new_frames);
- /* Only an update -> do not call can_rx_register() */
- do_rx_register = 0;
+ /* Don't register a new CAN filter for the rx_op update unless
+ * a concurrent NETDEV_UNREGISTER notifier already tore down
+ * the previous registration. In this case the receiver needs
+ * to be re-registered here so that this update doesn't
+ * silently stop delivering frames for the given ifindex.
+ * Ops with ifindex = 0 (all CAN interfaces) never carry a
+ * tracked rx_reg_dev and stay registered as-is.
+ */
+ do_rx_register = (ifindex && !op->rx_reg_dev) ? 1 : 0;
} else {
/* insert new BCM operation for the given can_id */
@@ -1436,6 +1444,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
/* call can_rx_register() */
do_rx_register = 1;
+ new_op = 1;
} /* if ((op = bcm_find_op(&bo->rx_ops, msg_head->can_id, ifindex))) */
@@ -1449,7 +1458,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
if (op->flags & SETTIMER) {
/* set timers (locked) for newly created op */
- if (do_rx_register) {
+ if (new_op) {
spin_lock_bh(&op->bcm_rx_update_lock);
op->ival1 = msg_head->ival1;
op->ival2 = msg_head->ival2;
@@ -1479,7 +1488,10 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
HRTIMER_MODE_REL_SOFT);
}
- /* now we can register for can_ids, if we added a new bcm_op */
+ /* now we can register for can_ids, if we added a new bcm_op
+ * or need to re-register after a NETDEV_UNREGISTER tore down
+ * the previous registration of an existing op
+ */
if (do_rx_register) {
if (ifindex) {
struct net_device *dev;
@@ -1509,18 +1521,32 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
err = -ENODEV;
}
- } else
+ } else {
err = can_rx_register(sock_net(sk), NULL, op->can_id,
REGMASK(op->can_id),
bcm_rx_handler, op, "bcm", sk);
+ }
+
if (err) {
- /* this bcm rx op is broken -> remove it */
- bcm_remove_op(op);
+ /* newly created bcm rx op is broken -> remove it */
+ if (new_op) {
+ bcm_remove_op(op);
+ return err;
+ }
+
+ /* an existing op just stays unregistered.
+ * Cancel op->timer and (defensively) op->thrtimer.
+ * Other settings can't be reached until the next
+ * successful RX_SETUP.
+ */
+ hrtimer_cancel(&op->timer);
+ hrtimer_cancel(&op->thrtimer);
return err;
}
- /* add this bcm_op to the list of the rx_ops */
- list_add_rcu(&op->list, &bo->rx_ops);
+ /* add a new bcm_op to the list of the rx_ops */
+ if (new_op)
+ list_add_rcu(&op->list, &bo->rx_ops);
}
return msg_head->nframes * op->cfsiz + MHSIZ;
@@ -1736,11 +1762,19 @@ static void bcm_notify(struct bcm_sock *bo, unsigned long msg,
case NETDEV_UNREGISTER:
lock_sock(sk);
- /* remove device specific receive entries */
+ /* rx_ops: remove device specific receive entries */
list_for_each_entry(op, &bo->rx_ops, list)
if (op->rx_reg_dev == dev)
bcm_rx_unreg(dev, op);
+ /* tx_ops: stop device specific cyclic transmissions on the
+ * vanishing ifindex. Cancelling the timer is enough to stop
+ * cyclic bcm_can_tx() calls as there is no re-arming.
+ */
+ list_for_each_entry(op, &bo->tx_ops, list)
+ if (op->ifindex == dev->ifindex)
+ hrtimer_cancel(&op->timer);
+
/* remove device reference, if this is our bound device */
if (bo->bound && bo->ifindex == dev->ifindex) {
#if IS_ENABLED(CONFIG_PROC_FS)
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 024/602] can: bcm: fix data race on rx_stamp/rx_ifindex in bcm_rx_handler()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (22 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 023/602] can: bcm: fix stale rx/tx ops after device removal Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 025/602] can: bcm: track a single source interface for ANYDEV timeout/throttle ops Greg Kroah-Hartman
` (581 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, sashiko-bot, Oliver Hartkopp, stable,
Marc Kleine-Budde, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oliver Hartkopp <socketcan@hartkopp.net>
commit 58fd6cbc8541216af1d7ed272ea7ac2b66d50fd8 upstream.
For an rx op subscribed on all interfaces (ifindex == 0), the same op
is registered once in the shared per-netns wildcard filter list, so
bcm_rx_handler() can run concurrently on different CPUs for frames
arriving on different net devices.
op->rx_stamp and op->rx_ifindex were written before bcm_rx_update_lock was
taken, allowing concurrent writers to race each other - including a torn
store of the 64-bit rx_stamp on 32-bit platforms.
Beyond a torn store bcm_send_to_user() must report the timestamp/ifindex
of the very same frame whose content it is delivering. So the assignment
is placed in the same unbroken bcm_rx_update_lock section as the content
comparison.
As a side effect, the RTR-request frame feature (which never reach
bcm_send_to_user()) no longer updates rx_stamp/rx_ifindex, since only
the notification path needs them.
Fixes: ffd980f976e7 ("[CAN]: Add broadcast manager (bcm) protocol")
Reported-by: sashiko-bot@kernel.org
Closes: https://lore.kernel.org/linux-can/20260707145135.5BC831F00A3A@smtp.kernel.org/
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://patch.msgid.link/20260714-bcm_fixes-v15-10-562f7e3e42da@hartkopp.net
Cc: stable@kernel.org
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/can/bcm.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/net/can/bcm.c b/net/can/bcm.c
index dd176d80f4cfbf..0312b69a988c5f 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -793,11 +793,6 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)
/* disable timeout */
hrtimer_cancel(&op->timer);
- /* save rx timestamp */
- op->rx_stamp = skb->tstamp;
- /* save originator for recvfrom() */
- op->rx_ifindex = skb->dev->ifindex;
-
/* op->flags/op->frames may be updated concurrently by bcm_rx_setup() */
spin_lock_bh(&op->bcm_rx_update_lock);
@@ -829,6 +824,14 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)
traffic_flags |= RX_OWN;
}
+ /* save rx timestamp and originator for recvfrom() under lock.
+ * For an op subscribed on all interfaces (ifindex == 0)
+ * bcm_rx_handler() can run concurrently on different CPUs so
+ * the CAN content and the meta data must be bundled correctly.
+ */
+ op->rx_stamp = skb->tstamp;
+ op->rx_ifindex = skb->dev->ifindex;
+
if (op->flags & RX_FILTER_ID) {
/* the easiest case */
bcm_rx_update_and_send(op, op->last_frames, rxframe,
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 025/602] can: bcm: track a single source interface for ANYDEV timeout/throttle ops
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (23 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 024/602] can: bcm: fix data race on rx_stamp/rx_ifindex in bcm_rx_handler() Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 026/602] can: isotp: fix use-after-free race with concurrent NETDEV_UNREGISTER Greg Kroah-Hartman
` (580 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, sashiko-bot, Oliver Hartkopp, stable,
Marc Kleine-Budde, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oliver Hartkopp <socketcan@hartkopp.net>
commit 2f5976f54a04e9f18b25283036ac3136be453b17 upstream.
An ANYDEV rx op (ifindex == 0) with an active RX timeout and/or
throttle timer has no defined semantics when matching frames arrive
from several interfaces: bcm_rx_handler() can run concurrently for
the same op on different CPUs, racing hrtimer_cancel()/
bcm_rx_starttimer() against bcm_rx_timeout_handler() and causing
spurious RX_TIMEOUT notifications and last_frames corruption. The
same concurrency lets throttled multiplex frames from different
interfaces clobber the single rx_ifindex/rx_stamp fields shared by
the op.
Add op->if_detected to track the first interface that delivers a
matching frame while a timeout/throttle timer is configured, and
reject frames from any other interface for that op. The claim is
decided in bcm_rx_handler() before hrtimer_cancel() touches
op->timer, so a rejected frame can never disturb the claimed
interface's watchdog. RTR-mode ops are excluded via RX_RTR_FRAME,
independent of kt_ival1/kt_ival2, since those may briefly hold a
stale value from an earlier non-RTR configuration.
The claim is released in bcm_notify() on NETDEV_UNREGISTER and in
bcm_rx_setup() when SETTIMER reconfigures the timer values.
A (re-)claim is only possible on CAN devices in NETREG_REGISTERED
dev->reg_state to cover the release in bcm_notify() where reg_state
becomes NETREG_UNREGISTERING until synchronize_net().
Fixes: ffd980f976e7 ("[CAN]: Add broadcast manager (bcm) protocol")
Reported-by: sashiko-bot@kernel.org
Closes: https://lore.kernel.org/linux-can/20260709105031.1A39C1F000E9@smtp.kernel.org/
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://patch.msgid.link/20260714-bcm_fixes-v15-11-562f7e3e42da@hartkopp.net
Cc: stable@kernel.org
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/can/bcm.c | 49 ++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 44 insertions(+), 5 deletions(-)
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 0312b69a988c5f..0c7e6203eb44e2 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -116,6 +116,7 @@ struct bcm_op {
struct hrtimer timer, thrtimer;
ktime_t rx_stamp, kt_ival1, kt_ival2, kt_lastmsg;
int rx_ifindex;
+ int if_detected; /* first received ifindex in ANYDEV rx_op mode */
int cfsiz;
u32 count;
u32 nframes;
@@ -790,6 +791,33 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)
return;
}
+ /* An ANYDEV op with an active RX timeout and/or throttle timer
+ * tracks a single source interface: claim the first interface that
+ * delivers a matching frame and reject frames from any other one,
+ * before hrtimer_cancel() below can touch op->timer - this avoids
+ * racing bcm_rx_timeout_handler() across concurrent interfaces.
+ * RX_RTR_FRAME ops are excluded, as kt_ival1/kt_ival2 may briefly
+ * hold a stale value from an earlier non-RTR configuration.
+ */
+ if (!op->ifindex) {
+ spin_lock_bh(&op->bcm_rx_update_lock);
+
+ if (!(op->flags & RX_RTR_FRAME) &&
+ (op->kt_ival1 || op->kt_ival2)) {
+ /* don't claim to vanishing interface */
+ if (!op->if_detected &&
+ skb->dev->reg_state == NETREG_REGISTERED)
+ op->if_detected = skb->dev->ifindex;
+
+ if (op->if_detected != skb->dev->ifindex) {
+ spin_unlock_bh(&op->bcm_rx_update_lock);
+ return;
+ }
+ }
+
+ spin_unlock_bh(&op->bcm_rx_update_lock);
+ }
+
/* disable timeout */
hrtimer_cancel(&op->timer);
@@ -824,10 +852,9 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)
traffic_flags |= RX_OWN;
}
- /* save rx timestamp and originator for recvfrom() under lock.
- * For an op subscribed on all interfaces (ifindex == 0)
- * bcm_rx_handler() can run concurrently on different CPUs so
- * the CAN content and the meta data must be bundled correctly.
+ /* save rx timestamp and originator for recvfrom() under lock: an
+ * ANYDEV op without an active timer can still run concurrently on
+ * different CPUs, so content and meta data must be bundled here.
*/
op->rx_stamp = skb->tstamp;
op->rx_ifindex = skb->dev->ifindex;
@@ -1363,6 +1390,7 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
op->kt_ival1 = bcm_timeval_to_ktime(msg_head->ival1);
op->kt_ival2 = bcm_timeval_to_ktime(msg_head->ival2);
op->kt_lastmsg = 0;
+ op->if_detected = 0; /* reclaim ifindex in ANYDEV mode */
}
spin_unlock_bh(&op->bcm_rx_update_lock);
@@ -1766,10 +1794,21 @@ static void bcm_notify(struct bcm_sock *bo, unsigned long msg,
lock_sock(sk);
/* rx_ops: remove device specific receive entries */
- list_for_each_entry(op, &bo->rx_ops, list)
+ list_for_each_entry(op, &bo->rx_ops, list) {
if (op->rx_reg_dev == dev)
bcm_rx_unreg(dev, op);
+ /* release an ANYDEV op's claim (see bcm_rx_handler())
+ * on this now confirmed-gone interface.
+ */
+ if (!op->ifindex) {
+ spin_lock_bh(&op->bcm_rx_update_lock);
+ if (op->if_detected == dev->ifindex)
+ op->if_detected = 0;
+ spin_unlock_bh(&op->bcm_rx_update_lock);
+ }
+ }
+
/* tx_ops: stop device specific cyclic transmissions on the
* vanishing ifindex. Cancelling the timer is enough to stop
* cyclic bcm_can_tx() calls as there is no re-arming.
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 026/602] can: isotp: fix use-after-free race with concurrent NETDEV_UNREGISTER
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (24 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 025/602] can: bcm: track a single source interface for ANYDEV timeout/throttle ops Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 027/602] can: isotp: serialize TX state transitions under so->rx_lock Greg Kroah-Hartman
` (579 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, sashiko-bot, Oliver Hartkopp, stable,
Marc Kleine-Budde, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oliver Hartkopp <socketcan@hartkopp.net>
commit 20bab8b88baac140ca3701116e1d486c7f51e311 upstream.
isotp_release() looked up the bound network device via dev_get_by_index()
using the stored ifindex. During device unregistration the device is
unlisted from the ifindex hash before the NETDEV_UNREGISTER notifier
chain runs, so a concurrent isotp_release() could find no device, skip
can_rx_unregister() entirely, and still proceed to free the socket.
Since isotp_release() had already removed itself from the isotp
notifier list at that point, isotp_notify() would never get a chance to
clean up either, leaving a stale CAN filter that keeps pointing at the
freed socket.
Fix this the same way raw.c already does: hold a tracked reference to
the bound net_device in the socket (so->dev/so->dev_tracker) from
bind() onward instead of re-resolving it from the ifindex, and
serialize bind()/release() with rtnl_lock() so that so->dev is always
consistent with what the NETDEV_UNREGISTER notifier sees. so->dev
stays valid regardless of ifindex-hash unlisting, and is only ever
cleared by whichever of isotp_release()/isotp_notify() gets there
first, so the filter is always removed exactly once.
isotp_bind() now rejects a (re)bind with -EAGAIN while so->[tx|rx].state
isn't ISOTP_IDLE yet, so a timer left running by a prior
NETDEV_UNREGISTER can't act on a newly bound so->ifindex. Both checks
share the same lock_sock() section, so there is no window in which a
concurrent isotp_notify() clearing so->bound could be missed.
Fixes: e057dd3fc20f ("can: add ISO 15765-2:2016 transport protocol")
Reported-by: sashiko-bot@kernel.org
Closes: https://lore.kernel.org/linux-can/20260707101420.47F261F000E9@smtp.kernel.org/
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://patch.msgid.link/20260712-isotp-fixes-v10-2-793a1b1ce17f@hartkopp.net
Cc: stable@kernel.org
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/can/isotp.c | 88 +++++++++++++++++++++++++++++++++----------------
1 file changed, 59 insertions(+), 29 deletions(-)
diff --git a/net/can/isotp.c b/net/can/isotp.c
index 176e16b46413fa..76e84e2113eeab 100644
--- a/net/can/isotp.c
+++ b/net/can/isotp.c
@@ -151,6 +151,7 @@ struct isotp_sock {
struct sock sk;
int bound;
int ifindex;
+ struct net_device *dev;
canid_t txid;
canid_t rxid;
ktime_t tx_gap;
@@ -964,6 +965,14 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
goto err_event_drop;
}
+ /* so->bound is only checked once above - a wakeup may have
+ * unbound/rebound the socket meanwhile, so re-validate it
+ */
+ if (!so->bound) {
+ err = -EADDRNOTAVAIL;
+ goto err_out_drop;
+ }
+
/* PDU size > default => try max_pdu_size */
if (size > so->tx.buflen && so->tx.buflen < max_pdu_size) {
u8 *newbuf = kmalloc(max_pdu_size, GFP_KERNEL);
@@ -1199,28 +1208,30 @@ static int isotp_release(struct socket *sock)
list_del(&so->notifier);
spin_unlock(&isotp_notifier_lock);
+ rtnl_lock();
lock_sock(sk);
- /* remove current filters & unregister */
- if (so->bound) {
- if (so->ifindex) {
- struct net_device *dev;
-
- dev = dev_get_by_index(net, so->ifindex);
- if (dev) {
- if (isotp_register_rxid(so))
- can_rx_unregister(net, dev, so->rxid,
- SINGLE_MASK(so->rxid),
- isotp_rcv, sk);
-
- can_rx_unregister(net, dev, so->txid,
- SINGLE_MASK(so->txid),
- isotp_rcv_echo, sk);
- dev_put(dev);
- }
- }
+ /* remove current filters & unregister
+ * tracked reference so->dev is taken at bind() time with rtnl_lock
+ */
+ if (so->bound && so->dev) {
+ if (isotp_register_rxid(so))
+ can_rx_unregister(net, so->dev, so->rxid,
+ SINGLE_MASK(so->rxid),
+ isotp_rcv, sk);
+
+ can_rx_unregister(net, so->dev, so->txid,
+ SINGLE_MASK(so->txid),
+ isotp_rcv_echo, sk);
+ dev_put(so->dev);
}
+ so->ifindex = 0;
+ so->bound = 0;
+ so->dev = NULL;
+
+ rtnl_unlock();
+
/* Always wait for a grace period before touching the timers below.
* A concurrent NETDEV_UNREGISTER may have already unregistered our
* filters and cleared so->bound in isotp_notify() without waiting
@@ -1233,9 +1244,6 @@ static int isotp_release(struct socket *sock)
hrtimer_cancel(&so->txtimer);
hrtimer_cancel(&so->rxtimer);
- so->ifindex = 0;
- so->bound = 0;
-
sock_orphan(sk);
sock->sk = NULL;
@@ -1289,6 +1297,7 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
if (!addr->can_ifindex)
return -ENODEV;
+ rtnl_lock();
lock_sock(sk);
if (so->bound) {
@@ -1296,6 +1305,17 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
goto out;
}
+ /* A transmission or reception that outlived a previous binding
+ * (unbound by NETDEV_UNREGISTER) may still be draining; the FC/echo
+ * and RX watchdog timers bound how long this takes. Checked together
+ * with so->bound in the same lock_sock() section above, so there is
+ * no window in which a concurrent isotp_notify() could be missed.
+ */
+ if (so->tx.state != ISOTP_IDLE || so->rx.state != ISOTP_IDLE) {
+ err = -EAGAIN;
+ goto out;
+ }
+
/* ensure different CAN IDs when the rx_id is to be registered */
if (isotp_register_rxid(so) && rx_id == tx_id) {
err = -EADDRNOTAVAIL;
@@ -1308,14 +1328,12 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
goto out;
}
if (dev->type != ARPHRD_CAN) {
- dev_put(dev);
err = -ENODEV;
- goto out;
+ goto out_put_dev;
}
- if (dev->mtu < so->ll.mtu) {
- dev_put(dev);
+ if (READ_ONCE(dev->mtu) < so->ll.mtu) {
err = -EINVAL;
- goto out;
+ goto out_put_dev;
}
if (!(dev->flags & IFF_UP))
notify_enetdown = 1;
@@ -1333,16 +1351,25 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
can_rx_register(net, dev, tx_id, SINGLE_MASK(tx_id),
isotp_rcv_echo, sk, "isotpe", sk);
- dev_put(dev);
-
/* switch to new settings */
so->ifindex = ifindex;
so->rxid = rx_id;
so->txid = tx_id;
so->bound = 1;
+ /* bind() ok -> hold a reference for so->dev so that isotp_release()
+ * can safely reach the device later, even if a concurrent
+ * NETDEV_UNREGISTER has already unlisted it by ifindex.
+ */
+ so->dev = dev;
+ dev_hold(so->dev);
+
+out_put_dev:
+ /* remove potential reference from dev_get_by_index() */
+ dev_put(dev);
out:
release_sock(sk);
+ rtnl_unlock();
if (notify_enetdown) {
sk->sk_err = ENETDOWN;
@@ -1545,7 +1572,7 @@ static void isotp_notify(struct isotp_sock *so, unsigned long msg,
if (!net_eq(dev_net(dev), sock_net(sk)))
return;
- if (so->ifindex != dev->ifindex)
+ if (so->dev != dev)
return;
switch (msg) {
@@ -1561,10 +1588,12 @@ static void isotp_notify(struct isotp_sock *so, unsigned long msg,
can_rx_unregister(dev_net(dev), dev, so->txid,
SINGLE_MASK(so->txid),
isotp_rcv_echo, sk);
+ dev_put(so->dev);
}
so->ifindex = 0;
so->bound = 0;
+ so->dev = NULL;
release_sock(sk);
sk->sk_err = ENODEV;
@@ -1624,6 +1653,7 @@ static int isotp_init(struct sock *sk)
so->ifindex = 0;
so->bound = 0;
+ so->dev = NULL;
so->opt.flags = CAN_ISOTP_DEFAULT_FLAGS;
so->opt.ext_address = CAN_ISOTP_DEFAULT_EXT_ADDRESS;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 027/602] can: isotp: serialize TX state transitions under so->rx_lock
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (25 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 026/602] can: isotp: fix use-after-free race with concurrent NETDEV_UNREGISTER Greg Kroah-Hartman
@ 2026-07-30 14:06 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 028/602] dmaengine: sh: rz-dmac: Move interrupt request after everything is set up Greg Kroah-Hartman
` (578 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:06 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, sashiko-bot, Oliver Hartkopp, stable,
Marc Kleine-Budde, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oliver Hartkopp <socketcan@hartkopp.net>
commit cf070fe33bfbd1a4c21236078fadb35dd223a157 upstream.
The TX state machine (so->tx.state) is driven from three contexts:
sendmsg() claiming and progressing a transfer, the RX path consuming
Flow Control/echo frames, and two hrtimers timing out a stalled
transfer. Mixing a lock-free cmpxchg() claim in sendmsg() with
hrtimer_cancel() calls made under so->rx_lock elsewhere left windows
where a frame or timer callback could act on a state that had already
moved on, corrupting an unrelated transfer.
so->rx_lock now covers the full lifecycle of a TX claim: sendmsg()
takes it to check so->tx.state is ISOTP_IDLE, switch it to
ISOTP_SENDING, bump so->tx_gen and drain the previous transfer's
timers - all as one critical section. isotp_rcv_fc()/isotp_rcv_cf()
already run under this lock via isotp_rcv(), and isotp_rcv_echo() now
takes it itself, so none of them can ever observe a transfer mid-claim.
This also means a transfer can no longer be handed to sendmsg()'s
cleanup paths (signal or send error) while another thread is
concurrently claiming or finishing it, so those paths can cancel
timers and reset the state unconditionally.
isotp_release() claims the socket the same way, so a racing sendmsg()
sees a consistent ISOTP_SHUTDOWN and skips arming its timer or sending.
Only the hrtimer callbacks stay outside so->rx_lock, since they run
under so->rx_lock's cancellation elsewhere and taking it themselves
would deadlock. so->tx_gen lets them recognize whether the transfer
they timed out is still the one currently active, so they don't
report an error against a transfer that has since completed or been
superseded.
Fixes: e057dd3fc20f ("can: add ISO 15765-2:2016 transport protocol")
Reported-by: sashiko-bot@kernel.org
Closes: https://lore.kernel.org/linux-can/20260710142146.BDAE61F000E9@smtp.kernel.org/
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://patch.msgid.link/20260712-isotp-fixes-v10-3-793a1b1ce17f@hartkopp.net
Cc: stable@kernel.org
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/can/isotp.c | 192 ++++++++++++++++++++++++++++++++++++++----------
1 file changed, 154 insertions(+), 38 deletions(-)
diff --git a/net/can/isotp.c b/net/can/isotp.c
index 76e84e2113eeab..b2622c881aa32b 100644
--- a/net/can/isotp.c
+++ b/net/can/isotp.c
@@ -156,7 +156,7 @@ struct isotp_sock {
canid_t rxid;
ktime_t tx_gap;
ktime_t lastrxcf_tstamp;
- struct hrtimer rxtimer, txtimer, txfrtimer;
+ struct hrtimer rxtimer, txtimer, txfrtimer, echotimer;
struct can_isotp_options opt;
struct can_isotp_fc_options rxfc, txfc;
struct can_isotp_ll_options ll;
@@ -164,6 +164,7 @@ struct isotp_sock {
u32 force_tx_stmin;
u32 force_rx_stmin;
u32 cfecho; /* consecutive frame echo tag */
+ u32 tx_gen; /* generation, bumped per new tx transfer */
struct tpcon rx, tx;
struct list_head notifier;
wait_queue_head_t wait;
@@ -370,6 +371,15 @@ static int isotp_rcv_fc(struct isotp_sock *so, struct canfd_frame *cf, int ae)
hrtimer_cancel(&so->txtimer);
+ /* isotp_tx_timeout() may have given up on this job while
+ * hrtimer_cancel() above waited for it to finish; so->rx_lock
+ * (held by our caller isotp_rcv()) rules out a concurrent claim,
+ * so a plain recheck is enough here.
+ */
+ if (so->tx.state != ISOTP_WAIT_FC &&
+ so->tx.state != ISOTP_WAIT_FIRST_FC)
+ return 1;
+
if ((cf->len < ae + FC_CONTENT_SZ) ||
((so->opt.flags & ISOTP_CHECK_PADDING) &&
check_pad(so, cf, ae + FC_CONTENT_SZ, so->opt.rxpad_content))) {
@@ -416,7 +426,7 @@ static int isotp_rcv_fc(struct isotp_sock *so, struct canfd_frame *cf, int ae)
so->tx.bs = 0;
so->tx.state = ISOTP_SENDING;
/* send CF frame and enable echo timeout handling */
- hrtimer_start(&so->txtimer, ktime_set(ISOTP_ECHO_TIMEOUT, 0),
+ hrtimer_start(&so->echotimer, ktime_set(ISOTP_ECHO_TIMEOUT, 0),
HRTIMER_MODE_REL_SOFT);
isotp_send_cframe(so);
break;
@@ -569,6 +579,14 @@ static int isotp_rcv_cf(struct sock *sk, struct canfd_frame *cf, int ae,
hrtimer_cancel(&so->rxtimer);
+ /* isotp_rx_timer_handler() may have raced us for so->rx.state
+ * while hrtimer_cancel() above waited for it to finish, already
+ * reporting ETIMEDOUT and resetting the reception; don't process
+ * this CF into a reassembly that has already been given up on.
+ */
+ if (so->rx.state != ISOTP_WAIT_DATA)
+ return 1;
+
/* CFs are never longer than the FF */
if (cf->len > so->rx.ll_dl)
return 1;
@@ -858,20 +876,36 @@ static void isotp_rcv_echo(struct sk_buff *skb, void *data)
struct canfd_frame *cf = (struct canfd_frame *)skb->data;
/* only handle my own local echo CF/SF skb's (no FF!) */
- if (skb->sk != sk || so->cfecho != *(u32 *)cf->data)
+ if (skb->sk != sk)
return;
+ /* unlike isotp_rcv_fc()/isotp_rcv_cf(), not already under so->rx_lock
+ * (no isotp_rcv() caller here), so take it ourselves
+ */
+ spin_lock(&so->rx_lock);
+
+ /* so->cfecho may since belong to a new transfer; recheck under lock */
+ if (so->cfecho != *(u32 *)cf->data)
+ goto out_unlock;
+
/* cancel local echo timeout */
- hrtimer_cancel(&so->txtimer);
+ hrtimer_cancel(&so->echotimer);
/* local echo skb with consecutive frame has been consumed */
so->cfecho = 0;
+ /* claiming a transfer also takes so->rx_lock, so a plain recheck
+ * is enough: so->tx.state can't have flipped to ISOTP_SENDING for
+ * a new claim while we're still in here
+ */
+ if (so->tx.state != ISOTP_SENDING)
+ goto out_unlock;
+
if (so->tx.idx >= so->tx.len) {
/* we are done */
so->tx.state = ISOTP_IDLE;
wake_up_interruptible(&so->wait);
- return;
+ goto out_unlock;
}
if (so->txfc.bs && so->tx.bs >= so->txfc.bs) {
@@ -879,53 +913,83 @@ static void isotp_rcv_echo(struct sk_buff *skb, void *data)
so->tx.state = ISOTP_WAIT_FC;
hrtimer_start(&so->txtimer, ktime_set(ISOTP_FC_TIMEOUT, 0),
HRTIMER_MODE_REL_SOFT);
- return;
+ goto out_unlock;
}
/* no gap between data frames needed => use burst mode */
if (!so->tx_gap) {
/* enable echo timeout handling */
- hrtimer_start(&so->txtimer, ktime_set(ISOTP_ECHO_TIMEOUT, 0),
+ hrtimer_start(&so->echotimer, ktime_set(ISOTP_ECHO_TIMEOUT, 0),
HRTIMER_MODE_REL_SOFT);
isotp_send_cframe(so);
- return;
+ goto out_unlock;
}
/* start timer to send next consecutive frame with correct delay */
hrtimer_start(&so->txfrtimer, so->tx_gap, HRTIMER_MODE_REL_SOFT);
+
+out_unlock:
+ spin_unlock(&so->rx_lock);
}
-static enum hrtimer_restart isotp_tx_timer_handler(struct hrtimer *hrtimer)
+/* shared by so->txtimer's and so->echotimer's callbacks. Both timers get
+ * cancelled under so->rx_lock elsewhere, so this must stay lock-free to
+ * avoid deadlocking with that; uses so->tx_gen instead to avoid tainting
+ * a new transfer with an error from the one that just timed out.
+ */
+static enum hrtimer_restart isotp_tx_timeout(struct isotp_sock *so)
{
- struct isotp_sock *so = container_of(hrtimer, struct isotp_sock,
- txtimer);
struct sock *sk = &so->sk;
+ u32 gen = READ_ONCE(so->tx_gen);
+ u32 old_state = READ_ONCE(so->tx.state);
/* don't handle timeouts in IDLE or SHUTDOWN state */
- if (so->tx.state == ISOTP_IDLE || so->tx.state == ISOTP_SHUTDOWN)
+ if (old_state == ISOTP_IDLE || old_state == ISOTP_SHUTDOWN)
+ return HRTIMER_NORESTART;
+
+ /* only claim the timeout if the state is still unchanged */
+ if (cmpxchg(&so->tx.state, old_state, ISOTP_IDLE) != old_state)
return HRTIMER_NORESTART;
/* we did not get any flow control or echo frame in time */
- /* report 'communication error on send' */
- sk->sk_err = ECOMM;
- if (!sock_flag(sk, SOCK_DEAD))
- sk_error_report(sk);
+ if (READ_ONCE(so->tx_gen) == gen) {
+ /* report 'communication error on send' */
+ sk->sk_err = ECOMM;
+ if (!sock_flag(sk, SOCK_DEAD))
+ sk_error_report(sk);
+ }
- /* reset tx state */
- so->tx.state = ISOTP_IDLE;
wake_up_interruptible(&so->wait);
return HRTIMER_NORESTART;
}
+/* so->txtimer: fires when a Flow Control frame does not arrive in time */
+static enum hrtimer_restart isotp_tx_timer_handler(struct hrtimer *hrtimer)
+{
+ struct isotp_sock *so = container_of(hrtimer, struct isotp_sock,
+ txtimer);
+
+ return isotp_tx_timeout(so);
+}
+
+/* so->echotimer: fires when a sent CF/SF's local echo does not arrive */
+static enum hrtimer_restart isotp_echo_timer_handler(struct hrtimer *hrtimer)
+{
+ struct isotp_sock *so = container_of(hrtimer, struct isotp_sock,
+ echotimer);
+
+ return isotp_tx_timeout(so);
+}
+
static enum hrtimer_restart isotp_txfr_timer_handler(struct hrtimer *hrtimer)
{
struct isotp_sock *so = container_of(hrtimer, struct isotp_sock,
txfrtimer);
/* start echo timeout handling and cover below protocol error */
- hrtimer_start(&so->txtimer, ktime_set(ISOTP_ECHO_TIMEOUT, 0),
+ hrtimer_start(&so->echotimer, ktime_set(ISOTP_ECHO_TIMEOUT, 0),
HRTIMER_MODE_REL_SOFT);
/* cfecho should be consumed by isotp_rcv_echo() here */
@@ -945,13 +1009,24 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
int ae = (so->opt.flags & CAN_ISOTP_EXTEND_ADDR) ? 1 : 0;
int wait_tx_done = (so->opt.flags & CAN_ISOTP_WAIT_TX_DONE) ? 1 : 0;
s64 hrtimer_sec = ISOTP_ECHO_TIMEOUT;
+ struct hrtimer *tx_hrt = &so->echotimer;
+ u32 new_state = ISOTP_SENDING;
int off;
int err;
if (!so->bound || so->tx.state == ISOTP_SHUTDOWN)
return -EADDRNOTAVAIL;
- while (cmpxchg(&so->tx.state, ISOTP_IDLE, ISOTP_SENDING) != ISOTP_IDLE) {
+ /* claim the socket under so->rx_lock: this serializes the claim
+ * with the RX path and with sendmsg()'s own error paths below, so
+ * none of them can ever see a transfer mid-claim
+ */
+ for (;;) {
+ spin_lock_bh(&so->rx_lock);
+ if (READ_ONCE(so->tx.state) == ISOTP_IDLE)
+ break;
+ spin_unlock_bh(&so->rx_lock);
+
/* we do not support multiple buffers - for now */
if (msg->msg_flags & MSG_DONTWAIT)
return -EAGAIN;
@@ -960,11 +1035,23 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
return -EADDRNOTAVAIL;
/* wait for complete transmission of current pdu */
- err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE);
+ err = wait_event_interruptible(so->wait,
+ so->tx.state == ISOTP_IDLE);
if (err)
- goto err_event_drop;
+ return err;
}
+ /* new transfer: bump so->tx_gen and drain the old one's timers,
+ * still under the so->rx_lock we just claimed the socket with
+ */
+ WRITE_ONCE(so->tx.state, ISOTP_SENDING);
+ WRITE_ONCE(so->tx_gen, READ_ONCE(so->tx_gen) + 1);
+ hrtimer_cancel(&so->txtimer);
+ hrtimer_cancel(&so->echotimer);
+ hrtimer_cancel(&so->txfrtimer);
+ so->cfecho = 0;
+ spin_unlock_bh(&so->rx_lock);
+
/* so->bound is only checked once above - a wakeup may have
* unbound/rebound the socket meanwhile, so re-validate it
*/
@@ -1075,18 +1162,33 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
so->cfecho = *(u32 *)cf->data;
} else {
/* standard flow control check */
- so->tx.state = ISOTP_WAIT_FIRST_FC;
+ new_state = ISOTP_WAIT_FIRST_FC;
/* start timeout for FC */
hrtimer_sec = ISOTP_FC_TIMEOUT;
+ tx_hrt = &so->txtimer;
/* no CF echo tag for isotp_rcv_echo() (FF-mode) */
so->cfecho = 0;
}
}
- hrtimer_start(&so->txtimer, ktime_set(hrtimer_sec, 0),
+ spin_lock_bh(&so->rx_lock);
+ if (so->tx.state == ISOTP_SHUTDOWN) {
+ /* isotp_release() has since taken over and already drained
+ * our timers - don't send into a socket that's going away
+ */
+ spin_unlock_bh(&so->rx_lock);
+ kfree_skb(skb);
+ dev_put(dev);
+ wake_up_interruptible(&so->wait);
+ return -EADDRNOTAVAIL;
+ }
+ /* WAIT_FIRST_FC for standard FF, else stays ISOTP_SENDING */
+ so->tx.state = new_state;
+ hrtimer_start(tx_hrt, ktime_set(hrtimer_sec, 0),
HRTIMER_MODE_REL_SOFT);
+ spin_unlock_bh(&so->rx_lock);
/* send the first or only CAN frame */
cf->flags = so->ll.tx_flags;
@@ -1099,13 +1201,10 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
pr_notice_once("can-isotp: %s: can_send_ret %pe\n",
__func__, ERR_PTR(err));
+ spin_lock_bh(&so->rx_lock);
/* no transmission -> no timeout monitoring */
- hrtimer_cancel(&so->txtimer);
-
- /* reset consecutive frame echo tag */
- so->cfecho = 0;
-
- goto err_out_drop;
+ hrtimer_cancel(tx_hrt);
+ goto err_out_drop_locked;
}
if (wait_tx_done) {
@@ -1121,14 +1220,21 @@ static int isotp_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
return size;
+err_out_drop:
+ /* claimed but nothing sent yet - no timer to cancel */
+ spin_lock_bh(&so->rx_lock);
+ goto err_out_drop_locked;
err_event_drop:
- /* got signal: force tx state machine to be idle */
- so->tx.state = ISOTP_IDLE;
+ /* interrupted waiting on our own transfer - drain its timers */
+ spin_lock_bh(&so->rx_lock);
hrtimer_cancel(&so->txfrtimer);
hrtimer_cancel(&so->txtimer);
-err_out_drop:
- /* drop this PDU and unlock a potential wait queue */
+ hrtimer_cancel(&so->echotimer);
+err_out_drop_locked:
+ /* release the claim; so->rx_lock still held from above */
+ so->cfecho = 0;
so->tx.state = ISOTP_IDLE;
+ spin_unlock_bh(&so->rx_lock);
wake_up_interruptible(&so->wait);
return err;
@@ -1190,13 +1296,20 @@ static int isotp_release(struct socket *sock)
so = isotp_sk(sk);
net = sock_net(sk);
- /* wait for complete transmission of current pdu */
- while (wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE) == 0 &&
- cmpxchg(&so->tx.state, ISOTP_IDLE, ISOTP_SHUTDOWN) != ISOTP_IDLE)
+ /* best-effort: wait for a running pdu to finish, but don't block on
+ * it forever - give up after the first signal
+ */
+ while (so->tx.state != ISOTP_IDLE &&
+ wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE) == 0)
;
- /* force state machines to be idle also when a signal occurred */
+ /* claim the socket under so->rx_lock like sendmsg() does, so its
+ * claim can't race the forced ISOTP_SHUTDOWN below; force it
+ * unconditionally, even when a signal cut the wait above short
+ */
+ spin_lock_bh(&so->rx_lock);
so->tx.state = ISOTP_SHUTDOWN;
+ spin_unlock_bh(&so->rx_lock);
so->rx.state = ISOTP_IDLE;
spin_lock(&isotp_notifier_lock);
@@ -1242,6 +1355,7 @@ static int isotp_release(struct socket *sock)
hrtimer_cancel(&so->txfrtimer);
hrtimer_cancel(&so->txtimer);
+ hrtimer_cancel(&so->echotimer);
hrtimer_cancel(&so->rxtimer);
sock_orphan(sk);
@@ -1684,6 +1798,8 @@ static int isotp_init(struct sock *sk)
so->rxtimer.function = isotp_rx_timer_handler;
hrtimer_init(&so->txtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
so->txtimer.function = isotp_tx_timer_handler;
+ hrtimer_init(&so->echotimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
+ so->echotimer.function = isotp_echo_timer_handler;
hrtimer_init(&so->txfrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_SOFT);
so->txfrtimer.function = isotp_txfr_timer_handler;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 028/602] dmaengine: sh: rz-dmac: Move interrupt request after everything is set up
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (26 preceding siblings ...)
2026-07-30 14:06 ` [PATCH 6.12 027/602] can: isotp: serialize TX state transitions under so->rx_lock Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 029/602] Revert "arm64: dts: ti: k3-am62a7-sk: Add bootph-all tag to vqmmc" Greg Kroah-Hartman
` (577 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Frank Li, John Madieu,
Claudiu Beznea, Tommaso Merciai, Vinod Koul, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
commit 731712403ddb39d1a76a11abf339a0615bc85de7 upstream.
Once the interrupt is requested, the interrupt handler may run immediately.
Since the IRQ handler can access channel->ch_base, which is initialized
only after requesting the IRQ, this may lead to invalid memory access.
Likewise, the IRQ thread may access uninitialized data (the ld_free,
ld_queue, and ld_active lists), which may also lead to issues.
Request the interrupts only after everything is set up. To keep the error
path simpler, use dmam_alloc_coherent() instead of dma_alloc_coherent().
Fixes: 5000d37042a6 ("dmaengine: sh: Add DMAC driver for RZ/G2L SoC")
Cc: stable@vger.kernel.org
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Tested-by: John Madieu <john.madieu.xa@bp.renesas.com>
Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
Tested-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
Link: https://patch.msgid.link/20260526084710.3491480-2-claudiu.beznea@kernel.org
[tm: Kept the channel->irq field in rz_dmac_chan_probe() instead of
upstream's local `irq` variable, as commit 04e227718ab8
("dmaengine: sh: rz-dmac: Make channel irq local") is not present
in this tree. Likewise kept platform_get_irq_byname() (mandatory)
instead of platform_get_irq_byname_optional() for the error IRQ in
rz_dmac_probe(), as commit 6b3a6b6dc074 ("dmaengine: sh: rz_dmac:
make error interrupt optional") is not present in this tree either;
its early return on failure becomes a goto err jump to match the
new call order.]
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/dma/sh/rz-dmac.c | 96 ++++++++++++++++------------------------
1 file changed, 38 insertions(+), 58 deletions(-)
diff --git a/drivers/dma/sh/rz-dmac.c b/drivers/dma/sh/rz-dmac.c
index 06952519f509b8..fece2cfec1ccb4 100644
--- a/drivers/dma/sh/rz-dmac.c
+++ b/drivers/dma/sh/rz-dmac.c
@@ -780,27 +780,6 @@ static int rz_dmac_chan_probe(struct rz_dmac *dmac,
channel->index = index;
channel->mid_rid = -EINVAL;
- /* Request the channel interrupt. */
- scnprintf(pdev_irqname, sizeof(pdev_irqname), "ch%u", index);
- channel->irq = platform_get_irq_byname(pdev, pdev_irqname);
- if (channel->irq < 0)
- return channel->irq;
-
- irqname = devm_kasprintf(dmac->dev, GFP_KERNEL, "%s:%u",
- dev_name(dmac->dev), index);
- if (!irqname)
- return -ENOMEM;
-
- ret = devm_request_threaded_irq(dmac->dev, channel->irq,
- rz_dmac_irq_handler,
- rz_dmac_irq_handler_thread, 0,
- irqname, channel);
- if (ret) {
- dev_err(dmac->dev, "failed to request IRQ %u (%d)\n",
- channel->irq, ret);
- return ret;
- }
-
/* Set io base address for each channel */
if (index < 8) {
channel->ch_base = dmac->base + CHANNEL_0_7_OFFSET +
@@ -813,9 +792,9 @@ static int rz_dmac_chan_probe(struct rz_dmac *dmac,
}
/* Allocate descriptors */
- lmdesc = dma_alloc_coherent(&pdev->dev,
- sizeof(struct rz_lmdesc) * DMAC_NR_LMDESC,
- &channel->lmdesc.base_dma, GFP_KERNEL);
+ lmdesc = dmam_alloc_coherent(&pdev->dev,
+ sizeof(struct rz_lmdesc) * DMAC_NR_LMDESC,
+ &channel->lmdesc.base_dma, GFP_KERNEL);
if (!lmdesc) {
dev_err(&pdev->dev, "Can't allocate memory (lmdesc)\n");
return -ENOMEM;
@@ -831,7 +810,26 @@ static int rz_dmac_chan_probe(struct rz_dmac *dmac,
INIT_LIST_HEAD(&channel->ld_free);
INIT_LIST_HEAD(&channel->ld_active);
- return 0;
+ /* Request the channel interrupt. */
+ scnprintf(pdev_irqname, sizeof(pdev_irqname), "ch%u", index);
+ channel->irq = platform_get_irq_byname(pdev, pdev_irqname);
+ if (channel->irq < 0)
+ return channel->irq;
+
+ irqname = devm_kasprintf(dmac->dev, GFP_KERNEL, "%s:%u",
+ dev_name(dmac->dev), index);
+ if (!irqname)
+ return -ENOMEM;
+
+ ret = devm_request_threaded_irq(dmac->dev, channel->irq,
+ rz_dmac_irq_handler,
+ rz_dmac_irq_handler_thread, 0,
+ irqname, channel);
+ if (ret)
+ dev_err(dmac->dev, "failed to request IRQ %u (%d)\n",
+ channel->irq, ret);
+
+ return ret;
}
static int rz_dmac_parse_of(struct device *dev, struct rz_dmac *dmac)
@@ -858,7 +856,6 @@ static int rz_dmac_probe(struct platform_device *pdev)
const char *irqname = "error";
struct dma_device *engine;
struct rz_dmac *dmac;
- int channel_num;
int ret;
int irq;
u8 i;
@@ -888,19 +885,6 @@ static int rz_dmac_probe(struct platform_device *pdev)
if (IS_ERR(dmac->ext_base))
return PTR_ERR(dmac->ext_base);
- /* Register interrupt handler for error */
- irq = platform_get_irq_byname(pdev, irqname);
- if (irq < 0)
- return irq;
-
- ret = devm_request_irq(&pdev->dev, irq, rz_dmac_irq_handler, 0,
- irqname, NULL);
- if (ret) {
- dev_err(&pdev->dev, "failed to request IRQ %u (%d)\n",
- irq, ret);
- return ret;
- }
-
/* Initialize the channels. */
INIT_LIST_HEAD(&dmac->engine.channels);
@@ -926,6 +910,21 @@ static int rz_dmac_probe(struct platform_device *pdev)
goto err;
}
+ /* Register interrupt handler for error */
+ irq = platform_get_irq_byname(pdev, irqname);
+ if (irq < 0) {
+ ret = irq;
+ goto err;
+ }
+
+ ret = devm_request_irq(&pdev->dev, irq, rz_dmac_irq_handler, 0,
+ irqname, NULL);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to request IRQ %u (%d)\n",
+ irq, ret);
+ goto err;
+ }
+
/* Register the DMAC as a DMA provider for DT. */
ret = of_dma_controller_register(pdev->dev.of_node, rz_dmac_of_xlate,
NULL);
@@ -964,16 +963,6 @@ static int rz_dmac_probe(struct platform_device *pdev)
dma_register_err:
of_dma_controller_free(pdev->dev.of_node);
err:
- channel_num = i ? i - 1 : 0;
- for (i = 0; i < channel_num; i++) {
- struct rz_dmac_chan *channel = &dmac->channels[i];
-
- dma_free_coherent(&pdev->dev,
- sizeof(struct rz_lmdesc) * DMAC_NR_LMDESC,
- channel->lmdesc.base,
- channel->lmdesc.base_dma);
- }
-
reset_control_assert(dmac->rstc);
err_pm_runtime_put:
pm_runtime_put(&pdev->dev);
@@ -986,18 +975,9 @@ static int rz_dmac_probe(struct platform_device *pdev)
static void rz_dmac_remove(struct platform_device *pdev)
{
struct rz_dmac *dmac = platform_get_drvdata(pdev);
- unsigned int i;
dma_async_device_unregister(&dmac->engine);
of_dma_controller_free(pdev->dev.of_node);
- for (i = 0; i < dmac->n_channels; i++) {
- struct rz_dmac_chan *channel = &dmac->channels[i];
-
- dma_free_coherent(&pdev->dev,
- sizeof(struct rz_lmdesc) * DMAC_NR_LMDESC,
- channel->lmdesc.base,
- channel->lmdesc.base_dma);
- }
reset_control_assert(dmac->rstc);
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 029/602] Revert "arm64: dts: ti: k3-am62a7-sk: Add bootph-all tag to vqmmc"
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (27 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 028/602] dmaengine: sh: rz-dmac: Move interrupt request after everything is set up Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 030/602] gpu: host1x: Fix use-after-free in host1x_bo_clear_cached_mappings Greg Kroah-Hartman
` (576 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
This reverts commit 1b21939117aea112f6b7fa67bba6fb43d2a8e8ec.
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
arch/arm64/boot/dts/ti/k3-am62a7-sk.dts | 2 --
1 file changed, 2 deletions(-)
diff --git a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
index f94378379447a6..0b6e371eea98d2 100644
--- a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts
@@ -134,7 +134,6 @@ vddshv_sdio: regulator-5 {
gpios = <&main_gpio0 31 GPIO_ACTIVE_HIGH>;
states = <1800000 0x0>,
<3300000 0x1>;
- bootph-all;
};
leds {
@@ -382,7 +381,6 @@ pmic_irq_pins_default: pmic-irq-default-pins {
pinctrl-single,pins = <
AM62AX_MCU_IOPAD(0x000, PIN_INPUT, 7) /* (E11) MCU_GPIO0_0 */
>;
- bootph-all;
};
};
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 030/602] gpu: host1x: Fix use-after-free in host1x_bo_clear_cached_mappings
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (28 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 029/602] Revert "arm64: dts: ti: k3-am62a7-sk: Add bootph-all tag to vqmmc" Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 031/602] crypto: tegra - Dont touch bo refcount in host1x bo pin/unpin Greg Kroah-Hartman
` (575 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Dan Carpenter, Mikko Perttunen,
Thierry Reding, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikko Perttunen <mperttunen@nvidia.com>
[ Upstream commit 266cddf7bd0f6c79b6c0633aef742a22bf70265b ]
__host1x_bo_unpin() drops the last reference to the mapping and frees
it, so we can't dereference mapping afterwards. The cache itself
outlives the mapping, so use the cache local variable instead.
Reported-by: Dan Carpenter <error27@gmail.com>
Closes: https://lore.kernel.org/linux-tegra/ah6ErK6f4kVudVIA@stanley.mountain/T/#u
Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Link: https://patch.msgid.link/20260603-host1x-bocache-leak-fix-v1-1-494101dbfd30@nvidia.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/host1x/bus.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c
index ef42e9a883f4f9..4dd83627fae06a 100644
--- a/drivers/gpu/host1x/bus.c
+++ b/drivers/gpu/host1x/bus.c
@@ -1006,10 +1006,10 @@ void host1x_bo_clear_cached_mappings(struct host1x_bo *bo)
if (WARN_ON(!cache))
continue;
- mutex_lock(&mapping->cache->lock);
+ mutex_lock(&cache->lock);
WARN_ON(kref_read(&mapping->ref) != 1);
__host1x_bo_unpin(&mapping->ref);
- mutex_unlock(&mapping->cache->lock);
+ mutex_unlock(&cache->lock);
}
}
EXPORT_SYMBOL(host1x_bo_clear_cached_mappings);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 031/602] crypto: tegra - Dont touch bo refcount in host1x bo pin/unpin
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (29 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 030/602] gpu: host1x: Fix use-after-free in host1x_bo_clear_cached_mappings Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 032/602] xprtrdma: Clear receive-side ownership pointers on release Greg Kroah-Hartman
` (574 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Mikko Perttunen, Herbert Xu,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikko Perttunen <mperttunen@nvidia.com>
[ Upstream commit f8c9c57d750346abd213ffed2ae3cacb0268e9f1 ]
Since commit "gpu: host1x: Allow entries in BO caches to be freed",
host1x_bo_pin() and host1x_bo_unpin() handle the bo's refcount
themselves. .pin/.unpin callbacks should not adjust it.
Signed-off-by: Mikko Perttunen <mperttunen@nvidia.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/crypto/tegra/tegra-se-main.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/crypto/tegra/tegra-se-main.c b/drivers/crypto/tegra/tegra-se-main.c
index 3c3b9f18d8cf50..e5ff4fe66a4b88 100644
--- a/drivers/crypto/tegra/tegra-se-main.c
+++ b/drivers/crypto/tegra/tegra-se-main.c
@@ -52,7 +52,7 @@ tegra_se_cmdbuf_pin(struct device *dev, struct host1x_bo *bo, enum dma_data_dire
return ERR_PTR(-ENOMEM);
kref_init(&map->ref);
- map->bo = host1x_bo_get(bo);
+ map->bo = bo;
map->direction = direction;
map->dev = dev;
@@ -93,7 +93,6 @@ static void tegra_se_cmdbuf_unpin(struct host1x_bo_mapping *map)
dma_unmap_sgtable(map->dev, map->sgt, map->direction, 0);
sg_free_table(map->sgt);
kfree(map->sgt);
- host1x_bo_put(map->bo);
kfree(map);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 032/602] xprtrdma: Clear receive-side ownership pointers on release
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (30 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 031/602] crypto: tegra - Dont touch bo refcount in host1x bo pin/unpin Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 033/602] Input: ims-pcu - fix heap-buffer-overflow in ims_pcu_process_data() Greg Kroah-Hartman
` (573 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Chuck Lever, Anna Schumaker,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <chuck.lever@oracle.com>
[ Upstream commit 2ae8e7afbc63bf84243367f89eb43571f0345a74 ]
Three small ownership-state cleanups land the transport in a
state that lets future reviewers reason about each pointer
locally rather than tracing the whole reply path:
rpcrdma_rep_put() clears rep->rr_rqst before the rep enters
rb_free_reps so that no rep on the free list still carries a
stale rqst pointer. rpcrdma_reply_handler() and
rpcrdma_unpin_rqst() are the only sites that set rr_rqst;
rpcrdma_reply_handler() hands the rep through
rpcrdma_rep_put(), and rpcrdma_unpin_rqst() NULLs rr_rqst
directly because its error path abandons the rep for
teardown cleanup rather than returning it to rb_free_reps.
rpcrdma_reply_put() NULLs req->rl_reply before calling
rpcrdma_rep_put(). The previous order placed the rep on
rb_free_reps while req->rl_reply still pointed at it; the
window was harmless because xprt_rdma_free_slot() holds the
req exclusively across the pair, but closing it makes the
invariant 'rep on rb_free_reps implies no req references it'
strictly checkable.
rpcrdma_sendctx_unmap() and rpcrdma_sendctx_cancel() clear
req->rl_sendctx after dropping the sendctx pointer in the
sendctx ring. Without this, req->rl_sendctx survives across
Send completion and points at a sendctx that may already have
been reassigned by rpcrdma_sendctx_get_locked() to a different
req. No caller dereferences the stale pointer today --
rpcrdma_prepare_send_sges() overwrites it before the next
Send -- but a NULL is a more honest representation of 'the
Send is no longer outstanding' and lets the assertion patch
that follows trip on any future regression.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/sunrpc/xprtrdma/rpc_rdma.c | 4 ++++
net/sunrpc/xprtrdma/verbs.c | 12 ++++++++++--
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c
index e201b37578a70e..aa57e057ff451f 100644
--- a/net/sunrpc/xprtrdma/rpc_rdma.c
+++ b/net/sunrpc/xprtrdma/rpc_rdma.c
@@ -542,6 +542,7 @@ void rpcrdma_sendctx_unmap(struct rpcrdma_sendctx *sc)
rpcrdma_sendctx_dma_unmap(sc);
sc->sc_req = NULL;
+ req->rl_sendctx = NULL;
rpcrdma_req_put(req);
}
@@ -550,8 +551,11 @@ void rpcrdma_sendctx_unmap(struct rpcrdma_sendctx *sc)
*/
static void rpcrdma_sendctx_cancel(struct rpcrdma_sendctx *sc)
{
+ struct rpcrdma_req *req = sc->sc_req;
+
rpcrdma_sendctx_dma_unmap(sc);
sc->sc_req = NULL;
+ req->rl_sendctx = NULL;
}
/* Prepare an SGE for the RPC-over-RDMA transport header.
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
index efd91ed249fabe..e2d3cee825cd7f 100644
--- a/net/sunrpc/xprtrdma/verbs.c
+++ b/net/sunrpc/xprtrdma/verbs.c
@@ -1080,9 +1080,15 @@ static struct rpcrdma_rep *rpcrdma_rep_get_locked(struct rpcrdma_buffer *buf)
* @buf: buffer pool
* @rep: rep to release
*
+ * The rep's transient association with an rpc_rqst, established
+ * by rpcrdma_reply_handler() and torn down here, must not survive
+ * onto rb_free_reps: rpcrdma_post_recvs() pulls reps from the free
+ * list to re-post them, and a non-NULL rr_rqst on a free-listed rep
+ * would imply the rep is still referenced by a req.
*/
void rpcrdma_rep_put(struct rpcrdma_buffer *buf, struct rpcrdma_rep *rep)
{
+ rep->rr_rqst = NULL;
llist_add(&rep->rr_node, &buf->rb_free_reps);
}
@@ -1265,9 +1271,11 @@ rpcrdma_mr_get(struct rpcrdma_xprt *r_xprt)
*/
void rpcrdma_reply_put(struct rpcrdma_buffer *buffers, struct rpcrdma_req *req)
{
- if (req->rl_reply) {
- rpcrdma_rep_put(buffers, req->rl_reply);
+ struct rpcrdma_rep *rep = req->rl_reply;
+
+ if (rep) {
req->rl_reply = NULL;
+ rpcrdma_rep_put(buffers, rep);
}
/* I2: rl_reply NULL after the put closes the
* 'rep on rb_free_reps still referenced by req' window.
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 033/602] Input: ims-pcu - fix heap-buffer-overflow in ims_pcu_process_data()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (31 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 032/602] xprtrdma: Clear receive-side ownership pointers on release Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 034/602] Input: ims-pcu - fix logic error in packet reset Greg Kroah-Hartman
` (572 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sanghoon Choi, Seungjin Bae,
Dmitry Torokhov, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Seungjin Bae <eeodqql09@gmail.com>
[ Upstream commit 875115b82c295277b81b6dfee7debc725f44e854 ]
The `ims_pcu_process_data()` processes incoming URB data byte by byte.
However, it fails to check if the `read_pos` index exceeds
IMS_PCU_BUF_SIZE.
If a malicious USB device sends a packet larger than IMS_PCU_BUF_SIZE,
`read_pos` will increment indefinitely. Moreover, since `read_pos` is
located immediately after `read_buf`, the attacker can overwrite
`read_pos` itself to arbitrarily control the index.
This manipulated `read_pos` is subsequently used in
`ims_pcu_handle_response()` to copy data into `cmd_buf`, leading to a
heap buffer overflow.
Specifically, an attacker can overwrite the `cmd_done.wait.head` located
at offset 136 relative to `cmd_buf` in the `ims_pcu_handle_response()`.
Consequently, when the driver calls `complete(&pcu->cmd_done)`, it
triggers a control flow hijack by using the manipulated pointer.
Fix this by adding a bounds check for `read_pos` before writing to
`read_buf`. If the packet is too long, discard it, log a warning,
and reset the parser state.
Fixes: 628329d524743 ("Input: add IMS Passenger Control Unit driver")
Co-developed-by: Sanghoon Choi <csh0052@gmail.com>
Signed-off-by: Sanghoon Choi <csh0052@gmail.com>
Signed-off-by: Seungjin Bae <eeodqql09@gmail.com>
Link: https://patch.msgid.link/20251221211442.841549-2-eeodqql09@gmail.com
[dtor: factor out resetting packet state, reset checksum as well]
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/input/misc/ims-pcu.c | 32 ++++++++++++++++++++++++++------
1 file changed, 26 insertions(+), 6 deletions(-)
diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c
index 4073e66e4d629e..3dc624c75bb5c5 100644
--- a/drivers/input/misc/ims-pcu.c
+++ b/drivers/input/misc/ims-pcu.c
@@ -448,6 +448,14 @@ static void ims_pcu_handle_response(struct ims_pcu *pcu)
}
}
+static void ims_pcu_reset_packet(struct ims_pcu *pcu)
+{
+ pcu->have_stx = true;
+ pcu->have_dle = false;
+ pcu->read_pos = 0;
+ pcu->check_sum = 0;
+}
+
static void ims_pcu_process_data(struct ims_pcu *pcu, struct urb *urb)
{
int i;
@@ -460,6 +468,14 @@ static void ims_pcu_process_data(struct ims_pcu *pcu, struct urb *urb)
continue;
if (pcu->have_dle) {
+ if (pcu->read_pos >= IMS_PCU_BUF_SIZE) {
+ dev_warn(pcu->dev,
+ "Packet too long (%d bytes), discarding\n",
+ pcu->read_pos);
+ ims_pcu_reset_packet(pcu);
+ continue;
+ }
+
pcu->have_dle = false;
pcu->read_buf[pcu->read_pos++] = data;
pcu->check_sum += data;
@@ -472,10 +488,8 @@ static void ims_pcu_process_data(struct ims_pcu *pcu, struct urb *urb)
dev_warn(pcu->dev,
"Unexpected STX at byte %d, discarding old data\n",
pcu->read_pos);
+ ims_pcu_reset_packet(pcu);
pcu->have_stx = true;
- pcu->have_dle = false;
- pcu->read_pos = 0;
- pcu->check_sum = 0;
break;
case IMS_PCU_PROTOCOL_DLE:
@@ -495,12 +509,18 @@ static void ims_pcu_process_data(struct ims_pcu *pcu, struct urb *urb)
ims_pcu_handle_response(pcu);
}
- pcu->have_stx = false;
- pcu->have_dle = false;
- pcu->read_pos = 0;
+ ims_pcu_reset_packet(pcu);
break;
default:
+ if (pcu->read_pos >= IMS_PCU_BUF_SIZE) {
+ dev_warn(pcu->dev,
+ "Packet too long (%d bytes), discarding\n",
+ pcu->read_pos);
+ ims_pcu_reset_packet(pcu);
+ continue;
+ }
+
pcu->read_buf[pcu->read_pos++] = data;
pcu->check_sum += data;
break;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 034/602] Input: ims-pcu - fix logic error in packet reset
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (32 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 033/602] Input: ims-pcu - fix heap-buffer-overflow in ims_pcu_process_data() Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 035/602] soc: qcom: ice: Allow explicit votes on iface clock for ICE Greg Kroah-Hartman
` (571 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sashiko bot, Dmitry Torokhov,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
[ Upstream commit 2c9b85a14abb4811e8d4773ccd13559e59792efb ]
ims_pcu_reset_packet() incorrectly sets have_stx to true, which implies
that the start-of-packet delimiter has already been received. This
causes the protocol parser to skip waiting for the next STX byte and
potentially process garbage data.
Correctly set have_stx to false when resetting the packet state.
Fixes: 875115b82c29 ("Input: ims-pcu - fix heap-buffer-overflow in ims_pcu_process_data()")
Cc: stable@vger.kernel.org
Reported-by: Sashiko bot <sashiko-bot@kernel.org>
Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/input/misc/ims-pcu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c
index 3dc624c75bb5c5..4cfcf6e945bba5 100644
--- a/drivers/input/misc/ims-pcu.c
+++ b/drivers/input/misc/ims-pcu.c
@@ -450,7 +450,7 @@ static void ims_pcu_handle_response(struct ims_pcu *pcu)
static void ims_pcu_reset_packet(struct ims_pcu *pcu)
{
- pcu->have_stx = true;
+ pcu->have_stx = false;
pcu->have_dle = false;
pcu->read_pos = 0;
pcu->check_sum = 0;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 035/602] soc: qcom: ice: Allow explicit votes on iface clock for ICE
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (33 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 034/602] Input: ims-pcu - fix logic error in packet reset Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 036/602] arm64: tegra: Fix CPU compatible string to cortex-a78ae on Tegra234 Greg Kroah-Hartman
` (570 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Manivannan Sadhasivam, Kuldeep Singh,
Konrad Dybcio, Harshal Dev, Bjorn Andersson, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Harshal Dev <harshal.dev@oss.qualcomm.com>
[ Upstream commit 0d5dc5818191b55e4364d04b1b898a14a2ccac38 ]
Since Qualcomm inline-crypto engine (ICE) is now a dedicated driver
de-coupled from the QCOM UFS driver, it explicitly votes for its required
clocks during probe. For scenarios where the 'clk_ignore_unused' flag is
not passed on the kernel command line, to avoid potential unclocked ICE
hardware register access during probe the ICE driver should additionally
vote on the 'iface' clock.
Also update the suspend and resume callbacks to handle un-voting and voting
on the 'iface' clock.
Fixes: 2afbf43a4aec6 ("soc: qcom: Make the Qualcomm UFS/SDCC ICE a dedicated driver")
Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
Reviewed-by: Kuldeep Singh <kuldeep.singh@oss.qualcomm.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20260416-qcom_ice_power_and_clk_vote-v5-2-5ccf5d7e2846@oss.qualcomm.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/soc/qcom/ice.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
index 85504a023e326a..0aa83175fbda10 100644
--- a/drivers/soc/qcom/ice.c
+++ b/drivers/soc/qcom/ice.c
@@ -49,6 +49,7 @@ struct qcom_ice {
struct device_link *link;
struct clk *core_clk;
+ struct clk *iface_clk;
};
static DEFINE_XARRAY(ice_handles);
@@ -150,8 +151,13 @@ int qcom_ice_resume(struct qcom_ice *ice)
err = clk_prepare_enable(ice->core_clk);
if (err) {
- dev_err(dev, "failed to enable core clock (%d)\n",
- err);
+ dev_err(dev, "Failed to enable core clock: %d\n", err);
+ return err;
+ }
+
+ err = clk_prepare_enable(ice->iface_clk);
+ if (err) {
+ dev_err(dev, "Failed to enable iface clock: %d\n", err);
return err;
}
@@ -161,6 +167,7 @@ EXPORT_SYMBOL_GPL(qcom_ice_resume);
int qcom_ice_suspend(struct qcom_ice *ice)
{
+ clk_disable_unprepare(ice->iface_clk);
clk_disable_unprepare(ice->core_clk);
return 0;
@@ -241,11 +248,17 @@ static struct qcom_ice *qcom_ice_create(struct device *dev,
engine->core_clk = devm_clk_get_optional_enabled(dev, "ice_core_clk");
if (!engine->core_clk)
engine->core_clk = devm_clk_get_optional_enabled(dev, "ice");
+ if (!engine->core_clk)
+ engine->core_clk = devm_clk_get_optional_enabled(dev, "core");
if (!engine->core_clk)
engine->core_clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(engine->core_clk))
return ERR_CAST(engine->core_clk);
+ engine->iface_clk = devm_clk_get_optional_enabled(dev, "iface");
+ if (IS_ERR(engine->iface_clk))
+ return ERR_CAST(engine->iface_clk);
+
if (!qcom_ice_check_supported(engine))
return ERR_PTR(-EOPNOTSUPP);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 036/602] arm64: tegra: Fix CPU compatible string to cortex-a78ae on Tegra234
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (34 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 035/602] soc: qcom: ice: Allow explicit votes on iface clock for ICE Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 037/602] firmware: arm_ffa: Respect firmware advertised RX/TX buffer size limits Greg Kroah-Hartman
` (569 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sumit Gupta, Thierry Reding,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sumit Gupta <sumitg@nvidia.com>
[ Upstream commit 0dfa1e960f86e032007882b032c5cc7d14ebe73e ]
The Tegra234 SoC uses Cortex-A78AE cores, not Cortex-A78. Update the
compatible string for all CPU nodes to match the actual hardware.
Tegra234 hardware reports:
# head /proc/cpuinfo | egrep 'implementer|part'
CPU implementer : 0x41
CPU part : 0xd42
Which maps to (from arch/arm64/include/asm/cputype.h):
#define ARM_CPU_IMP_ARM 0x41
#define ARM_CPU_PART_CORTEX_A78AE 0xD42
Fixes: a12cf5c339b08 ("arm64: tegra: Describe Tegra234 CPU hierarchy")
Signed-off-by: Sumit Gupta <sumitg@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
arch/arm64/boot/dts/nvidia/tegra234.dtsi | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/arch/arm64/boot/dts/nvidia/tegra234.dtsi b/arch/arm64/boot/dts/nvidia/tegra234.dtsi
index 75428e70a69252..c1d2d91975057a 100644
--- a/arch/arm64/boot/dts/nvidia/tegra234.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra234.dtsi
@@ -5262,7 +5262,7 @@ cpus {
#size-cells = <0>;
cpu0_0: cpu@0 {
- compatible = "arm,cortex-a78";
+ compatible = "arm,cortex-a78ae";
device_type = "cpu";
reg = <0x00000>;
@@ -5281,7 +5281,7 @@ cpu0_0: cpu@0 {
};
cpu0_1: cpu@100 {
- compatible = "arm,cortex-a78";
+ compatible = "arm,cortex-a78ae";
device_type = "cpu";
reg = <0x00100>;
@@ -5300,7 +5300,7 @@ cpu0_1: cpu@100 {
};
cpu0_2: cpu@200 {
- compatible = "arm,cortex-a78";
+ compatible = "arm,cortex-a78ae";
device_type = "cpu";
reg = <0x00200>;
@@ -5319,7 +5319,7 @@ cpu0_2: cpu@200 {
};
cpu0_3: cpu@300 {
- compatible = "arm,cortex-a78";
+ compatible = "arm,cortex-a78ae";
device_type = "cpu";
reg = <0x00300>;
@@ -5338,7 +5338,7 @@ cpu0_3: cpu@300 {
};
cpu1_0: cpu@10000 {
- compatible = "arm,cortex-a78";
+ compatible = "arm,cortex-a78ae";
device_type = "cpu";
reg = <0x10000>;
@@ -5357,7 +5357,7 @@ cpu1_0: cpu@10000 {
};
cpu1_1: cpu@10100 {
- compatible = "arm,cortex-a78";
+ compatible = "arm,cortex-a78ae";
device_type = "cpu";
reg = <0x10100>;
@@ -5376,7 +5376,7 @@ cpu1_1: cpu@10100 {
};
cpu1_2: cpu@10200 {
- compatible = "arm,cortex-a78";
+ compatible = "arm,cortex-a78ae";
device_type = "cpu";
reg = <0x10200>;
@@ -5395,7 +5395,7 @@ cpu1_2: cpu@10200 {
};
cpu1_3: cpu@10300 {
- compatible = "arm,cortex-a78";
+ compatible = "arm,cortex-a78ae";
device_type = "cpu";
reg = <0x10300>;
@@ -5414,7 +5414,7 @@ cpu1_3: cpu@10300 {
};
cpu2_0: cpu@20000 {
- compatible = "arm,cortex-a78";
+ compatible = "arm,cortex-a78ae";
device_type = "cpu";
reg = <0x20000>;
@@ -5433,7 +5433,7 @@ cpu2_0: cpu@20000 {
};
cpu2_1: cpu@20100 {
- compatible = "arm,cortex-a78";
+ compatible = "arm,cortex-a78ae";
device_type = "cpu";
reg = <0x20100>;
@@ -5452,7 +5452,7 @@ cpu2_1: cpu@20100 {
};
cpu2_2: cpu@20200 {
- compatible = "arm,cortex-a78";
+ compatible = "arm,cortex-a78ae";
device_type = "cpu";
reg = <0x20200>;
@@ -5471,7 +5471,7 @@ cpu2_2: cpu@20200 {
};
cpu2_3: cpu@20300 {
- compatible = "arm,cortex-a78";
+ compatible = "arm,cortex-a78ae";
device_type = "cpu";
reg = <0x20300>;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 037/602] firmware: arm_ffa: Respect firmware advertised RX/TX buffer size limits
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (35 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 036/602] arm64: tegra: Fix CPU compatible string to cortex-a78ae on Tegra234 Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 038/602] IB/mad: Drop unmatched RMPP responses before reassembly Greg Kroah-Hartman
` (568 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Sudeep Holla, Seth Forshee,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Seth Forshee <sforshee@nvidia.com>
[ Upstream commit 53716a4d745f1dac7aff33f3d1494b701eb2f888 ]
FFA_FEATURES reports the minimum size and alignment boundary required
for RXTX_MAP. In FF-A v1.2 and later it can also report a maximum buffer
size, with zero meaning that no maximum is enforced.
The driver only used the minimum value and then rounded it up to PAGE_SIZE
before invoking RXTX_MAP after commit 83210251fd70 ("firmware: arm_ffa:
Use the correct buffer size during RXTX_MAP"). On systems where PAGE_SIZE
is larger than the advertised minimum, this can exceed a non-zero maximum
reported by firmware. Older implementations do not advertise a maximum and
may also reject the rounded-up size.
Decode the maximum size and clamp the page-aligned minimum to it when it
is present. If no maximum is advertised and RXTX_MAP rejects the rounded
size with INVALID_PARAMETERS, retry with the advertised minimum size.
Record drv_info->rxtx_bufsz only after RXTX_MAP succeeds so it reflects
the size registered with firmware.
While there, also update RXTX_MAP_MIN_BUFSZ() to use FIELD_GET() for
consistency.
Fixes: 83210251fd70 ("firmware: arm_ffa: Use the correct buffer size during RXTX_MAP")
Suggested-by: Sudeep Holla <sudeep.holla@kernel.org>
Signed-off-by: Seth Forshee <sforshee@nvidia.com>
Link: https://patch.msgid.link/20260602-b4-ffa-rxtx-map-fixes-v2-1-7cb06508da84@nvidia.com
(sudeep.holla: Minor rewording subject and commit message)
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/firmware/arm_ffa/driver.c | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 3b221ba990aa1e..67fc9e46001b77 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -32,6 +32,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
+#include <linux/minmax.h>
#include <linux/module.h>
#include <linux/mm.h>
#include <linux/mutex.h>
@@ -55,7 +56,9 @@
(FIELD_PREP(SENDER_ID_MASK, (s)) | FIELD_PREP(RECEIVER_ID_MASK, (r)))
#define RXTX_MAP_MIN_BUFSZ_MASK GENMASK(1, 0)
-#define RXTX_MAP_MIN_BUFSZ(x) ((x) & RXTX_MAP_MIN_BUFSZ_MASK)
+#define RXTX_MAP_MAX_BUFSZ_MASK GENMASK(31, 16)
+#define RXTX_MAP_MIN_BUFSZ(x) (FIELD_GET(RXTX_MAP_MIN_BUFSZ_MASK, (x)))
+#define RXTX_MAP_MAX_BUFSZ(x) (FIELD_GET(RXTX_MAP_MAX_BUFSZ_MASK, (x)))
#define FFA_MAX_NOTIFICATIONS 64
@@ -1855,7 +1858,7 @@ static int __init ffa_init(void)
{
int ret;
u32 buf_sz;
- size_t rxtx_bufsz = SZ_4K;
+ size_t rxtx_min_bufsz = SZ_4K, rxtx_max_bufsz = 0, rxtx_bufsz;
ret = ffa_transport_init(&invoke_ffa_fn);
if (ret)
@@ -1878,15 +1881,18 @@ static int __init ffa_init(void)
ret = ffa_features(FFA_FN_NATIVE(RXTX_MAP), 0, &buf_sz, NULL);
if (!ret) {
if (RXTX_MAP_MIN_BUFSZ(buf_sz) == 1)
- rxtx_bufsz = SZ_64K;
+ rxtx_min_bufsz = SZ_64K;
else if (RXTX_MAP_MIN_BUFSZ(buf_sz) == 2)
- rxtx_bufsz = SZ_16K;
+ rxtx_min_bufsz = SZ_16K;
else
- rxtx_bufsz = SZ_4K;
+ rxtx_min_bufsz = SZ_4K;
+
+ rxtx_max_bufsz = RXTX_MAP_MAX_BUFSZ(buf_sz) * SZ_4K;
+ if (rxtx_max_bufsz != 0 && rxtx_max_bufsz < rxtx_min_bufsz)
+ rxtx_max_bufsz = rxtx_min_bufsz;
}
- rxtx_bufsz = PAGE_ALIGN(rxtx_bufsz);
- drv_info->rxtx_bufsz = rxtx_bufsz;
+ rxtx_bufsz = min_not_zero(PAGE_ALIGN(rxtx_min_bufsz), rxtx_max_bufsz);
drv_info->rx_buffer = alloc_pages_exact(rxtx_bufsz, GFP_KERNEL);
if (!drv_info->rx_buffer) {
ret = -ENOMEM;
@@ -1902,10 +1908,17 @@ static int __init ffa_init(void)
ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer),
virt_to_phys(drv_info->rx_buffer),
rxtx_bufsz / FFA_PAGE_SIZE);
+ if (ret == -EINVAL && !rxtx_max_bufsz && rxtx_min_bufsz < rxtx_bufsz) {
+ rxtx_bufsz = rxtx_min_bufsz;
+ ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer),
+ virt_to_phys(drv_info->rx_buffer),
+ rxtx_bufsz / FFA_PAGE_SIZE);
+ }
if (ret) {
pr_err("failed to register FFA RxTx buffers\n");
goto free_pages;
}
+ drv_info->rxtx_bufsz = rxtx_bufsz;
mutex_init(&drv_info->rx_lock);
mutex_init(&drv_info->tx_lock);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 038/602] IB/mad: Drop unmatched RMPP responses before reassembly
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (36 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 037/602] firmware: arm_ffa: Respect firmware advertised RX/TX buffer size limits Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 039/602] mtd: mtdswap: remove debugfs stats file on teardown Greg Kroah-Hartman
` (567 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Michael Bommarito, Leon Romanovsky,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <michael.bommarito@gmail.com>
[ Upstream commit d2e52d610b9b09694261632340b801a421e0b0c5 ]
Kernel-handled RMPP receive processing starts reassembly for active
DATA responses before the response is matched to an outstanding send.
The normal match happens later, after ib_process_rmpp_recv_wc() has
either assembled a complete message or consumed the segment.
That ordering lets an unsolicited response that routes to a kernel
RMPP agent by the high TID bits allocate or extend RMPP receive state
before the full TID and source address are checked against a real
request. A reordered burst can therefore reach the receive-side
insertion path even though the response would not match any send.
For kernel-handled RMPP DATA responses, require the existing
ib_find_send_mad() match before entering RMPP reassembly. The matcher
already checks the full TID, management class and source address/GID
against the agent wait, backlog and in-flight send lists. If there is
no match, drop the response without creating RMPP state.
This leaves the RMPP window behavior unchanged and only rejects
responses that have no corresponding request.
Fixes: fa619a77046b ("[PATCH] IB: Add RMPP implementation")
Assisted-by: Codex:gpt-5-5-xhigh
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Link: https://patch.msgid.link/3170ff3bc389a930bb1641f2caa394a0b2241579.1780774907.git.michael.bommarito@gmail.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/infiniband/core/mad.c | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 73f3a0b9a54b5f..96c1fd8039fb59 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -1778,6 +1778,24 @@ void ib_mark_mad_done(struct ib_mad_send_wr_private *mad_send_wr)
&mad_send_wr->mad_agent_priv->done_list);
}
+static bool is_kernel_rmpp_data_response(struct ib_mad_agent_private *agent,
+ struct ib_mad_recv_wc *mad_recv_wc)
+{
+ const struct ib_mad_hdr *mad_hdr = &mad_recv_wc->recv_buf.mad->mad_hdr;
+ struct ib_rmpp_mad *rmpp_mad;
+
+ if (!ib_mad_kernel_rmpp_agent(&agent->agent) ||
+ !ib_response_mad(mad_hdr) ||
+ !ib_is_mad_class_rmpp(mad_hdr->mgmt_class))
+ return false;
+
+ rmpp_mad = (struct ib_rmpp_mad *)mad_recv_wc->recv_buf.mad;
+
+ return (ib_get_rmpp_flags(&rmpp_mad->rmpp_hdr) &
+ IB_MGMT_RMPP_FLAG_ACTIVE) &&
+ rmpp_mad->rmpp_hdr.rmpp_type == IB_MGMT_RMPP_TYPE_DATA;
+}
+
static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
struct ib_mad_recv_wc *mad_recv_wc)
{
@@ -1796,6 +1814,18 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,
}
list_add(&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list);
+ if (is_kernel_rmpp_data_response(mad_agent_priv, mad_recv_wc)) {
+ spin_lock_irqsave(&mad_agent_priv->lock, flags);
+ mad_send_wr = ib_find_send_mad(mad_agent_priv, mad_recv_wc);
+ spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
+
+ if (!mad_send_wr) {
+ ib_free_recv_mad(mad_recv_wc);
+ deref_mad_agent(mad_agent_priv);
+ return;
+ }
+ }
+
if (ib_mad_kernel_rmpp_agent(&mad_agent_priv->agent)) {
mad_recv_wc = ib_process_rmpp_recv_wc(mad_agent_priv,
mad_recv_wc);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 039/602] mtd: mtdswap: remove debugfs stats file on teardown
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (37 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 038/602] IB/mad: Drop unmatched RMPP responses before reassembly Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 040/602] mtd: nand: mtk-ecc: stop on ECC idle timeouts Greg Kroah-Hartman
` (566 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Pengpeng Hou, Miquel Raynal,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <pengpeng@iscas.ac.cn>
[ Upstream commit 66fb31358108d10245b9e4ef0eef3e7d9747055e ]
mtdswap_add_debugfs() creates an mtdswap_stats debugfs file under the
per-MTD debugfs directory, but mtdswap_remove_dev() never removes it
before freeing the mtdswap_dev.
Store the returned dentry and remove it during device teardown before the
driver-private state is freed.
Fixes: a32159024620 ("mtd: Add mtdswap block driver")
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/mtd/mtdswap.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/mtdswap.c b/drivers/mtd/mtdswap.c
index 680366616da240..4d695875ea1b23 100644
--- a/drivers/mtd/mtdswap.c
+++ b/drivers/mtd/mtdswap.c
@@ -125,6 +125,7 @@ struct mtdswap_dev {
char *page_buf;
char *oob_buf;
+ struct dentry *debugfs_stats;
};
struct mtdswap_oobdata {
@@ -1262,7 +1263,8 @@ static int mtdswap_add_debugfs(struct mtdswap_dev *d)
if (IS_ERR_OR_NULL(root))
return -1;
- debugfs_create_file("mtdswap_stats", S_IRUSR, root, d, &mtdswap_fops);
+ d->debugfs_stats = debugfs_create_file("mtdswap_stats", 0400, root,
+ d, &mtdswap_fops);
return 0;
}
@@ -1463,6 +1465,7 @@ static void mtdswap_remove_dev(struct mtd_blktrans_dev *dev)
{
struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev);
+ debugfs_remove(d->debugfs_stats);
del_mtd_blktrans_dev(dev);
mtdswap_cleanup(d);
kfree(d);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 040/602] mtd: nand: mtk-ecc: stop on ECC idle timeouts
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (38 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 039/602] mtd: mtdswap: remove debugfs stats file on teardown Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 041/602] btrfs: reject free space cache with more entries than pages Greg Kroah-Hartman
` (565 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Pengpeng Hou, Miquel Raynal,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <pengpeng@iscas.ac.cn>
[ Upstream commit 16f7ec8d5dc100eafd2c8e06cd30340a30b104a1 ]
mtk_ecc_wait_idle() logs when the encoder or decoder does not become
idle, but returns void. Callers can therefore configure a non-idle ECC
engine or read parity bytes after an unconfirmed encoder idle state.
Return the idle poll result and propagate it from the enable and encode
paths that require the engine to be idle before continuing.
Fixes: 1d6b1e464950 ("mtd: mediatek: driver for MTK Smart Device")
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/mtd/nand/ecc-mtk.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/nand/ecc-mtk.c b/drivers/mtd/nand/ecc-mtk.c
index c75bb8b80cc1e1..96703f0a418ea2 100644
--- a/drivers/mtd/nand/ecc-mtk.c
+++ b/drivers/mtd/nand/ecc-mtk.c
@@ -123,8 +123,8 @@ static int mt7622_ecc_regs[] = {
[ECC_DECIRQ_STA] = 0x144,
};
-static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc,
- enum mtk_ecc_operation op)
+static inline int mtk_ecc_wait_idle(struct mtk_ecc *ecc,
+ enum mtk_ecc_operation op)
{
struct device *dev = ecc->dev;
u32 val;
@@ -136,6 +136,8 @@ static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc,
if (ret)
dev_warn(dev, "%s NOT idle\n",
op == ECC_ENCODE ? "encoder" : "decoder");
+
+ return ret;
}
static irqreturn_t mtk_ecc_irq(int irq, void *id)
@@ -312,7 +314,11 @@ int mtk_ecc_enable(struct mtk_ecc *ecc, struct mtk_ecc_config *config)
return ret;
}
- mtk_ecc_wait_idle(ecc, op);
+ ret = mtk_ecc_wait_idle(ecc, op);
+ if (ret) {
+ mutex_unlock(&ecc->lock);
+ return ret;
+ }
ret = mtk_ecc_config(ecc, config);
if (ret) {
@@ -412,7 +418,9 @@ int mtk_ecc_encode(struct mtk_ecc *ecc, struct mtk_ecc_config *config,
if (ret)
goto timeout;
- mtk_ecc_wait_idle(ecc, ECC_ENCODE);
+ ret = mtk_ecc_wait_idle(ecc, ECC_ENCODE);
+ if (ret)
+ goto timeout;
/* Program ECC bytes to OOB: per sector oob = FDM + ECC + SPARE */
len = (config->strength * ecc->caps->parity_bits + 7) >> 3;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 041/602] btrfs: reject free space cache with more entries than pages
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (39 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 040/602] mtd: nand: mtk-ecc: stop on ECC idle timeouts Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 042/602] btrfs: fix root leak if its reloc root is unexpected in merge_reloc_roots() Greg Kroah-Hartman
` (564 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Weiming Shi, Qu Wenruo, Xiang Mei,
David Sterba, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei <xmei5@asu.edu>
[ Upstream commit a2d8d5647ed854e38f941741aea45b9eb15a6350 ]
When loading a v1 free space cache, __load_free_space_cache() takes
num_entries and num_bitmaps straight from the on-disk
btrfs_free_space_header. That header is stored in the tree_root under a key
with type 0, which the tree-checker has no case for, so neither count is
validated before the load trusts it.
The load loops num_entries times and maps the next page whenever the current
one runs out, going through io_ctl_check_crc() -> io_ctl_map_page(), which
does io_ctl->pages[io_ctl->index++]. But pages[] is allocated in
io_ctl_init() from the cache inode's i_size, not from num_entries:
num_pages = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE);
io_ctl->pages = kcalloc(num_pages, sizeof(struct page *), GFP_NOFS);
So if num_entries claims more records than the pages can hold, io_ctl->index
runs off the end of pages[]. The write side never hits this because
io_ctl_add_entry() and io_ctl_add_bitmap() both stop once
io_ctl->index >= io_ctl->num_pages; the read side just never had the same
check.
To trigger it, take a clean cache (num_entries = <N> here), set num_entries
in the header to 0x10000, and fix up the leaf checksum so it still passes
the tree-checker. The cache inode has i_size = 65536, so num_pages is 16 and
pages[] is a 16-pointer (kmalloc-128) array. The load now tries to read
65536 entries, io_ctl->index walks up to 16, and pages[16] is read past the
array:
BUG: KASAN: slab-out-of-bounds in io_ctl_check_crc (fs/btrfs/free-space-cache.c:420 fs/btrfs/free-space-cache.c:565)
Read of size 8 at addr ffff88800c833a80 by task kworker/u8:3/58
io_ctl_check_crc (fs/btrfs/free-space-cache.c:420 fs/btrfs/free-space-cache.c:565)
__load_free_space_cache (fs/btrfs/free-space-cache.c:655 fs/btrfs/free-space-cache.c:820)
load_free_space_cache (fs/btrfs/free-space-cache.c:1017)
caching_thread (fs/btrfs/block-group.c:880)
btrfs_work_helper (fs/btrfs/async-thread.c:312)
process_one_work
worker_thread
kthread
ret_from_fork
free-space-cache.c:420 is io_ctl_map_page(), inlined into io_ctl_check_crc()
at line 565, which is why that is the frame KASAN names. The out-of-bounds
slot is then treated as a struct page and handed to crc32c(), so the bad
read turns into a GP fault.
Add the missing check to io_ctl_check_crc(), which is where both the entry
loop and the bitmap loop end up. When num_entries is too large the load now
fails like any corrupt cache: __load_free_space_cache() drops it and rebuilds
the free space from the extent tree, so a valid cache is never rejected.
Reported-by: Weiming Shi <bestswngs@gmail.com>
Fixes: 5b0e95bf607d ("Btrfs: inline checksums into the disk free space cache")
Link: https://lore.kernel.org/linux-btrfs/CAPpSM+RMPByMCKXvM5QFKToxsyNccfuFLWMdD0mfd0wh2Ja62w@mail.gmail.com/
Assisted-by: Claude:claude-opus-4-8
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Xiang Mei <xmei5@asu.edu>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/btrfs/free-space-cache.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index f4bcb25306606a..01588dd3c7028f 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -556,6 +556,9 @@ static int io_ctl_check_crc(struct btrfs_io_ctl *io_ctl, int index)
u32 crc = ~(u32)0;
unsigned offset = 0;
+ if (index >= io_ctl->num_pages)
+ return -EIO;
+
if (index == 0)
offset = sizeof(u32) * io_ctl->num_pages;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 042/602] btrfs: fix root leak if its reloc root is unexpected in merge_reloc_roots()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (40 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 041/602] btrfs: reject free space cache with more entries than pages Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 043/602] firmware: arm_ffa: Fix NULL dereference in ffa_partition_info_get() Greg Kroah-Hartman
` (563 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Qu Wenruo, Johannes Thumshirn,
Filipe Manana, David Sterba, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana <fdmanana@suse.com>
[ Upstream commit ce6050bafb4e33377dc17fcc357736bfc351180c ]
If we have an unexpected reloc_root for our root, we jump to the out label
but never drop the reference we obtained for root, resulting in a leak.
Add a missing btrfs_put_root() call.
Fixes: 24213fa46c70 ("btrfs: do proper error handling in merge_reloc_roots")
Reviewed-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/btrfs/relocation.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 43e8c331168e94..d2a1323e8b1034 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -1956,6 +1956,7 @@ void merge_reloc_roots(struct reloc_control *rc)
* corruption, e.g. bad reloc tree key offset.
*/
ret = -EINVAL;
+ btrfs_put_root(root);
goto out;
}
ret = merge_reloc_root(rc, root);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 043/602] firmware: arm_ffa: Fix NULL dereference in ffa_partition_info_get()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (41 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 042/602] btrfs: fix root leak if its reloc root is unexpected in merge_reloc_roots() Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 044/602] RDMA/cma: Fix hardware address comparison length in netevent callback Greg Kroah-Hartman
` (562 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Unnathi Chalicheemala, Sudeep Holla,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Unnathi Chalicheemala <unnathi.chalicheemala@oss.qualcomm.com>
[ Upstream commit 8ae5f8e4836667fcaffdf2e3c6068b0a8b364dd8 ]
ffa_partition_info_get() passes uuid_str directly to uuid_parse()
without a NULL check. When a caller passes NULL, uuid_parse() ->
__uuid_parse() -> uuid_is_valid() dereferences the pointer, causing
a kernel panic:
| Unable to handle kernel NULL pointer dereference at virtual address
| 0000000000000040
| pc : uuid_parse+0x40/0xac
| lr : ffa_partition_info_get+0x1c/0x94 [arm_ffa]
Add a NULL guard before uuid_parse() so a NULL argument returns
-ENODEV instead of crashing. Callers are expected to always supply
a valid partition UUID, so NULL is not a supported input.
Fixes: d0c0bce83122 ("firmware: arm_ffa: Setup in-kernel users of FFA partitions")
Signed-off-by: Unnathi Chalicheemala <unnathi.chalicheemala@oss.qualcomm.com>
Link: https://patch.msgid.link/20260617-ffa_partition_nullptr_fix-v2-1-bc801b4ce34c@oss.qualcomm.com
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/firmware/arm_ffa/driver.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 67fc9e46001b77..62222c9cfc3e6d 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -1029,7 +1029,7 @@ static int ffa_partition_info_get(const char *uuid_str,
uuid_t uuid;
struct ffa_partition_info *pbuf;
- if (uuid_parse(uuid_str, &uuid)) {
+ if (!uuid_str || uuid_parse(uuid_str, &uuid)) {
pr_err("invalid uuid (%s)\n", uuid_str);
return -ENODEV;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 044/602] RDMA/cma: Fix hardware address comparison length in netevent callback
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (42 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 043/602] firmware: arm_ffa: Fix NULL dereference in ffa_partition_info_get() Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 045/602] RDMA/umem: Add pinned revocable dmabuf import interface Greg Kroah-Hartman
` (561 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Or Gerlitz, Leon Romanovsky,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Or Gerlitz <ogerlitz@ddn.com>
[ Upstream commit 18313833e2c6de222a4f6c072da759d0d5888528 ]
The cited commit hardcoded the hardware address comparison len to ETH_ALEN.
This breaks IPoIB, which uses 20-byte addresses. By truncating the
memcmp, the CMA may incorrectly assume the target address is
unchanged and fails to abort the stalled connection.
Fix this by replacing ETH_ALEN with the dynamic neigh->dev->addr_len
to correctly evaluate the full address regardless of the link layer.
Fixes: 925d046e7e52 ("RDMA/core: Add a netevent notifier to cma")
Signed-off-by: Or Gerlitz <ogerlitz@ddn.com>
Link: https://patch.msgid.link/20260617-fix-cma-ipoib-v1-1-03f869344304@ddn.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/infiniband/core/cma.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 52d70eeb0c52ec..a225eae78d3e58 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -5231,7 +5231,7 @@ static int cma_netevent_callback(struct notifier_block *self,
list_for_each_entry(current_id, &ips_node->id_list, id_list_entry) {
if (!memcmp(current_id->id.route.addr.dev_addr.dst_dev_addr,
- neigh->ha, ETH_ALEN))
+ neigh->ha, neigh->dev->addr_len))
continue;
cma_id_get(current_id);
if (!queue_work(cma_wq, ¤t_id->id.net_work))
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 045/602] RDMA/umem: Add pinned revocable dmabuf import interface
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (43 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 044/602] RDMA/cma: Fix hardware address comparison length in netevent callback Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 046/602] RDMA/irdma: Prevent rereg_mr for non-mem regions Greg Kroah-Hartman
` (560 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jacob Moroni, Leon Romanovsky,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jacob Moroni <jmoroni@google.com>
[ Upstream commit ff85a2ebacbdaec9f28c4660c991295ace93cd1c ]
Added an interface for importing a pinned but revocable dmabuf.
This interface can be used by drivers that are capable of revocation
so that they can import dmabufs from exporters that may require it,
such as VFIO.
This interface implements a two step process, where drivers will first
call ib_umem_dmabuf_get_pinned_revocable_and_lock() which will pin and
map the dmabuf (and provide a functional move_notify/invalidate_mappings
callback), but will return with the lock still held so that the
driver can then populate the callback via
ib_umem_dmabuf_set_revoke_locked() without races from concurrent
revocations. This scheme also allows for easier integration with drivers
that may not have actually allocated their internal MR objects at the time
of the get_pinned_revocable* call.
Signed-off-by: Jacob Moroni <jmoroni@google.com>
Link: https://patch.msgid.link/20260305170826.3803155-4-jmoroni@google.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Stable-dep-of: a846aecb931b ("RDMA/irdma: Prevent rereg_mr for non-mem regions")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/infiniband/core/umem_dmabuf.c | 61 +++++++++++++++++++++++++++
include/rdma/ib_umem.h | 19 +++++++++
2 files changed, 80 insertions(+)
diff --git a/drivers/infiniband/core/umem_dmabuf.c b/drivers/infiniband/core/umem_dmabuf.c
index f16491bd5f2b11..1206993e2e3e83 100644
--- a/drivers/infiniband/core/umem_dmabuf.c
+++ b/drivers/infiniband/core/umem_dmabuf.c
@@ -206,6 +206,10 @@ static void ib_umem_dmabuf_revoke_locked(struct dma_buf_attachment *attach)
if (umem_dmabuf->revoked)
return;
+
+ if (umem_dmabuf->pinned_revoke)
+ umem_dmabuf->pinned_revoke(umem_dmabuf->private);
+
ib_umem_dmabuf_unmap_pages(umem_dmabuf);
if (umem_dmabuf->pinned) {
dma_buf_unpin(umem_dmabuf->attach);
@@ -214,6 +218,11 @@ static void ib_umem_dmabuf_revoke_locked(struct dma_buf_attachment *attach)
umem_dmabuf->revoked = 1;
}
+static struct dma_buf_attach_ops ib_umem_dmabuf_attach_pinned_revocable_ops = {
+ .allow_peer2peer = true,
+ .move_notify = ib_umem_dmabuf_revoke_locked,
+};
+
static struct ib_umem_dmabuf *
ib_umem_dmabuf_get_pinned_and_lock(struct ib_device *device,
struct device *dma_device,
@@ -266,6 +275,58 @@ ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device,
}
EXPORT_SYMBOL(ib_umem_dmabuf_get_pinned_with_dma_device);
+/**
+ * ib_umem_dmabuf_get_pinned_revocable_and_lock - Map & pin a revocable dmabuf
+ * @device: IB device.
+ * @offset: Start offset.
+ * @size: Length.
+ * @fd: dmabuf fd.
+ * @access: Access flags.
+ *
+ * Obtains a umem from a dmabuf for drivers/devices that can support revocation.
+ *
+ * Returns with dma_resv_lock held upon success. The driver must set the revoke
+ * callback prior to unlock by calling ib_umem_dmabuf_set_revoke_locked().
+ *
+ * When a revocation occurs, the revoke callback will be called. The driver must
+ * ensure that the region is no longer accessed when the callback returns. Any
+ * subsequent access attempts should also probably cause an AE for MRs.
+ *
+ * If the umem is used for an MR, the driver must ensure that the key remains in
+ * use such that it cannot be obtained by a new region until this region is
+ * fully deregistered (i.e., ibv_dereg_mr). If a driver needs to serialize with
+ * revoke calls, it can use dma_resv_lock.
+ *
+ * If successful, then the revoke callback may be called at any time and will
+ * also be called automatically upon ib_umem_release (serialized). The revoke
+ * callback will be called one time at most.
+ *
+ * Return: A pointer to ib_umem_dmabuf on success, or an ERR_PTR on failure.
+ */
+struct ib_umem_dmabuf *
+ib_umem_dmabuf_get_pinned_revocable_and_lock(struct ib_device *device,
+ unsigned long offset, size_t size,
+ int fd, int access)
+{
+ const struct dma_buf_attach_ops *ops =
+ &ib_umem_dmabuf_attach_pinned_revocable_ops;
+
+ return ib_umem_dmabuf_get_pinned_and_lock(device, device->dma_device,
+ offset, size, fd, access,
+ ops);
+}
+EXPORT_SYMBOL(ib_umem_dmabuf_get_pinned_revocable_and_lock);
+
+void ib_umem_dmabuf_set_revoke_locked(struct ib_umem_dmabuf *umem_dmabuf,
+ void (*revoke)(void *priv), void *priv)
+{
+ dma_resv_assert_held(umem_dmabuf->attach->dmabuf->resv);
+
+ umem_dmabuf->pinned_revoke = revoke;
+ umem_dmabuf->private = priv;
+}
+EXPORT_SYMBOL(ib_umem_dmabuf_set_revoke_locked);
+
struct ib_umem_dmabuf *ib_umem_dmabuf_get_pinned(struct ib_device *device,
unsigned long offset,
size_t size, int fd,
diff --git a/include/rdma/ib_umem.h b/include/rdma/ib_umem.h
index 694f7e0876af81..4c5329b504d0cb 100644
--- a/include/rdma/ib_umem.h
+++ b/include/rdma/ib_umem.h
@@ -36,6 +36,7 @@ struct ib_umem_dmabuf {
struct scatterlist *last_sg;
unsigned long first_sg_offset;
unsigned long last_sg_trim;
+ void (*pinned_revoke)(void *priv);
void *private;
u8 pinned : 1;
u8 revoked : 1;
@@ -124,6 +125,12 @@ struct ib_umem_dmabuf *ib_umem_dmabuf_get_pinned(struct ib_device *device,
size_t size, int fd,
int access);
struct ib_umem_dmabuf *
+ib_umem_dmabuf_get_pinned_revocable_and_lock(struct ib_device *device,
+ unsigned long offset, size_t size,
+ int fd, int access);
+void ib_umem_dmabuf_set_revoke_locked(struct ib_umem_dmabuf *umem_dmabuf,
+ void (*revoke)(void *priv), void *priv);
+struct ib_umem_dmabuf *
ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device,
struct device *dma_device,
unsigned long offset, size_t size,
@@ -180,6 +187,18 @@ ib_umem_dmabuf_get_pinned(struct ib_device *device, unsigned long offset,
return ERR_PTR(-EOPNOTSUPP);
}
+static inline struct ib_umem_dmabuf *
+ib_umem_dmabuf_get_pinned_revocable_and_lock(struct ib_device *device,
+ unsigned long offset, size_t size,
+ int fd, int access)
+{
+ return ERR_PTR(-EOPNOTSUPP);
+}
+
+static inline void
+ib_umem_dmabuf_set_revoke_locked(struct ib_umem_dmabuf *umem_dmabuf,
+ void (*revoke)(void *priv), void *priv) {}
+
static inline struct ib_umem_dmabuf *
ib_umem_dmabuf_get_pinned_with_dma_device(struct ib_device *device,
struct device *dma_device,
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 046/602] RDMA/irdma: Prevent rereg_mr for non-mem regions
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (44 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 045/602] RDMA/umem: Add pinned revocable dmabuf import interface Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 047/602] RDMA/erdma: initialize ret for empty receive WR lists Greg Kroah-Hartman
` (559 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jacob Moroni, David Hu,
Leon Romanovsky, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jacob Moroni <jmoroni@google.com>
[ Upstream commit a846aecb931b4d65d5eafa92a0623545af46d4f2 ]
When a QP/CQ/SRQ is created, a two step process is used
where the buffer is allocated in userspace and explicitly
registered with the normal reg_mr mechanism prior to creating
the actual QP/CQ/SRQ object.
These special registrations are indicated via an ABI field
so the driver knows that they do not have a valid mkey and
to skip the actual CQP command submission.
Since these are real MR objects from the core's perspective,
it is possible for a user application to invoke rereg_mr on them
and cause a real CQP op to be emitted with the zero-initialized
mkey value of 0.
Fix this by preventing rereg_mr on these special regions.
Fixes: 5ac388db27c4 ("RDMA/irdma: Add support to re-register a memory region")
Signed-off-by: Jacob Moroni <jmoroni@google.com>
Reviewed-by: David Hu <xuehaohu@google.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/infiniband/hw/irdma/verbs.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index 92b56338819ef8..255c6d21756ba4 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -3252,6 +3252,9 @@ static struct ib_mr *irdma_rereg_user_mr(struct ib_mr *ib_mr, int flags,
if (flags & ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS))
return ERR_PTR(-EOPNOTSUPP);
+ if (iwmr->type != IRDMA_MEMREG_TYPE_MEM)
+ return ERR_PTR(-EINVAL);
+
ret = ib_umem_check_rereg(iwmr->region, flags, new_access);
if (ret)
return ERR_PTR(ret);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 047/602] RDMA/erdma: initialize ret for empty receive WR lists
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (45 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 046/602] RDMA/irdma: Prevent rereg_mr for non-mem regions Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 048/602] RDMA/hns: Fix potential integer overflow in mhop hem cleanup Greg Kroah-Hartman
` (558 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Ruoyu Wang, Cheng Xu,
Jason Gunthorpe, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <ruoyuw560@gmail.com>
[ Upstream commit 2815a277c53e9a84784d6410cd55a9da5b33068d ]
erdma_post_recv() returns ret after walking the receive work request list.
If the caller passes an empty list, the loop is skipped and ret is not
assigned.
Initialize ret to 0 so an empty receive work request list returns success
instead of stack data.
Fixes: 155055771704 ("RDMA/erdma: Add verbs implementation")
Link: https://patch.msgid.link/r/20260618041752.481193-1-ruoyuw560@gmail.com
Signed-off-by: Ruoyu Wang <ruoyuw560@gmail.com>
Reviewed-by: Cheng Xu <chengyou@linux.alibaba.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/infiniband/hw/erdma/erdma_qp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/infiniband/hw/erdma/erdma_qp.c b/drivers/infiniband/hw/erdma/erdma_qp.c
index 4d1f9114cd97c5..4dfab0c49e5192 100644
--- a/drivers/infiniband/hw/erdma/erdma_qp.c
+++ b/drivers/infiniband/hw/erdma/erdma_qp.c
@@ -573,7 +573,7 @@ int erdma_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *recv_wr,
const struct ib_recv_wr *wr = recv_wr;
struct erdma_qp *qp = to_eqp(ibqp);
unsigned long flags;
- int ret;
+ int ret = 0;
spin_lock_irqsave(&qp->lock, flags);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 048/602] RDMA/hns: Fix potential integer overflow in mhop hem cleanup
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (46 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 047/602] RDMA/erdma: initialize ret for empty receive WR lists Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 049/602] RDMA/siw: publish QP after initialization Greg Kroah-Hartman
` (557 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Danila Chernetsov, Junxian Huang,
Jason Gunthorpe, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Danila Chernetsov <listdansp@mail.ru>
[ Upstream commit 9f0f2d2121f16d420199a82ac5bbc242269133b3 ]
In hns_roce_cleanup_mhop_hem_table(), the expression:
obj = i * buf_chunk_size / table->obj_size;
is evaluated using 32-bit unsigned arithmetic because
'buf_chunk_size' is u32 and the usual arithmetic conversions convert
'i' to unsigned int. The result is assigned to a u64 variable, but the
multiplication may overflow before the assignment.
For sufficiently large HEM tables, this produces an incorrect object
index passed to hns_roce_table_mhop_put().
Cast 'i' to u64 before the multiplication so that the intermediate
calculation is performed with 64-bit arithmetic.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
Fixes: a25d13cbe816 ("RDMA/hns: Add the interfaces to support multi hop addressing for the contexts in hip08")
Link: https://patch.msgid.link/r/20260627095951.51378-1-listdansp@mail.ru
Signed-off-by: Danila Chernetsov <listdansp@mail.ru>
Reviewed-by: Junxian Huang <huangjunxian6@hisilicon.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/infiniband/hw/hns/hns_roce_hem.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c
index 1680d0ac071ed1..ae7a3939124f23 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hem.c
+++ b/drivers/infiniband/hw/hns/hns_roce_hem.c
@@ -842,7 +842,7 @@ static void hns_roce_cleanup_mhop_hem_table(struct hns_roce_dev *hr_dev,
mhop.bt_chunk_size;
for (i = 0; i < table->num_hem; ++i) {
- obj = i * buf_chunk_size / table->obj_size;
+ obj = (u64)i * buf_chunk_size / table->obj_size;
if (table->hem[i])
hns_roce_table_mhop_put(hr_dev, table, obj, 0);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 049/602] RDMA/siw: publish QP after initialization
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (47 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 048/602] RDMA/hns: Fix potential integer overflow in mhop hem cleanup Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 050/602] mtd: fix double free and WARN_ON in add_mtd_device() error paths Greg Kroah-Hartman
` (556 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Bernard Metzler, Ruoyu Wang,
Jason Gunthorpe, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <ruoyuw560@gmail.com>
[ Upstream commit bb27fcc67c429d97f785c92c35a6c5adebb05d7f ]
siw_create_qp() currently calls siw_qp_add() before the queues, CQ
pointers, state, completion, and device list entry are ready. A QPN
lookup can therefore reach a QP that is still being constructed.
Move siw_qp_add() to the end of siw_create_qp(), after QP
initialization and before adding the QP to the siw device list.
Fixes: f29dd55b0236 ("rdma/siw: queue pair methods")
Link: https://patch.msgid.link/r/20260630060040.966461-1-ruoyuw560@gmail.com
Suggested-by: Bernard Metzler <bernard.metzler@linux.dev>
Signed-off-by: Ruoyu Wang <ruoyuw560@gmail.com>
Acked-by: Bernard Metzler <bernard.metzler@linux.dev>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/infiniband/sw/siw/siw_verbs.c | 44 +++++++++++++++------------
1 file changed, 24 insertions(+), 20 deletions(-)
diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c
index d0c0cde09f1186..8ecff632ab6f3d 100644
--- a/drivers/infiniband/sw/siw/siw_verbs.c
+++ b/drivers/infiniband/sw/siw/siw_verbs.c
@@ -317,6 +317,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
struct siw_ucontext *uctx =
rdma_udata_to_drv_context(udata, struct siw_ucontext,
base_ucontext);
+ struct siw_uresp_create_qp uresp = {};
unsigned long flags;
int num_sqe, num_rqe, rv = 0;
size_t length;
@@ -370,11 +371,6 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
spin_lock_init(&qp->rq_lock);
spin_lock_init(&qp->orq_lock);
- rv = siw_qp_add(sdev, qp);
- if (rv)
- goto err_atomic;
-
-
/* All queue indices are derived from modulo operations
* on a free running 'get' (consumer) and 'put' (producer)
* unsigned counter. Having queue sizes at power of two
@@ -392,14 +388,14 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
if (qp->sendq == NULL) {
rv = -ENOMEM;
- goto err_out_xa;
+ goto err_out;
}
if (attrs->sq_sig_type != IB_SIGNAL_REQ_WR) {
if (attrs->sq_sig_type == IB_SIGNAL_ALL_WR)
qp->attrs.flags |= SIW_SIGNAL_ALL_WR;
else {
rv = -EINVAL;
- goto err_out_xa;
+ goto err_out;
}
}
qp->pd = pd;
@@ -425,7 +421,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
if (qp->recvq == NULL) {
rv = -ENOMEM;
- goto err_out_xa;
+ goto err_out;
}
qp->attrs.rq_size = num_rqe;
}
@@ -440,11 +436,8 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
qp->attrs.state = SIW_QP_STATE_IDLE;
if (udata) {
- struct siw_uresp_create_qp uresp = {};
-
uresp.num_sqe = num_sqe;
uresp.num_rqe = num_rqe;
- uresp.qp_id = qp_id(qp);
if (qp->sendq) {
length = num_sqe * sizeof(struct siw_sqe);
@@ -453,7 +446,7 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
length, &uresp.sq_key);
if (!qp->sq_entry) {
rv = -ENOMEM;
- goto err_out_xa;
+ goto err_out;
}
}
@@ -465,9 +458,23 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
if (!qp->rq_entry) {
uresp.sq_key = SIW_INVAL_UOBJ_KEY;
rv = -ENOMEM;
- goto err_out_xa;
+ goto err_out;
}
}
+ }
+ qp->tx_cpu = siw_get_tx_cpu(sdev);
+ if (qp->tx_cpu < 0) {
+ rv = -EINVAL;
+ goto err_out;
+ }
+ init_completion(&qp->qp_free);
+
+ rv = siw_qp_add(sdev, qp);
+ if (rv)
+ goto err_out_tx;
+
+ if (udata) {
+ uresp.qp_id = qp_id(qp);
if (udata->outlen < sizeof(uresp)) {
rv = -EINVAL;
@@ -477,22 +484,19 @@ int siw_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
if (rv)
goto err_out_xa;
}
- qp->tx_cpu = siw_get_tx_cpu(sdev);
- if (qp->tx_cpu < 0) {
- rv = -EINVAL;
- goto err_out_xa;
- }
+
INIT_LIST_HEAD(&qp->devq);
spin_lock_irqsave(&sdev->lock, flags);
list_add_tail(&qp->devq, &sdev->qp_list);
spin_unlock_irqrestore(&sdev->lock, flags);
- init_completion(&qp->qp_free);
-
return 0;
err_out_xa:
xa_erase(&sdev->qp_xa, qp_id(qp));
+err_out_tx:
+ siw_put_tx_cpu(qp->tx_cpu);
+err_out:
if (uctx) {
rdma_user_mmap_entry_remove(qp->sq_entry);
rdma_user_mmap_entry_remove(qp->rq_entry);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 050/602] mtd: fix double free and WARN_ON in add_mtd_device() error paths
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (48 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 049/602] RDMA/siw: publish QP after initialization Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 051/602] selftests/alsa: Fix memory leak in find_controls error path Greg Kroah-Hartman
` (555 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, syzbot+e9c76b56dc05023b8117, Xue Lei,
Miquel Raynal, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xue Lei <Xue.Lei@windriver.com>
[ Upstream commit 9d4af746af8ce27eefc2338b2feaa1e01f28b6c3 ]
When device_register() or mtd_nvmem_add() fails inside
add_mtd_device() for a partition, the error handling triggers
mtd_release() via put_device() or device_unregister(). mtd_release()
calls release_mtd_partition() which frees the mtd_info structure.
However, callers such as mtd_add_partition() and add_mtd_partitions()
also call free_partition() in their error paths, resulting in a double
free.
Additionally, release_mtd_partition() hits WARN_ON(!list_empty(
&mtd->part.node)) because the partition node is still linked in the
parent's partitions list when the release callback fires from the
add_mtd_device() error path.
Fix this by overriding dev->type and dev->release before put_device()
in the error paths, so that device_release() invokes a no-op function
instead of mtd_release(). For the mtd_nvmem_add() failure case,
device_unregister() is replaced with device_del() to separate the
device removal from the final kobject reference drop, allowing the
override to take effect before put_device() is called.
The callers' error paths (list_del + free_partition) remain the sole
owners of mtd_info lifetime on add_mtd_device() failure, which is the
expected contract.
The normal partition teardown path is not affected: del_mtd_device()
goes through kref_put() -> mtd_device_release() -> device_unregister()
with dev->type still set to &mtd_devtype, so mtd_release() ->
release_mtd_partition() continues to work correctly for the regular
removal case.
Reported-by: syzbot+e9c76b56dc05023b8117@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=e9c76b56dc05023b8117
Fixes: 19bfa9ebebb5 ("mtd: use refcount to prevent corruption")
Signed-off-by: Xue Lei <Xue.Lei@windriver.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/mtd/mtdcore.c | 23 +++++++++++++++++++----
1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 724f917f91bac0..0c8e8eb5f0f3d8 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -104,6 +104,15 @@ static void mtd_release(struct device *dev)
device_destroy(&mtd_class, index + 1);
}
+/*
+ * No-op device release used in add_mtd_device() error paths.
+ * Prevents mtd_release() from being called via device_release(),
+ * which would free the mtd_info that the caller still manages.
+ */
+static void mtd_dev_release_nop(struct device *dev)
+{
+}
+
static void mtd_device_release(struct kref *kref)
{
struct mtd_info *mtd = container_of(kref, struct mtd_info, refcnt);
@@ -746,10 +755,8 @@ int add_mtd_device(struct mtd_info *mtd)
mtd_check_of_node(mtd);
of_node_get(mtd_get_of_node(mtd));
error = device_register(&mtd->dev);
- if (error) {
- put_device(&mtd->dev);
+ if (error)
goto fail_added;
- }
/* Add the nvmem provider */
error = mtd_nvmem_add(mtd);
@@ -787,8 +794,16 @@ int add_mtd_device(struct mtd_info *mtd)
return 0;
fail_nvmem_add:
- device_unregister(&mtd->dev);
+ device_del(&mtd->dev);
fail_added:
+ /*
+ * Clear type and set nop release to prevent mtd_release() ->
+ * release_mtd_partition() -> free_partition() from freeing mtd.
+ * The caller handles cleanup on failure.
+ */
+ mtd->dev.type = NULL;
+ mtd->dev.release = mtd_dev_release_nop;
+ put_device(&mtd->dev);
of_node_put(mtd_get_of_node(mtd));
idr_remove(&mtd_idr, i);
fail_locked:
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 051/602] selftests/alsa: Fix memory leak in find_controls error path
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (49 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 050/602] mtd: fix double free and WARN_ON in add_mtd_device() error paths Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 052/602] RDMA/irdma: Prevent overflows in memory contiguity checks Greg Kroah-Hartman
` (554 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Malaya Kumar Rout, Takashi Iwai,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Malaya Kumar Rout <malayarout91@gmail.com>
[ Upstream commit cb89f0c1aed02eb233c4271f76f830b37e222ff6 ]
In find_controls(), card_data is allocated with malloc() but when
snd_ctl_open_lconf() fails, the code jumps to next_card without
freeing the allocated memory. This results in a memory leak for
each card where snd_ctl_open_lconf() fails.
Add free(card_data) before goto next_card to ensure proper cleanup
of the allocated memory in the error path.
Fixes: 5aaf9efffc57 ("kselftest: alsa: Add simplistic test for ALSA mixer controls kselftest")
Signed-off-by: Malaya Kumar Rout <malayarout91@gmail.com>
Link: https://patch.msgid.link/20260704105736.94874-1-malayarout91@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
tools/testing/selftests/alsa/mixer-test.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/tools/testing/selftests/alsa/mixer-test.c b/tools/testing/selftests/alsa/mixer-test.c
index 2a4b2662035efc..2964f02ffd9d3c 100644
--- a/tools/testing/selftests/alsa/mixer-test.c
+++ b/tools/testing/selftests/alsa/mixer-test.c
@@ -84,6 +84,7 @@ static void find_controls(void)
if (err < 0) {
ksft_print_msg("Failed to get hctl for card %d: %s\n",
card, snd_strerror(err));
+ free(card_data);
goto next_card;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 052/602] RDMA/irdma: Prevent overflows in memory contiguity checks
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (50 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 051/602] selftests/alsa: Fix memory leak in find_controls error path Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 053/602] xfrm6: clear dst.dev on error to avoid double netdev_put in xfrm6_fill_dst() Greg Kroah-Hartman
` (553 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Aleksandrova Alyona, Leon Romanovsky,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aleksandrova Alyona <aga@itb.spb.ru>
[ Upstream commit 3cda0dfe8c651dcbb9e38977905d3d3b1750c4ab ]
irdma_check_mem_contiguous() and irdma_check_mr_contiguous() verify that
PBL entries describe physically contiguous memory ranges.
Both functions calculate byte offsets using 32-bit operands. For example,
with 4 KiB pages, pg_size * pg_idx overflows 32-bit arithmetic when
pg_idx reaches 1048576. In the level-2 check, PBLE_PER_PAGE is 512, so
i * pg_size * PBLE_PER_PAGE overflows when i reaches 2048.
These values are reachable in the driver. For MRs, palloc->total_cnt
comes from iwmr->page_cnt, which is calculated by
ib_umem_num_dma_blocks(). The MR size is limited by IRDMA_MAX_MR_SIZE,
so a 4 GiB MR with 4 KiB pages can reach page_cnt of 1048576. PBLE
resources do not exclude this value either: for gen3, the limit is based
on avail_sds * MAX_PBLE_PER_SD, and MAX_PBLE_PER_SD is 0x40000, so 4 SDs
are enough for 1048576 PBLEs.
Cast one operand to u64 before the multiplications so that the offset
calculations are performed in 64-bit arithmetic.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs")
Signed-off-by: Aleksandrova Alyona <aga@itb.spb.ru>
Link: https://patch.msgid.link/20260624144846.61242-1-aga@itb.spb.ru
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/infiniband/hw/irdma/verbs.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index 255c6d21756ba4..d8e101fc74ff73 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -2367,7 +2367,7 @@ static bool irdma_check_mem_contiguous(u64 *arr, u32 npages, u32 pg_size)
u32 pg_idx;
for (pg_idx = 0; pg_idx < npages; pg_idx++) {
- if ((*arr + (pg_size * pg_idx)) != arr[pg_idx])
+ if ((*arr + ((u64)pg_size * pg_idx)) != arr[pg_idx])
return false;
}
@@ -2400,7 +2400,7 @@ static bool irdma_check_mr_contiguous(struct irdma_pble_alloc *palloc,
for (i = 0; i < lvl2->leaf_cnt; i++, leaf++) {
arr = leaf->addr;
- if ((*start_addr + (i * pg_size * PBLE_PER_PAGE)) != *arr)
+ if ((*start_addr + ((u64)i * pg_size * PBLE_PER_PAGE)) != *arr)
return false;
ret = irdma_check_mem_contiguous(arr, leaf->cnt, pg_size);
if (!ret)
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 053/602] xfrm6: clear dst.dev on error to avoid double netdev_put in xfrm6_fill_dst()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (51 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 052/602] RDMA/irdma: Prevent overflows in memory contiguity checks Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 054/602] xfrm: policy: preallocate inexact bins before xfrm_hash_rebuild reinsert Greg Kroah-Hartman
` (552 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, AutonomousCodeSecurity,
Xiang Mei (Microsoft), Steffen Klassert, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei (Microsoft) <xmei5@asu.edu>
[ Upstream commit 136992de9bb91871084ae52d172610541c76e4d2 ]
On the error path where in6_dev_get(dev) returns NULL, xfrm6_fill_dst()
releases the device reference with netdev_put() but leaves
xdst->u.dst.dev set. dst_destroy() later calls netdev_put(dst->dev)
again, so the same net_device reference is released twice, underflowing
its refcount (ref_tracker WARNING + "unregister_netdevice: waiting for
<dev> to become free").
Clear xdst->u.dst.dev after the netdev_put(), the same way the XFRM
device-offload paths xfrm_dev_state_add() and xfrm_dev_policy_add() in
net/xfrm/xfrm_device.c NULL ->dev when releasing the reference on error.
ref_tracker: reference already released.
ref_tracker: allocated in:
xfrm6_fill_dst (net/ipv6/xfrm6_policy.c:86)
...
udpv6_sendmsg (net/ipv6/udp.c:1696)
...
ref_tracker: freed in:
xfrm6_fill_dst (net/ipv6/xfrm6_policy.c:90)
...
WARNING: lib/ref_tracker.c:322 at ref_tracker_free+0x58b/0x780
dst_destroy (net/core/dst.c:115)
rcu_core
handle_softirqs
...
Fixes: 84c4a9dfbf43 ("xfrm6: release dev before returning error")
Reported-by: AutonomousCodeSecurity@microsoft.com
Signed-off-by: Xiang Mei (Microsoft) <xmei5@asu.edu>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/ipv6/xfrm6_policy.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 125ea9a5b8a082..3b749475f6ed65 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -88,6 +88,7 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
xdst->u.rt6.rt6i_idev = in6_dev_get(dev);
if (!xdst->u.rt6.rt6i_idev) {
netdev_put(dev, &xdst->u.dst.dev_tracker);
+ xdst->u.dst.dev = NULL;
return -ENODEV;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 054/602] xfrm: policy: preallocate inexact bins before xfrm_hash_rebuild reinsert
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (52 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 053/602] xfrm6: clear dst.dev on error to avoid double netdev_put in xfrm6_fill_dst() Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 055/602] wifi: cfg80211: cancel sched scan results work on unregister Greg Kroah-Hartman
` (551 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, AutonomousCodeSecurity,
Xiang Mei (Microsoft), Florian Westphal, Steffen Klassert,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei (Microsoft) <xmei5@asu.edu>
[ Upstream commit f38f8cce2f7e79775b3db7e8a5eacda04ac908e4 ]
xfrm_hash_rebuild()'s first loop preallocates the bins/chains the reinsert
loop needs, so the reinsert (after hlist_del_rcu()) cannot allocate or
fail. But its guard is inverted: it skips policies with prefixlen <
threshold and preallocates for the rest.
prefixlen < threshold is exactly when policy_hash_bysel() returns NULL and
the reinsert takes the allocating xfrm_policy_inexact_insert() path. So the
loop preallocates for the exact policies (which never allocate) and skips
the inexact ones, whose bin/node is then allocated GFP_ATOMIC during
reinsert. On failure the error path only WARN_ONCE()s and continues,
leaving a poisoned bydst node; the next rebuild's hlist_del_rcu()
dereferences LIST_POISON2 and takes a GPF. Reachable under memory pressure,
deterministic via failslab.
Invert the guard so preallocation covers exactly the reinserted policies;
the reinsert then allocates nothing and cannot fail.
Crash:
Oops: general protection fault, probably for non-canonical address
0xfbd59c0000000024: 0000 [#1] SMP KASAN NOPTI
KASAN: maybe wild-memory-access in range [0xdead...]
...
Workqueue: events xfrm_hash_rebuild
RIP: 0010:xfrm_hash_rebuild+0x5b3/0x1190
RAX: dead000000000122 (LIST_POISON2 + offset)
...
Call Trace:
hlist_del_rcu (include/linux/rculist.h:599)
xfrm_hash_rebuild (net/xfrm/xfrm_policy.c:1365)
process_one_work (kernel/workqueue.c:3322)
worker_thread (kernel/workqueue.c:3486)
kthread (kernel/kthread.c:436)
ret_from_fork (arch/x86/kernel/process.c:158)
ret_from_fork_asm (arch/x86/entry/entry_64.S:245)
...
Kernel panic - not syncing: Fatal exception in interrupt
Fixes: 24969facd704 ("xfrm: policy: store inexact policies in an rhashtable")
Reported-by: AutonomousCodeSecurity@microsoft.com
Signed-off-by: Xiang Mei (Microsoft) <xmei5@asu.edu>
Reviewed-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/xfrm/xfrm_policy.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index f74e45a34b70df..e033390e77855c 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1329,8 +1329,8 @@ static void xfrm_hash_rebuild(struct work_struct *work)
}
}
- if (policy->selector.prefixlen_d < dbits ||
- policy->selector.prefixlen_s < sbits)
+ if (policy->selector.prefixlen_d >= dbits &&
+ policy->selector.prefixlen_s >= sbits)
continue;
bin = xfrm_policy_inexact_alloc_bin(policy, dir);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 055/602] wifi: cfg80211: cancel sched scan results work on unregister
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (53 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 054/602] xfrm: policy: preallocate inexact bins before xfrm_hash_rebuild reinsert Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 056/602] wifi: ipw2100: fix potential memory leak in ipw2100_pci_init_one() Greg Kroah-Hartman
` (550 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Cen Zhang, Johannes Berg,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cen Zhang <zzzccc427@gmail.com>
[ Upstream commit edf0730be33696a1bd142792830d392129e495cc ]
cfg80211_sched_scan_results() can queue rdev->sched_scan_res_wk from a
driver result notification while a scheduled scan request is present. The
work callback recovers the containing cfg80211_registered_device and then
locks the wiphy and walks the scheduled-scan request list.
wiphy_unregister() already makes the wiphy unreachable and drains rdev work
items before cfg80211_dev_free() can release the object, but it does not
drain sched_scan_res_wk. A queued or running result work item can therefore
cross the unregister/free boundary and access freed rdev state.
The buggy scenario involves two paths, with each column showing the order
within that path:
scheduled-scan result path: unregister/free path:
1. cfg80211_sched_scan_results() 1. interface teardown stops and
queues rdev->sched_scan_res_wk. removes the scheduled scan request.
2. cfg80211_wq starts the work 2. wiphy_unregister() drains other
item and recovers rdev. rdev work items.
3. The worker locks rdev->wiphy 3. cfg80211_dev_free() destroys and
and walks rdev state. frees rdev.
Cancel sched_scan_res_wk in wiphy_unregister() alongside the other rdev
work items. cancel_work_sync() removes a pending result notification and
waits for an already running callback, so cfg80211_dev_free() cannot free
rdev while this work item is still active.
Validation reproduced this kernel report:
BUG: KASAN: use-after-free in cfg80211_sched_scan_results_wk+0x4a6/0x530
Workqueue: cfg80211 cfg80211_sched_scan_results_wk [cfg80211]
Read of size 8
Call trace:
dump_stack_lvl+0x66/0xa0
print_report+0xce/0x630
cfg80211_sched_scan_results_wk+0x4a6/0x530
srso_alias_return_thunk+0x5/0xfbef5
__virt_addr_valid+0x224/0x430
kasan_report+0xac/0xe0
lockdep_hardirqs_on_prepare+0xea/0x1a0
process_one_work+0x8d0/0x18f0 (kernel/workqueue.c:3212)
lock_is_held_type+0x8f/0x100
worker_thread+0x5ad/0xfd0
__kthread_parkme+0xc6/0x200
kthread+0x31e/0x410
trace_hardirqs_on+0x1a/0x170
ret_from_fork+0x576/0x810
__switch_to+0x57e/0xe20
__switch_to_asm+0x33/0x70
ret_from_fork_asm+0x1a/0x30
Fixes: 807f8a8c3004 ("cfg80211/nl80211: add support for scheduled scans")
Assisted-by: Codex:gpt-5.5
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Link: https://patch.msgid.link/20260619162542.3878296-1-zzzccc427@gmail.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/wireless/core.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 46e70f2e39ccf9..556b0d859d2dea 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -1174,6 +1174,7 @@ void wiphy_unregister(struct wiphy *wiphy)
/* this has nothing to do now but make sure it's gone */
cancel_work_sync(&rdev->wiphy_work);
+ cancel_work_sync(&rdev->sched_scan_res_wk);
cancel_work_sync(&rdev->rfkill_block);
cancel_work_sync(&rdev->conn_work);
flush_work(&rdev->event_work);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 056/602] wifi: ipw2100: fix potential memory leak in ipw2100_pci_init_one()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (54 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 055/602] wifi: cfg80211: cancel sched scan results work on unregister Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 057/602] wifi: mac80211_hwsim: clamp virtio RX length before skb_put Greg Kroah-Hartman
` (549 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Abdun Nihaal, Johannes Berg,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdun Nihaal <nihaal@cse.iitm.ac.in>
[ Upstream commit 0d388f62031dbabcba0f44bb91b59f10e88cac17 ]
The memory allocated in the ipw2100_alloc_device() function is not freed
in some of the error paths in ipw2100_pci_init_one(). Fix that by
converting the direct return into a goto to the error path return.
The error path when pci_enable_device() fails cannot jump to fail, since
at this point priv is not set, so perform error handling inline.
Fixes: 2c86c275015c ("Add ipw2100 wireless driver.")
Signed-off-by: Abdun Nihaal <nihaal@cse.iitm.ac.in>
Link: https://patch.msgid.link/20260620065242.93798-1-nihaal@cse.iitm.ac.in
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/intel/ipw2x00/ipw2100.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
index fe75941c584d15..95778dfdfa6d81 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
@@ -6167,6 +6167,8 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
if (err) {
printk(KERN_WARNING DRV_NAME
"Error calling pci_enable_device.\n");
+ free_libipw(dev, 0);
+ pci_iounmap(pci_dev, ioaddr);
return err;
}
@@ -6179,16 +6181,14 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
if (err) {
printk(KERN_WARNING DRV_NAME
"Error calling pci_set_dma_mask.\n");
- pci_disable_device(pci_dev);
- return err;
+ goto fail;
}
err = pci_request_regions(pci_dev, DRV_NAME);
if (err) {
printk(KERN_WARNING DRV_NAME
"Error calling pci_request_regions.\n");
- pci_disable_device(pci_dev);
- return err;
+ goto fail;
}
/* We disable the RETRY_TIMEOUT register (0x41) to keep
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 057/602] wifi: mac80211_hwsim: clamp virtio RX length before skb_put
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (55 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 056/602] wifi: ipw2100: fix potential memory leak in ipw2100_pci_init_one() Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 058/602] wifi: mac80211: fix unsol_bcast_probe_resp double free on alloc failure Greg Kroah-Hartman
` (548 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Bryam Vargas, Johannes Berg,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <hexlabsecurity@proton.me>
[ Upstream commit 10a2b430f8f06ae14b9590b6f6faa6b588ef0654 ]
hwsim_virtio_rx_work() passes the virtqueue used-ring length reported by
the device straight to skb_put() on a fixed-size receive skb. A backend
reporting a length larger than the skb tailroom drives skb_put() past the
buffer end and hits skb_over_panic() -- a host-triggerable guest panic
(denial of service).
Clamp the length to the skb's available room before skb_put(). A
conforming device never reports more than the posted buffer size, so valid
frames are unaffected; a truncated over-report then fails the
length/header checks in hwsim_virtio_handle_cmd() and is dropped, so
truncating rather than dropping here cannot be turned into a parsing
problem.
Fixes: 5d44fe7c9808 ("mac80211_hwsim: add frame transmission support over virtio")
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
Link: https://patch.msgid.link/20260620-b4-disp-474bee37-v1-1-1a4d37f3e2d4@proton.me
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/virtual/mac80211_hwsim.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
index e992e59b591892..63fae67c816225 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
@@ -6605,6 +6605,7 @@ static void hwsim_virtio_rx_work(struct work_struct *work)
skb->data = skb->head;
skb_reset_tail_pointer(skb);
+ len = min(len, skb_end_offset(skb));
skb_put(skb, len);
hwsim_virtio_handle_cmd(skb);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 058/602] wifi: mac80211: fix unsol_bcast_probe_resp double free on alloc failure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (56 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 057/602] wifi: mac80211_hwsim: clamp virtio RX length before skb_put Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 059/602] wifi: mac80211: fix fils_discovery " Greg Kroah-Hartman
` (547 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Weiming Shi, Xiang Mei,
Johannes Berg, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei <xmei5@asu.edu>
[ Upstream commit 1d067abcd37062426c59ec73dbc4e87a63f33fea ]
ieee80211_set_unsol_bcast_probe_resp() calls kfree_rcu() on the old
template before allocating the replacement. If the kzalloc() then fails,
it returns -ENOMEM while link->u.ap.unsol_bcast_probe_resp still points
at the object already queued for freeing. A later update or AP teardown
re-queues that same rcu_head; the second free is caught by KASAN when the
RCU sheaf is processed in softirq:
BUG: KASAN: double-free in rcu_free_sheaf (mm/slub.c:5850)
Free of addr ffff88800d06f300 by task exploit/145
...
__rcu_free_sheaf_prepare (mm/slub.c:2634 mm/slub.c:2940)
rcu_free_sheaf (mm/slub.c:5850)
rcu_core (kernel/rcu/tree.c:2617 kernel/rcu/tree.c:2869)
handle_softirqs (kernel/softirq.c:622)
The buggy address belongs to the cache kmalloc-128 of size 128
Queue the old object for kfree_rcu() only after the new one is published,
matching ieee80211_set_probe_resp() and ieee80211_set_s1g_short_beacon().
Fixes: 3b1c256eb4ae ("wifi: mac80211: fixes in FILS discovery updates")
Reported-by: Weiming Shi <bestswngs@gmail.com>
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Xiang Mei <xmei5@asu.edu>
Link: https://patch.msgid.link/20260621093532.884188-1-xmei5@asu.edu
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/mac80211/cfg.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 0abb687fd58d5c..981f316df9cd9e 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1010,8 +1010,6 @@ ieee80211_set_unsol_bcast_probe_resp(struct ieee80211_sub_if_data *sdata,
link_conf->unsol_bcast_probe_resp_interval = params->interval;
old = sdata_dereference(link->u.ap.unsol_bcast_probe_resp, sdata);
- if (old)
- kfree_rcu(old, rcu_head);
if (params->tmpl && params->tmpl_len) {
new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL);
@@ -1024,6 +1022,9 @@ ieee80211_set_unsol_bcast_probe_resp(struct ieee80211_sub_if_data *sdata,
RCU_INIT_POINTER(link->u.ap.unsol_bcast_probe_resp, NULL);
}
+ if (old)
+ kfree_rcu(old, rcu_head);
+
*changed |= BSS_CHANGED_UNSOL_BCAST_PROBE_RESP;
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 059/602] wifi: mac80211: fix fils_discovery double free on alloc failure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (57 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 058/602] wifi: mac80211: fix unsol_bcast_probe_resp double free on alloc failure Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 060/602] wifi: libertas: fix memory leak in helper_firmware_cb() Greg Kroah-Hartman
` (546 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Weiming Shi, Xiang Mei,
Johannes Berg, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei <xmei5@asu.edu>
[ Upstream commit 286e52a799fa158bdbd77da1426c4d93f9a6e7ad ]
ieee80211_set_fils_discovery() calls kfree_rcu() on the old template
before allocating the replacement. If the kzalloc() then fails, it
returns -ENOMEM while link->u.ap.fils_discovery still points at the
object already queued for freeing. A later update or AP teardown
(ieee80211_stop_ap()) re-queues that same rcu_head; the second free is
caught by KASAN when the RCU sheaf is processed in softirq:
BUG: KASAN: double-free in rcu_free_sheaf (mm/slub.c:5850)
Free of addr ffff88800c065280 by task swapper/0/0
...
__rcu_free_sheaf_prepare (mm/slub.c:2634 mm/slub.c:2940)
rcu_free_sheaf (mm/slub.c:5850)
rcu_core (kernel/rcu/tree.c:2617 kernel/rcu/tree.c:2869)
handle_softirqs (kernel/softirq.c:622)
The buggy address belongs to the cache kmalloc-96 of size 96
Queue the old object for kfree_rcu() only after the new one is published,
matching ieee80211_set_probe_resp() and ieee80211_set_s1g_short_beacon().
Fixes: 3b1c256eb4ae ("wifi: mac80211: fixes in FILS discovery updates")
Reported-by: Weiming Shi <bestswngs@gmail.com>
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Xiang Mei <xmei5@asu.edu>
Link: https://patch.msgid.link/20260621093532.884188-2-xmei5@asu.edu
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/mac80211/cfg.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 981f316df9cd9e..b9ed82b8321a6a 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -977,9 +977,6 @@ static int ieee80211_set_fils_discovery(struct ieee80211_sub_if_data *sdata,
fd->max_interval = params->max_interval;
old = sdata_dereference(link->u.ap.fils_discovery, sdata);
- if (old)
- kfree_rcu(old, rcu_head);
-
if (params->tmpl && params->tmpl_len) {
new = kzalloc(sizeof(*new) + params->tmpl_len, GFP_KERNEL);
if (!new)
@@ -991,6 +988,9 @@ static int ieee80211_set_fils_discovery(struct ieee80211_sub_if_data *sdata,
RCU_INIT_POINTER(link->u.ap.fils_discovery, NULL);
}
+ if (old)
+ kfree_rcu(old, rcu_head);
+
*changed |= BSS_CHANGED_FILS_DISCOVERY;
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 060/602] wifi: libertas: fix memory leak in helper_firmware_cb()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (58 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 059/602] wifi: mac80211: fix fils_discovery " Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 061/602] wifi: p54: validate RX frame length in p54_rx_eeprom_readback() Greg Kroah-Hartman
` (545 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Dawei Feng, Johannes Berg,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dawei Feng <dawei.feng@seu.edu.cn>
[ Upstream commit 63c2391deefb31e1b801b7f32bd502ca4808639b ]
helper_firmware_cb() neglects to free the single-stage firmware image
after a successful async load, leading to a memory leak in the USB
firmware-download path.
Fix this memory leak by calling release_firmware() immediately after
lbs_fw_loaded() returns.
The bug was first flagged by an experimental analysis tool we are
developing for kernel memory-management bugs while analyzing
v6.13-rc1. The tool is still under development and is not yet publicly
available. Manual inspection confirms that the bug is still present in
the current wireless tree.
An x86_64 allyesconfig build showed no new warnings. As we do not have
compatible Libertas USB hardware for exercising this firmware-download
path, no runtime testing was able to be performed.
Fixes: 1dfba3060fe7 ("libertas: move firmware lifetime handling to firmware.c")
Signed-off-by: Dawei Feng <dawei.feng@seu.edu.cn>
Link: https://patch.msgid.link/20260624085343.575508-1-dawei.feng@seu.edu.cn
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/marvell/libertas/firmware.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/marvell/libertas/firmware.c b/drivers/net/wireless/marvell/libertas/firmware.c
index f124110944b7e9..9bf7d4c207b9ed 100644
--- a/drivers/net/wireless/marvell/libertas/firmware.c
+++ b/drivers/net/wireless/marvell/libertas/firmware.c
@@ -78,6 +78,7 @@ static void helper_firmware_cb(const struct firmware *firmware, void *context)
} else {
/* No main firmware needed for this helper --> success! */
lbs_fw_loaded(priv, 0, firmware, NULL);
+ release_firmware(firmware);
}
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 061/602] wifi: p54: validate RX frame length in p54_rx_eeprom_readback()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (59 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 060/602] wifi: libertas: fix memory leak in helper_firmware_cb() Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 062/602] wifi: cfg80211: pass net_device to .set_monitor_channel Greg Kroah-Hartman
` (544 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Weiming Shi, Xiang Mei,
Christian Lamparter, Johannes Berg, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei <xmei5@asu.edu>
[ Upstream commit ebd6d37fa94bee929e0b4c9ca19fdf9b1dcf6cea ]
p54_rx_eeprom_readback() copies the requested EEPROM slice out of a
device-supplied readback frame without checking that the skb actually holds
that many bytes. Commit da1b9a55ff11 ("wifi: p54: prevent buffer-overflow in
p54_rx_eeprom_readback()") closed the destination overflow by copying a
fixed priv->eeprom_slice_size (and rejecting a mismatched advertised len),
but the source side is still unbounded: nothing verifies the frame is long
enough to supply that many bytes.
A malicious USB device can send a short frame whose advertised len matches
priv->eeprom_slice_size while the payload is truncated. The equality check
passes and memcpy() reads past the end of the skb, leaking adjacent heap:
BUG: KASAN: slab-out-of-bounds in p54_rx (drivers/net/wireless/intersil/p54/txrx.c:507)
Read of size 1016 at addr ffff88800f077114 by task swapper/0/0
Call Trace:
<IRQ>
...
__asan_memcpy (mm/kasan/shadow.c:105)
p54_rx (drivers/net/wireless/intersil/p54/txrx.c:507)
p54u_rx_cb (drivers/net/wireless/intersil/p54/p54usb.c:163)
__usb_hcd_giveback_urb (drivers/usb/core/hcd.c:1657)
dummy_timer (drivers/usb/gadget/udc/dummy_hcd.c:2005)
...
</IRQ>
The buggy address belongs to the object at ffff88800f0770c0
which belongs to the cache skbuff_small_head of size 704
The buggy address is located 84 bytes inside of
allocated 704-byte region [ffff88800f0770c0, ffff88800f077380)
Check that the slice fits in the skb before copying.
Fixes: 7cb770729ba8 ("p54: move eeprom code into common library")
Reported-by: Weiming Shi <bestswngs@gmail.com>
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Xiang Mei <xmei5@asu.edu>
Acked-by: Christian Lamparter <chunkeey@gmail.com>
Link: https://patch.msgid.link/20260628000510.4152481-1-xmei5@asu.edu
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/intersil/p54/txrx.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/net/wireless/intersil/p54/txrx.c b/drivers/net/wireless/intersil/p54/txrx.c
index 2deb1bb54f24bd..dc7bf54e30bba1 100644
--- a/drivers/net/wireless/intersil/p54/txrx.c
+++ b/drivers/net/wireless/intersil/p54/txrx.c
@@ -499,11 +499,19 @@ static void p54_rx_eeprom_readback(struct p54_common *priv,
if (le16_to_cpu(eeprom->v2.len) != priv->eeprom_slice_size)
return;
+ if (eeprom->v2.data + priv->eeprom_slice_size >
+ skb_tail_pointer(skb))
+ return;
+
memcpy(priv->eeprom, eeprom->v2.data, priv->eeprom_slice_size);
} else {
if (le16_to_cpu(eeprom->v1.len) != priv->eeprom_slice_size)
return;
+ if (eeprom->v1.data + priv->eeprom_slice_size >
+ skb_tail_pointer(skb))
+ return;
+
memcpy(priv->eeprom, eeprom->v1.data, priv->eeprom_slice_size);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 062/602] wifi: cfg80211: pass net_device to .set_monitor_channel
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (60 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 061/602] wifi: p54: validate RX frame length in p54_rx_eeprom_readback() Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 063/602] wifi: cfg80211: define and use wiphy guard Greg Kroah-Hartman
` (543 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Felix Fietkau, Johannes Berg,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Fietkau <nbd@nbd.name>
[ Upstream commit 9c4f830927750a2bf9fd9426a5257f0fdce3b662 ]
Preparation for allowing multiple monitor interfaces with different channels
on a multi-radio wiphy.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Link: https://patch.msgid.link/35fa652dbfebf93343f8b9a08fdef0467a2a02dc.1728462320.git-series.nbd@nbd.name
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Stable-dep-of: 2b0eab425e1f ("wifi: cfg80211: convert pmsr_free_wk to wiphy_work to fix deadlock")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/ath/wil6210/cfg80211.c | 1 +
drivers/net/wireless/marvell/libertas/cfg.c | 1 +
drivers/net/wireless/microchip/wilc1000/cfg80211.c | 3 ++-
include/net/cfg80211.h | 1 +
net/mac80211/cfg.c | 1 +
net/wireless/chan.c | 3 ++-
net/wireless/core.h | 1 +
net/wireless/nl80211.c | 2 +-
net/wireless/rdev-ops.h | 5 +++--
net/wireless/trace.h | 10 ++++++----
net/wireless/wext-compat.c | 2 +-
11 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index e8f1d30a8d73c5..a1a0a9223e74ac 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -1493,6 +1493,7 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
}
static int wil_cfg80211_set_channel(struct wiphy *wiphy,
+ struct net_device *dev,
struct cfg80211_chan_def *chandef)
{
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
diff --git a/drivers/net/wireless/marvell/libertas/cfg.c b/drivers/net/wireless/marvell/libertas/cfg.c
index 37bb788f83e36e..309556541a83ed 100644
--- a/drivers/net/wireless/marvell/libertas/cfg.c
+++ b/drivers/net/wireless/marvell/libertas/cfg.c
@@ -486,6 +486,7 @@ static int lbs_add_wps_enrollee_tlv(u8 *tlv, const u8 *ie, size_t ie_len)
*/
static int lbs_cfg_set_monitor_channel(struct wiphy *wiphy,
+ struct net_device *dev,
struct cfg80211_chan_def *chandef)
{
struct lbs_private *priv = wiphy_priv(wiphy);
diff --git a/drivers/net/wireless/microchip/wilc1000/cfg80211.c b/drivers/net/wireless/microchip/wilc1000/cfg80211.c
index eb37b228d54ea0..9977be0020fe76 100644
--- a/drivers/net/wireless/microchip/wilc1000/cfg80211.c
+++ b/drivers/net/wireless/microchip/wilc1000/cfg80211.c
@@ -231,6 +231,7 @@ struct wilc_vif *wilc_get_wl_to_vif(struct wilc *wl)
}
static int set_channel(struct wiphy *wiphy,
+ struct net_device *dev,
struct cfg80211_chan_def *chandef)
{
struct wilc *wl = wiphy_priv(wiphy);
@@ -1424,7 +1425,7 @@ static int start_ap(struct wiphy *wiphy, struct net_device *dev,
struct wilc_vif *vif = netdev_priv(dev);
int ret;
- ret = set_channel(wiphy, &settings->chandef);
+ ret = set_channel(wiphy, dev, &settings->chandef);
if (ret != 0)
netdev_err(dev, "Error in setting channel\n");
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 96121dc14e8263..f1710d7af6656b 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4699,6 +4699,7 @@ struct cfg80211_ops {
struct ieee80211_channel *chan);
int (*set_monitor_channel)(struct wiphy *wiphy,
+ struct net_device *dev,
struct cfg80211_chan_def *chandef);
int (*scan)(struct wiphy *wiphy,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index b9ed82b8321a6a..cfd02f48935450 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -893,6 +893,7 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
}
static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
+ struct net_device *dev,
struct cfg80211_chan_def *chandef)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index c4f3fefeb35444..eb8826e33d1757 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -1634,6 +1634,7 @@ bool cfg80211_reg_check_beaconing(struct wiphy *wiphy,
EXPORT_SYMBOL(cfg80211_reg_check_beaconing);
int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
struct cfg80211_chan_def *chandef)
{
if (!rdev->ops->set_monitor_channel)
@@ -1641,7 +1642,7 @@ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
if (!cfg80211_has_monitors_only(rdev))
return -EBUSY;
- return rdev_set_monitor_channel(rdev, chandef);
+ return rdev_set_monitor_channel(rdev, dev, chandef);
}
bool cfg80211_any_usable_channels(struct wiphy *wiphy,
diff --git a/net/wireless/core.h b/net/wireless/core.h
index d4b26cbe3342d0..a60883b6e43105 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -517,6 +517,7 @@ static inline unsigned int elapsed_jiffies_msecs(unsigned long start)
}
int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
struct cfg80211_chan_def *chandef);
int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 15a8237f79bffa..90ff3ee8df6122 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3568,7 +3568,7 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
case NL80211_IFTYPE_MESH_POINT:
return cfg80211_set_mesh_channel(rdev, wdev, &chandef);
case NL80211_IFTYPE_MONITOR:
- return cfg80211_set_monitor_channel(rdev, &chandef);
+ return cfg80211_set_monitor_channel(rdev, dev, &chandef);
default:
break;
}
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index f5adbf6b5c846c..adb6105bbb7d1d 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -445,11 +445,12 @@ rdev_libertas_set_mesh_channel(struct cfg80211_registered_device *rdev,
static inline int
rdev_set_monitor_channel(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
struct cfg80211_chan_def *chandef)
{
int ret;
- trace_rdev_set_monitor_channel(&rdev->wiphy, chandef);
- ret = rdev->ops->set_monitor_channel(&rdev->wiphy, chandef);
+ trace_rdev_set_monitor_channel(&rdev->wiphy, dev, chandef);
+ ret = rdev->ops->set_monitor_channel(&rdev->wiphy, dev, chandef);
trace_rdev_return_int(&rdev->wiphy, ret);
return ret;
}
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 945013185c9860..68bbf3a778ce1f 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -1339,19 +1339,21 @@ TRACE_EVENT(rdev_libertas_set_mesh_channel,
);
TRACE_EVENT(rdev_set_monitor_channel,
- TP_PROTO(struct wiphy *wiphy,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
struct cfg80211_chan_def *chandef),
- TP_ARGS(wiphy, chandef),
+ TP_ARGS(wiphy, netdev, chandef),
TP_STRUCT__entry(
WIPHY_ENTRY
+ NETDEV_ENTRY
CHAN_DEF_ENTRY
),
TP_fast_assign(
WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
CHAN_DEF_ASSIGN(chandef);
),
- TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT,
- WIPHY_PR_ARG, CHAN_DEF_PR_ARG)
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT,
+ WIPHY_PR_ARG, NETDEV_PR_ARG, CHAN_DEF_PR_ARG)
);
TRACE_EVENT(rdev_auth,
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 3af11dae0942ae..32a695c8a4d2af 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -830,7 +830,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
ret = -EINVAL;
break;
}
- ret = cfg80211_set_monitor_channel(rdev, &chandef);
+ ret = cfg80211_set_monitor_channel(rdev, dev, &chandef);
break;
case NL80211_IFTYPE_MESH_POINT:
freq = cfg80211_wext_freq(wextfreq);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 063/602] wifi: cfg80211: define and use wiphy guard
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (61 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 062/602] wifi: cfg80211: pass net_device to .set_monitor_channel Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 064/602] wifi: cfg80211: convert pmsr_free_wk to wiphy_work to fix deadlock Greg Kroah-Hartman
` (542 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jeff Johnson, Johannes Berg,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <johannes.berg@intel.com>
[ Upstream commit f42d22d3f79639c1b4e41daf28dad2505d6a5a8b ]
Define a guard for the wiphy mutex, and use it in
most code in cfg80211, though not all due to some
interaction with RTNL and/or indentation.
Suggested-by: Jeff Johnson <quic_jjohnson@quicinc.com>
Reviewed-by: Jeff Johnson <quic_jjohnson@quicinc.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Link: https://patch.msgid.link/20241122094225.88765cbaab65.I610c9b14f36902e75e1d13f0db29f8bef2298804@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Stable-dep-of: 2b0eab425e1f ("wifi: cfg80211: convert pmsr_free_wk to wiphy_work to fix deadlock")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
include/net/cfg80211.h | 4 +
net/wireless/chan.c | 4 +-
net/wireless/core.c | 42 +++--
net/wireless/mlme.c | 8 +-
net/wireless/nl80211.c | 190 +++++++++-------------
net/wireless/pmsr.c | 4 +-
net/wireless/reg.c | 55 +++----
net/wireless/scan.c | 40 +++--
net/wireless/sme.c | 12 +-
net/wireless/util.c | 7 +-
net/wireless/wext-compat.c | 317 +++++++++++++------------------------
net/wireless/wext-sme.c | 43 ++---
12 files changed, 278 insertions(+), 448 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index f1710d7af6656b..a76e0459a8e63b 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -6030,6 +6030,10 @@ static inline void wiphy_unlock(struct wiphy *wiphy)
mutex_unlock(&wiphy->mtx);
}
+DEFINE_GUARD(wiphy, struct wiphy *,
+ mutex_lock(&_T->mtx),
+ mutex_unlock(&_T->mtx))
+
struct wiphy_work;
typedef void (*wiphy_work_func_t)(struct wiphy *, struct wiphy_work *);
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index eb8826e33d1757..515d40c09e7886 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -1039,10 +1039,10 @@ bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy,
if (!reg_dfs_domain_same(wiphy, &rdev->wiphy))
continue;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
found = cfg80211_is_wiphy_oper_chan(&rdev->wiphy, chan) ||
cfg80211_offchan_chain_is_active(rdev, chan);
- wiphy_unlock(&rdev->wiphy);
if (found)
return true;
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 556b0d859d2dea..7799cec95a9d99 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -191,7 +191,8 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
return err;
}
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
if (!wdev->netdev)
continue;
@@ -212,7 +213,6 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
continue;
nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);
}
- wiphy_unlock(&rdev->wiphy);
return 0;
}
@@ -221,9 +221,9 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
{
struct cfg80211_registered_device *rdev = data;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
rdev_rfkill_poll(rdev);
- wiphy_unlock(&rdev->wiphy);
}
void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
@@ -283,7 +283,7 @@ void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy)
/* otherwise, check iftype */
- wiphy_lock(wiphy);
+ guard(wiphy)(wiphy);
switch (wdev->iftype) {
case NL80211_IFTYPE_P2P_DEVICE:
@@ -295,8 +295,6 @@ void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy)
default:
break;
}
-
- wiphy_unlock(wiphy);
}
}
EXPORT_SYMBOL_GPL(cfg80211_shutdown_all_interfaces);
@@ -331,9 +329,9 @@ static void cfg80211_event_work(struct work_struct *work)
rdev = container_of(work, struct cfg80211_registered_device,
event_work);
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
cfg80211_process_rdev_events(rdev);
- wiphy_unlock(&rdev->wiphy);
}
void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev)
@@ -347,10 +345,10 @@ void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev)
if (wdev->netdev)
dev_close(wdev->netdev);
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
cfg80211_leave(rdev, wdev);
cfg80211_remove_virtual_intf(rdev, wdev);
- wiphy_unlock(&rdev->wiphy);
}
}
}
@@ -423,9 +421,9 @@ static void cfg80211_wiphy_work(struct work_struct *work)
trace_wiphy_work_worker_start(&rdev->wiphy);
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
if (rdev->suspended)
- goto out;
+ return;
spin_lock_irq(&rdev->wiphy_work_lock);
wk = list_first_entry_or_null(&rdev->wiphy_work_list,
@@ -441,8 +439,6 @@ static void cfg80211_wiphy_work(struct work_struct *work)
} else {
spin_unlock_irq(&rdev->wiphy_work_lock);
}
-out:
- wiphy_unlock(&rdev->wiphy);
}
/* exported functions */
@@ -1532,9 +1528,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
break;
case NETDEV_REGISTER:
if (!wdev->registered) {
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
cfg80211_register_wdev(rdev, wdev);
- wiphy_unlock(&rdev->wiphy);
}
break;
case NETDEV_UNREGISTER:
@@ -1543,16 +1539,16 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
* so check wdev->registered.
*/
if (wdev->registered && !wdev->registering) {
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
_cfg80211_unregister_wdev(wdev, false);
- wiphy_unlock(&rdev->wiphy);
}
break;
case NETDEV_GOING_DOWN:
- wiphy_lock(&rdev->wiphy);
- cfg80211_leave(rdev, wdev);
- cfg80211_remove_links(wdev);
- wiphy_unlock(&rdev->wiphy);
+ scoped_guard(wiphy, &rdev->wiphy) {
+ cfg80211_leave(rdev, wdev);
+ cfg80211_remove_links(wdev);
+ }
/* since we just did cfg80211_leave() nothing to do there */
cancel_work_sync(&wdev->disconnect_wk);
cancel_work_sync(&wdev->pmsr_free_wk);
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 26319522c7abc3..fbdf6acfcb7dc7 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -627,10 +627,10 @@ void cfg80211_mgmt_registrations_update_wk(struct work_struct *wk)
rdev = container_of(wk, struct cfg80211_registered_device,
mgmt_registrations_update_wk);
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list)
cfg80211_mgmt_registrations_update(wdev);
- wiphy_unlock(&rdev->wiphy);
}
int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
@@ -1194,10 +1194,10 @@ cfg80211_background_cac_event(struct cfg80211_registered_device *rdev,
const struct cfg80211_chan_def *chandef,
enum nl80211_radar_event event)
{
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
__cfg80211_background_cac_event(rdev, rdev->background_radar_wdev,
chandef, event);
- wiphy_unlock(&rdev->wiphy);
}
void cfg80211_background_cac_done_wk(struct work_struct *work)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 90ff3ee8df6122..0af78812e38efe 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3632,7 +3632,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
} else
wdev = netdev->ieee80211_ptr;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
/*
* end workaround code, by now the rdev is available
@@ -3645,32 +3645,24 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
rtnl_unlock();
if (result)
- goto out;
+ return result;
if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) {
struct ieee80211_txq_params txq_params;
struct nlattr *tb[NL80211_TXQ_ATTR_MAX + 1];
- if (!rdev->ops->set_txq_params) {
- result = -EOPNOTSUPP;
- goto out;
- }
+ if (!rdev->ops->set_txq_params)
+ return -EOPNOTSUPP;
- if (!netdev) {
- result = -EINVAL;
- goto out;
- }
+ if (!netdev)
+ return -EINVAL;
if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
- netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
- result = -EINVAL;
- goto out;
- }
+ netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+ return -EINVAL;
- if (!netif_running(netdev)) {
- result = -ENETDOWN;
- goto out;
- }
+ if (!netif_running(netdev))
+ return -ENETDOWN;
nla_for_each_nested(nl_txq_params,
info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
@@ -3681,10 +3673,11 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
txq_params_policy,
info->extack);
if (result)
- goto out;
+ return result;
+
result = parse_txq_params(tb, &txq_params);
if (result)
- goto out;
+ return result;
txq_params.link_id =
nl80211_link_id_or_invalid(info->attrs);
@@ -3700,7 +3693,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
result = rdev_set_txq_params(rdev, netdev,
&txq_params);
if (result)
- goto out;
+ return result;
}
}
@@ -3717,7 +3710,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
}
if (result)
- goto out;
+ return result;
}
if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) {
@@ -3728,19 +3721,15 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
if (!(rdev->wiphy.features & NL80211_FEATURE_VIF_TXPOWER))
txp_wdev = NULL;
- if (!rdev->ops->set_tx_power) {
- result = -EOPNOTSUPP;
- goto out;
- }
+ if (!rdev->ops->set_tx_power)
+ return -EOPNOTSUPP;
idx = NL80211_ATTR_WIPHY_TX_POWER_SETTING;
type = nla_get_u32(info->attrs[idx]);
if (!info->attrs[NL80211_ATTR_WIPHY_TX_POWER_LEVEL] &&
- (type != NL80211_TX_POWER_AUTOMATIC)) {
- result = -EINVAL;
- goto out;
- }
+ (type != NL80211_TX_POWER_AUTOMATIC))
+ return -EINVAL;
if (type != NL80211_TX_POWER_AUTOMATIC) {
idx = NL80211_ATTR_WIPHY_TX_POWER_LEVEL;
@@ -3749,7 +3738,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
result = rdev_set_tx_power(rdev, txp_wdev, type, mbm);
if (result)
- goto out;
+ return result;
}
if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
@@ -3758,10 +3747,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
if ((!rdev->wiphy.available_antennas_tx &&
!rdev->wiphy.available_antennas_rx) ||
- !rdev->ops->set_antenna) {
- result = -EOPNOTSUPP;
- goto out;
- }
+ !rdev->ops->set_antenna)
+ return -EOPNOTSUPP;
tx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]);
rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]);
@@ -3769,17 +3756,15 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
/* reject antenna configurations which don't match the
* available antenna masks, except for the "all" mask */
if ((~tx_ant && (tx_ant & ~rdev->wiphy.available_antennas_tx)) ||
- (~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas_rx))) {
- result = -EINVAL;
- goto out;
- }
+ (~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas_rx)))
+ return -EINVAL;
tx_ant = tx_ant & rdev->wiphy.available_antennas_tx;
rx_ant = rx_ant & rdev->wiphy.available_antennas_rx;
result = rdev_set_antenna(rdev, tx_ant, rx_ant);
if (result)
- goto out;
+ return result;
}
changed = 0;
@@ -3801,10 +3786,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) {
frag_threshold = nla_get_u32(
info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]);
- if (frag_threshold < 256) {
- result = -EINVAL;
- goto out;
- }
+ if (frag_threshold < 256)
+ return -EINVAL;
if (frag_threshold != (u32) -1) {
/*
@@ -3825,10 +3808,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
}
if (info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) {
- if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) {
- result = -EINVAL;
- goto out;
- }
+ if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK])
+ return -EINVAL;
coverage_class = nla_get_u8(
info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]);
@@ -3836,20 +3817,17 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
}
if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) {
- if (!(rdev->wiphy.features & NL80211_FEATURE_ACKTO_ESTIMATION)) {
- result = -EOPNOTSUPP;
- goto out;
- }
+ if (!(rdev->wiphy.features & NL80211_FEATURE_ACKTO_ESTIMATION))
+ return -EOPNOTSUPP;
changed |= WIPHY_PARAM_DYN_ACK;
}
if (info->attrs[NL80211_ATTR_TXQ_LIMIT]) {
if (!wiphy_ext_feature_isset(&rdev->wiphy,
- NL80211_EXT_FEATURE_TXQS)) {
- result = -EOPNOTSUPP;
- goto out;
- }
+ NL80211_EXT_FEATURE_TXQS))
+ return -EOPNOTSUPP;
+
txq_limit = nla_get_u32(
info->attrs[NL80211_ATTR_TXQ_LIMIT]);
changed |= WIPHY_PARAM_TXQ_LIMIT;
@@ -3857,10 +3835,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]) {
if (!wiphy_ext_feature_isset(&rdev->wiphy,
- NL80211_EXT_FEATURE_TXQS)) {
- result = -EOPNOTSUPP;
- goto out;
- }
+ NL80211_EXT_FEATURE_TXQS))
+ return -EOPNOTSUPP;
+
txq_memory_limit = nla_get_u32(
info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]);
changed |= WIPHY_PARAM_TXQ_MEMORY_LIMIT;
@@ -3868,10 +3845,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[NL80211_ATTR_TXQ_QUANTUM]) {
if (!wiphy_ext_feature_isset(&rdev->wiphy,
- NL80211_EXT_FEATURE_TXQS)) {
- result = -EOPNOTSUPP;
- goto out;
- }
+ NL80211_EXT_FEATURE_TXQS))
+ return -EOPNOTSUPP;
+
txq_quantum = nla_get_u32(
info->attrs[NL80211_ATTR_TXQ_QUANTUM]);
changed |= WIPHY_PARAM_TXQ_QUANTUM;
@@ -3883,10 +3859,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
u8 old_coverage_class;
u32 old_txq_limit, old_txq_memory_limit, old_txq_quantum;
- if (!rdev->ops->set_wiphy_params) {
- result = -EOPNOTSUPP;
- goto out;
- }
+ if (!rdev->ops->set_wiphy_params)
+ return -EOPNOTSUPP;
old_retry_short = rdev->wiphy.retry_short;
old_retry_long = rdev->wiphy.retry_long;
@@ -3924,15 +3898,11 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
rdev->wiphy.txq_limit = old_txq_limit;
rdev->wiphy.txq_memory_limit = old_txq_memory_limit;
rdev->wiphy.txq_quantum = old_txq_quantum;
- goto out;
+ return result;
}
}
- result = 0;
-
-out:
- wiphy_unlock(&rdev->wiphy);
- return result;
+ return 0;
}
int nl80211_send_chandef(struct sk_buff *msg, const struct cfg80211_chan_def *chandef)
@@ -4149,22 +4119,22 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
if_idx = 0;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
if (if_idx < if_start) {
if_idx++;
continue;
}
+
if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
rdev, wdev,
- NL80211_CMD_NEW_INTERFACE) < 0) {
- wiphy_unlock(&rdev->wiphy);
+ NL80211_CMD_NEW_INTERFACE) < 0)
goto out;
- }
+
if_idx++;
}
- wiphy_unlock(&rdev->wiphy);
if_start = 0;
wp_idx++;
@@ -4489,16 +4459,13 @@ static int _nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
- int ret;
/* to avoid failing a new interface creation due to pending removal */
cfg80211_destroy_ifaces(rdev);
- wiphy_lock(&rdev->wiphy);
- ret = _nl80211_new_interface(skb, info);
- wiphy_unlock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
- return ret;
+ return _nl80211_new_interface(skb, info);
}
static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
@@ -10094,7 +10061,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
struct cfg80211_chan_def chandef;
enum nl80211_dfs_regions dfs_region;
unsigned int cac_time_ms;
- int err = -EINVAL;
+ int err;
flush_delayed_work(&rdev->dfs_update_channels_wk);
@@ -10109,35 +10076,29 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
return -EINVAL;
}
- wiphy_lock(wiphy);
+ guard(wiphy)(wiphy);
dfs_region = reg_get_dfs_region(wiphy);
if (dfs_region == NL80211_DFS_UNSET)
- goto unlock;
+ return -EINVAL;
err = nl80211_parse_chandef(rdev, info, &chandef);
if (err)
- goto unlock;
+ return err;
err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype);
if (err < 0)
- goto unlock;
+ return err;
- if (err == 0) {
- err = -EINVAL;
- goto unlock;
- }
+ if (err == 0)
+ return -EINVAL;
- if (!cfg80211_chandef_dfs_usable(wiphy, &chandef)) {
- err = -EINVAL;
- goto unlock;
- }
+ if (!cfg80211_chandef_dfs_usable(wiphy, &chandef))
+ return -EINVAL;
- if (nla_get_flag(info->attrs[NL80211_ATTR_RADAR_BACKGROUND])) {
- err = cfg80211_start_background_radar_detection(rdev, wdev,
- &chandef);
- goto unlock;
- }
+ if (nla_get_flag(info->attrs[NL80211_ATTR_RADAR_BACKGROUND]))
+ return cfg80211_start_background_radar_detection(rdev, wdev,
+ &chandef);
if (cfg80211_beaconing_iface_active(wdev)) {
/* During MLO other link(s) can beacon, only the current link
@@ -10147,26 +10108,19 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
!wdev->links[link_id].ap.beacon_interval) {
/* nothing */
} else {
- err = -EBUSY;
- goto unlock;
+ return -EBUSY;
}
}
- if (wdev->links[link_id].cac_started) {
- err = -EBUSY;
- goto unlock;
- }
+ if (wdev->links[link_id].cac_started)
+ return -EBUSY;
/* CAC start is offloaded to HW and can't be started manually */
- if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD)) {
- err = -EOPNOTSUPP;
- goto unlock;
- }
+ if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD))
+ return -EOPNOTSUPP;
- if (!rdev->ops->start_radar_detection) {
- err = -EOPNOTSUPP;
- goto unlock;
- }
+ if (!rdev->ops->start_radar_detection)
+ return -EOPNOTSUPP;
cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef);
if (WARN_ON(!cac_time_ms))
@@ -10193,10 +10147,8 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
wdev->links[link_id].cac_start_time = jiffies;
wdev->links[link_id].cac_time_ms = cac_time_ms;
}
-unlock:
- wiphy_unlock(wiphy);
- return err;
+ return 0;
}
static int nl80211_notify_radar_detection(struct sk_buff *skb,
diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c
index d2b61b6ba58db7..13801cf35e9fca 100644
--- a/net/wireless/pmsr.c
+++ b/net/wireless/pmsr.c
@@ -630,9 +630,9 @@ void cfg80211_pmsr_free_wk(struct work_struct *work)
struct wireless_dev *wdev = container_of(work, struct wireless_dev,
pmsr_free_wk);
- wiphy_lock(wdev->wiphy);
+ guard(wiphy)(wdev->wiphy);
+
cfg80211_pmsr_process_abort(wdev);
- wiphy_unlock(wdev->wiphy);
}
void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev)
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 9f8428dc418a50..daf51fb56648c4 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -2468,11 +2468,11 @@ static void reg_leave_invalid_chans(struct wiphy *wiphy)
struct wireless_dev *wdev;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
- wiphy_lock(wiphy);
+ guard(wiphy)(wiphy);
+
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list)
if (!reg_wdev_chan_valid(wiphy, wdev))
cfg80211_leave(rdev, wdev);
- wiphy_unlock(wiphy);
}
static void reg_check_chans_work(struct work_struct *work)
@@ -2652,13 +2652,11 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
return;
rtnl_lock();
- wiphy_lock(wiphy);
-
- tmp = get_wiphy_regdom(wiphy);
- rcu_assign_pointer(wiphy->regd, new_regd);
- rcu_free_regdom(tmp);
-
- wiphy_unlock(wiphy);
+ scoped_guard(wiphy, wiphy) {
+ tmp = get_wiphy_regdom(wiphy);
+ rcu_assign_pointer(wiphy->regd, new_regd);
+ rcu_free_regdom(tmp);
+ }
rtnl_unlock();
}
EXPORT_SYMBOL(wiphy_apply_custom_regulatory);
@@ -2828,9 +2826,9 @@ reg_process_hint_driver(struct wiphy *wiphy,
tmp = get_wiphy_regdom(wiphy);
ASSERT_RTNL();
- wiphy_lock(wiphy);
- rcu_assign_pointer(wiphy->regd, regd);
- wiphy_unlock(wiphy);
+ scoped_guard(wiphy, wiphy) {
+ rcu_assign_pointer(wiphy->regd, regd);
+ }
rcu_free_regdom(tmp);
}
@@ -3208,9 +3206,9 @@ static void reg_process_self_managed_hints(void)
ASSERT_RTNL();
for_each_rdev(rdev) {
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
reg_process_self_managed_hint(&rdev->wiphy);
- wiphy_unlock(&rdev->wiphy);
}
reg_check_channels();
@@ -3603,14 +3601,12 @@ static bool is_wiphy_all_set_reg_flag(enum ieee80211_regulatory_flags flag)
struct wireless_dev *wdev;
for_each_rdev(rdev) {
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
- if (!(wdev->wiphy->regulatory_flags & flag)) {
- wiphy_unlock(&rdev->wiphy);
+ if (!(wdev->wiphy->regulatory_flags & flag))
return false;
- }
}
- wiphy_unlock(&rdev->wiphy);
}
return true;
@@ -3886,19 +3882,18 @@ static int reg_set_rd_driver(const struct ieee80211_regdomain *rd,
if (!driver_request->intersect) {
ASSERT_RTNL();
- wiphy_lock(request_wiphy);
- if (request_wiphy->regd)
- tmp = get_wiphy_regdom(request_wiphy);
-
- regd = reg_copy_regd(rd);
- if (IS_ERR(regd)) {
- wiphy_unlock(request_wiphy);
- return PTR_ERR(regd);
+ scoped_guard(wiphy, request_wiphy) {
+ if (request_wiphy->regd)
+ tmp = get_wiphy_regdom(request_wiphy);
+
+ regd = reg_copy_regd(rd);
+ if (IS_ERR(regd))
+ return PTR_ERR(regd);
+
+ rcu_assign_pointer(request_wiphy->regd, regd);
+ rcu_free_regdom(tmp);
}
- rcu_assign_pointer(request_wiphy->regd, regd);
- rcu_free_regdom(tmp);
- wiphy_unlock(request_wiphy);
reset_regdomains(false, rd);
return 0;
}
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 3fb31f17daf4ae..44973529687486 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -1234,7 +1234,8 @@ void cfg80211_sched_scan_results_wk(struct work_struct *work)
rdev = container_of(work, struct cfg80211_registered_device,
sched_scan_res_wk);
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
list_for_each_entry_safe(req, tmp, &rdev->sched_scan_req_list, list) {
if (req->report_results) {
req->report_results = false;
@@ -1249,7 +1250,6 @@ void cfg80211_sched_scan_results_wk(struct work_struct *work)
NL80211_CMD_SCHED_SCAN_RESULTS);
}
}
- wiphy_unlock(&rdev->wiphy);
}
void cfg80211_sched_scan_results(struct wiphy *wiphy, u64 reqid)
@@ -1284,9 +1284,9 @@ EXPORT_SYMBOL(cfg80211_sched_scan_stopped_locked);
void cfg80211_sched_scan_stopped(struct wiphy *wiphy, u64 reqid)
{
- wiphy_lock(wiphy);
+ guard(wiphy)(wiphy);
+
cfg80211_sched_scan_stopped_locked(wiphy, reqid);
- wiphy_unlock(wiphy);
}
EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
@@ -3558,10 +3558,8 @@ int cfg80211_wext_siwscan(struct net_device *dev,
/* translate "Scan for SSID" request */
if (wreq) {
if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
- if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) {
- err = -EINVAL;
- goto out;
- }
+ if (wreq->essid_len > IEEE80211_MAX_SSID_LEN)
+ return -EINVAL;
memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len);
creq->ssids[0].ssid_len = wreq->essid_len;
}
@@ -3577,20 +3575,20 @@ int cfg80211_wext_siwscan(struct net_device *dev,
eth_broadcast_addr(creq->bssid);
- wiphy_lock(&rdev->wiphy);
-
- rdev->scan_req = creq;
- err = rdev_scan(rdev, creq);
- if (err) {
- rdev->scan_req = NULL;
- /* creq will be freed below */
- } else {
- nl80211_send_scan_start(rdev, dev->ieee80211_ptr);
- /* creq now owned by driver */
- creq = NULL;
- dev_hold(dev);
+ scoped_guard(wiphy, &rdev->wiphy) {
+ rdev->scan_req = creq;
+ err = rdev_scan(rdev, creq);
+ if (err) {
+ rdev->scan_req = NULL;
+ /* creq will be freed below */
+ } else {
+ nl80211_send_scan_start(rdev, dev->ieee80211_ptr);
+ /* creq now owned by driver */
+ creq = NULL;
+ dev_hold(dev);
+ }
}
- wiphy_unlock(&rdev->wiphy);
+
out:
kfree(creq);
return err;
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index d8250ae17d940b..ab57648ca57748 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -252,7 +252,7 @@ void cfg80211_conn_work(struct work_struct *work)
u8 bssid_buf[ETH_ALEN], *bssid = NULL;
enum nl80211_timeout_reason treason;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
if (!wdev->netdev)
@@ -280,8 +280,6 @@ void cfg80211_conn_work(struct work_struct *work)
__cfg80211_connect_result(wdev->netdev, &cr, false);
}
}
-
- wiphy_unlock(&rdev->wiphy);
}
static void cfg80211_step_auth_next(struct cfg80211_conn *conn,
@@ -693,13 +691,13 @@ static bool cfg80211_is_all_idle(void)
* as chan dfs state, etc.
*/
for_each_rdev(rdev) {
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
if (wdev->conn || wdev->connected ||
cfg80211_beaconing_iface_active(wdev))
is_all_idle = false;
}
- wiphy_unlock(&rdev->wiphy);
}
return is_all_idle;
@@ -1586,7 +1584,7 @@ void cfg80211_autodisconnect_wk(struct work_struct *work)
container_of(work, struct wireless_dev, disconnect_wk);
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
- wiphy_lock(wdev->wiphy);
+ guard(wiphy)(wdev->wiphy);
if (wdev->conn_owner_nlportid) {
switch (wdev->iftype) {
@@ -1622,6 +1620,4 @@ void cfg80211_autodisconnect_wk(struct work_struct *work)
break;
}
}
-
- wiphy_unlock(wdev->wiphy);
}
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 5be4ccb8714110..8478f3a0e94021 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -2601,7 +2601,6 @@ int cfg80211_get_station(struct net_device *dev, const u8 *mac_addr,
{
struct cfg80211_registered_device *rdev;
struct wireless_dev *wdev;
- int ret;
wdev = dev->ieee80211_ptr;
if (!wdev)
@@ -2613,11 +2612,9 @@ int cfg80211_get_station(struct net_device *dev, const u8 *mac_addr,
memset(sinfo, 0, sizeof(*sinfo));
- wiphy_lock(&rdev->wiphy);
- ret = rdev_get_station(rdev, dev, mac_addr, sinfo);
- wiphy_unlock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
- return ret;
+ return rdev_get_station(rdev, dev, mac_addr, sinfo);
}
EXPORT_SYMBOL(cfg80211_get_station);
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 32a695c8a4d2af..186f84b3679bf0 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -40,7 +40,6 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
struct cfg80211_registered_device *rdev;
struct vif_params vifparams;
enum nl80211_iftype type;
- int ret;
rdev = wiphy_to_rdev(wdev->wiphy);
@@ -63,11 +62,9 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
memset(&vifparams, 0, sizeof(vifparams));
- wiphy_lock(wdev->wiphy);
- ret = cfg80211_change_iface(rdev, dev, type, &vifparams);
- wiphy_unlock(wdev->wiphy);
+ guard(wiphy)(wdev->wiphy);
- return ret;
+ return cfg80211_change_iface(rdev, dev, type, &vifparams);
}
EXPORT_WEXT_HANDLER(cfg80211_wext_siwmode);
@@ -262,23 +259,17 @@ int cfg80211_wext_siwrts(struct net_device *dev,
u32 orts = wdev->wiphy->rts_threshold;
int err;
- wiphy_lock(&rdev->wiphy);
- if (rts->disabled || !rts->fixed) {
+ guard(wiphy)(&rdev->wiphy);
+ if (rts->disabled || !rts->fixed)
wdev->wiphy->rts_threshold = (u32) -1;
- } else if (rts->value < 0) {
- err = -EINVAL;
- goto out;
- } else {
+ else if (rts->value < 0)
+ return -EINVAL;
+ else
wdev->wiphy->rts_threshold = rts->value;
- }
err = rdev_set_wiphy_params(rdev, WIPHY_PARAM_RTS_THRESHOLD);
-
if (err)
wdev->wiphy->rts_threshold = orts;
-
-out:
- wiphy_unlock(&rdev->wiphy);
return err;
}
EXPORT_WEXT_HANDLER(cfg80211_wext_siwrts);
@@ -308,12 +299,12 @@ int cfg80211_wext_siwfrag(struct net_device *dev,
u32 ofrag = wdev->wiphy->frag_threshold;
int err;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
if (frag->disabled || !frag->fixed) {
wdev->wiphy->frag_threshold = (u32) -1;
} else if (frag->value < 256) {
- err = -EINVAL;
- goto out;
+ return -EINVAL;
} else {
/* Fragment length must be even, so strip LSB. */
wdev->wiphy->frag_threshold = frag->value & ~0x1;
@@ -322,9 +313,6 @@ int cfg80211_wext_siwfrag(struct net_device *dev,
err = rdev_set_wiphy_params(rdev, WIPHY_PARAM_FRAG_THRESHOLD);
if (err)
wdev->wiphy->frag_threshold = ofrag;
-out:
- wiphy_unlock(&rdev->wiphy);
-
return err;
}
EXPORT_WEXT_HANDLER(cfg80211_wext_siwfrag);
@@ -360,7 +348,8 @@ static int cfg80211_wext_siwretry(struct net_device *dev,
(retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
return -EINVAL;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
if (retry->flags & IW_RETRY_LONG) {
wdev->wiphy->retry_long = retry->value;
changed |= WIPHY_PARAM_RETRY_LONG;
@@ -379,7 +368,6 @@ static int cfg80211_wext_siwretry(struct net_device *dev,
wdev->wiphy->retry_short = oshort;
wdev->wiphy->retry_long = olong;
}
- wiphy_unlock(&rdev->wiphy);
return err;
}
@@ -587,9 +575,9 @@ static int cfg80211_wext_siwencode(struct net_device *dev,
struct iw_point *erq = &wrqu->encoding;
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
- int idx, err;
- bool remove = false;
struct key_params params;
+ bool remove = false;
+ int idx;
if (wdev->iftype != NL80211_IFTYPE_STATION &&
wdev->iftype != NL80211_IFTYPE_ADHOC)
@@ -601,11 +589,9 @@ static int cfg80211_wext_siwencode(struct net_device *dev,
!rdev->ops->set_default_key)
return -EOPNOTSUPP;
- wiphy_lock(&rdev->wiphy);
- if (wdev->valid_links) {
- err = -EOPNOTSUPP;
- goto out;
- }
+ guard(wiphy)(&rdev->wiphy);
+ if (wdev->valid_links)
+ return -EOPNOTSUPP;
idx = erq->flags & IW_ENCODE_INDEX;
if (idx == 0) {
@@ -613,8 +599,7 @@ static int cfg80211_wext_siwencode(struct net_device *dev,
if (idx < 0)
idx = 0;
} else if (idx < 1 || idx > 4) {
- err = -EINVAL;
- goto out;
+ return -EINVAL;
} else {
idx--;
}
@@ -623,7 +608,8 @@ static int cfg80211_wext_siwencode(struct net_device *dev,
remove = true;
else if (erq->length == 0) {
/* No key data - just set the default TX key index */
- err = 0;
+ int err = 0;
+
if (wdev->connected ||
(wdev->iftype == NL80211_IFTYPE_ADHOC &&
wdev->u.ibss.current_bss))
@@ -631,28 +617,22 @@ static int cfg80211_wext_siwencode(struct net_device *dev,
true);
if (!err)
wdev->wext.default_key = idx;
- goto out;
+ return err;
}
memset(¶ms, 0, sizeof(params));
params.key = keybuf;
params.key_len = erq->length;
- if (erq->length == 5) {
+ if (erq->length == 5)
params.cipher = WLAN_CIPHER_SUITE_WEP40;
- } else if (erq->length == 13) {
+ else if (erq->length == 13)
params.cipher = WLAN_CIPHER_SUITE_WEP104;
- } else if (!remove) {
- err = -EINVAL;
- goto out;
- }
-
- err = cfg80211_set_encryption(rdev, dev, false, NULL, remove,
- wdev->wext.default_key == -1,
- idx, ¶ms);
-out:
- wiphy_unlock(&rdev->wiphy);
+ else if (!remove)
+ return -EINVAL;
- return err;
+ return cfg80211_set_encryption(rdev, dev, false, NULL, remove,
+ wdev->wext.default_key == -1,
+ idx, ¶ms);
}
static int cfg80211_wext_siwencodeext(struct net_device *dev,
@@ -668,7 +648,6 @@ static int cfg80211_wext_siwencodeext(struct net_device *dev,
bool remove = false;
struct key_params params;
u32 cipher;
- int ret;
if (wdev->iftype != NL80211_IFTYPE_STATION &&
wdev->iftype != NL80211_IFTYPE_ADHOC)
@@ -743,16 +722,13 @@ static int cfg80211_wext_siwencodeext(struct net_device *dev,
params.seq_len = 6;
}
- wiphy_lock(wdev->wiphy);
- ret = cfg80211_set_encryption(
- rdev, dev,
- !(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY),
- addr, remove,
- ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
- idx, ¶ms);
- wiphy_unlock(wdev->wiphy);
+ guard(wiphy)(wdev->wiphy);
- return ret;
+ return cfg80211_set_encryption(rdev, dev,
+ !(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY),
+ addr, remove,
+ ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
+ idx, ¶ms);
}
static int cfg80211_wext_giwencode(struct net_device *dev,
@@ -803,61 +779,41 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
struct cfg80211_chan_def chandef = {
.width = NL80211_CHAN_WIDTH_20_NOHT,
};
- int freq, ret;
+ int freq;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
switch (wdev->iftype) {
case NL80211_IFTYPE_STATION:
- ret = cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra);
- break;
+ return cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra);
case NL80211_IFTYPE_ADHOC:
- ret = cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra);
- break;
+ return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra);
case NL80211_IFTYPE_MONITOR:
freq = cfg80211_wext_freq(wextfreq);
- if (freq < 0) {
- ret = freq;
- break;
- }
- if (freq == 0) {
- ret = -EINVAL;
- break;
- }
+ if (freq < 0)
+ return freq;
+ if (freq == 0)
+ return -EINVAL;
+
chandef.center_freq1 = freq;
chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
- if (!chandef.chan) {
- ret = -EINVAL;
- break;
- }
- ret = cfg80211_set_monitor_channel(rdev, dev, &chandef);
- break;
+ if (!chandef.chan)
+ return -EINVAL;
+ return cfg80211_set_monitor_channel(rdev, dev, &chandef);
case NL80211_IFTYPE_MESH_POINT:
freq = cfg80211_wext_freq(wextfreq);
- if (freq < 0) {
- ret = freq;
- break;
- }
- if (freq == 0) {
- ret = -EINVAL;
- break;
- }
+ if (freq < 0)
+ return freq;
+ if (freq == 0)
+ return -EINVAL;
chandef.center_freq1 = freq;
chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
- if (!chandef.chan) {
- ret = -EINVAL;
- break;
- }
- ret = cfg80211_set_mesh_channel(rdev, wdev, &chandef);
- break;
+ if (!chandef.chan)
+ return -EINVAL;
+ return cfg80211_set_mesh_channel(rdev, wdev, &chandef);
default:
- ret = -EOPNOTSUPP;
- break;
+ return -EOPNOTSUPP;
}
-
- wiphy_unlock(&rdev->wiphy);
-
- return ret;
}
static int cfg80211_wext_giwfreq(struct net_device *dev,
@@ -870,35 +826,26 @@ static int cfg80211_wext_giwfreq(struct net_device *dev,
struct cfg80211_chan_def chandef = {};
int ret;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
switch (wdev->iftype) {
case NL80211_IFTYPE_STATION:
- ret = cfg80211_mgd_wext_giwfreq(dev, info, freq, extra);
- break;
+ return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra);
case NL80211_IFTYPE_ADHOC:
- ret = cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
- break;
+ return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
case NL80211_IFTYPE_MONITOR:
- if (!rdev->ops->get_channel) {
- ret = -EINVAL;
- break;
- }
+ if (!rdev->ops->get_channel)
+ return -EINVAL;
ret = rdev_get_channel(rdev, wdev, 0, &chandef);
if (ret)
- break;
+ return ret;
freq->m = chandef.chan->center_freq;
freq->e = 6;
- ret = 0;
- break;
+ return ret;
default:
- ret = -EINVAL;
- break;
+ return -EINVAL;
}
-
- wiphy_unlock(&rdev->wiphy);
-
- return ret;
}
static int cfg80211_wext_siwtxpower(struct net_device *dev,
@@ -909,7 +856,6 @@ static int cfg80211_wext_siwtxpower(struct net_device *dev,
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
enum nl80211_tx_power_setting type;
int dbm = 0;
- int ret;
if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
return -EINVAL;
@@ -951,11 +897,9 @@ static int cfg80211_wext_siwtxpower(struct net_device *dev,
return 0;
}
- wiphy_lock(&rdev->wiphy);
- ret = rdev_set_tx_power(rdev, wdev, type, DBM_TO_MBM(dbm));
- wiphy_unlock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
- return ret;
+ return rdev_set_tx_power(rdev, wdev, type, DBM_TO_MBM(dbm));
}
static int cfg80211_wext_giwtxpower(struct net_device *dev,
@@ -974,9 +918,9 @@ static int cfg80211_wext_giwtxpower(struct net_device *dev,
if (!rdev->ops->get_tx_power)
return -EOPNOTSUPP;
- wiphy_lock(&rdev->wiphy);
- err = rdev_get_tx_power(rdev, wdev, &val);
- wiphy_unlock(&rdev->wiphy);
+ scoped_guard(wiphy, &rdev->wiphy) {
+ err = rdev_get_tx_power(rdev, wdev, &val);
+ }
if (err)
return err;
@@ -1218,9 +1162,9 @@ static int cfg80211_wext_siwpower(struct net_device *dev,
timeout = wrq->value / 1000;
}
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
err = rdev_set_power_mgmt(rdev, dev, ps, timeout);
- wiphy_unlock(&rdev->wiphy);
if (err)
return err;
@@ -1253,8 +1197,8 @@ static int cfg80211_wext_siwrate(struct net_device *dev,
struct cfg80211_bitrate_mask mask;
u32 fixed, maxrate;
struct ieee80211_supported_band *sband;
- int band, ridx, ret;
bool match = false;
+ int band, ridx;
if (!rdev->ops->set_bitrate_mask)
return -EOPNOTSUPP;
@@ -1292,14 +1236,12 @@ static int cfg80211_wext_siwrate(struct net_device *dev,
if (!match)
return -EINVAL;
- wiphy_lock(&rdev->wiphy);
- if (dev->ieee80211_ptr->valid_links)
- ret = -EOPNOTSUPP;
- else
- ret = rdev_set_bitrate_mask(rdev, dev, 0, NULL, &mask);
- wiphy_unlock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
- return ret;
+ if (dev->ieee80211_ptr->valid_links)
+ return -EOPNOTSUPP;
+
+ return rdev_set_bitrate_mask(rdev, dev, 0, NULL, &mask);
}
static int cfg80211_wext_giwrate(struct net_device *dev,
@@ -1328,9 +1270,9 @@ static int cfg80211_wext_giwrate(struct net_device *dev,
if (err)
return err;
- wiphy_lock(&rdev->wiphy);
- err = rdev_get_station(rdev, dev, addr, &sinfo);
- wiphy_unlock(&rdev->wiphy);
+ scoped_guard(wiphy, &rdev->wiphy) {
+ err = rdev_get_station(rdev, dev, addr, &sinfo);
+ }
if (err)
return err;
@@ -1429,23 +1371,17 @@ static int cfg80211_wext_siwap(struct net_device *dev,
struct sockaddr *ap_addr = &wrqu->ap_addr;
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
- int ret;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
switch (wdev->iftype) {
case NL80211_IFTYPE_ADHOC:
- ret = cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra);
- break;
+ return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra);
case NL80211_IFTYPE_STATION:
- ret = cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra);
- break;
+ return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra);
default:
- ret = -EOPNOTSUPP;
- break;
+ return -EOPNOTSUPP;
}
- wiphy_unlock(&rdev->wiphy);
-
- return ret;
}
static int cfg80211_wext_giwap(struct net_device *dev,
@@ -1455,23 +1391,17 @@ static int cfg80211_wext_giwap(struct net_device *dev,
struct sockaddr *ap_addr = &wrqu->ap_addr;
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
- int ret;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
switch (wdev->iftype) {
case NL80211_IFTYPE_ADHOC:
- ret = cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra);
- break;
+ return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra);
case NL80211_IFTYPE_STATION:
- ret = cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra);
- break;
+ return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra);
default:
- ret = -EOPNOTSUPP;
- break;
+ return -EOPNOTSUPP;
}
- wiphy_unlock(&rdev->wiphy);
-
- return ret;
}
static int cfg80211_wext_siwessid(struct net_device *dev,
@@ -1481,23 +1411,17 @@ static int cfg80211_wext_siwessid(struct net_device *dev,
struct iw_point *data = &wrqu->data;
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
- int ret;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
switch (wdev->iftype) {
case NL80211_IFTYPE_ADHOC:
- ret = cfg80211_ibss_wext_siwessid(dev, info, data, ssid);
- break;
+ return cfg80211_ibss_wext_siwessid(dev, info, data, ssid);
case NL80211_IFTYPE_STATION:
- ret = cfg80211_mgd_wext_siwessid(dev, info, data, ssid);
- break;
+ return cfg80211_mgd_wext_siwessid(dev, info, data, ssid);
default:
- ret = -EOPNOTSUPP;
- break;
+ return -EOPNOTSUPP;
}
- wiphy_unlock(&rdev->wiphy);
-
- return ret;
}
static int cfg80211_wext_giwessid(struct net_device *dev,
@@ -1507,26 +1431,20 @@ static int cfg80211_wext_giwessid(struct net_device *dev,
struct iw_point *data = &wrqu->data;
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
- int ret;
data->flags = 0;
data->length = 0;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
switch (wdev->iftype) {
case NL80211_IFTYPE_ADHOC:
- ret = cfg80211_ibss_wext_giwessid(dev, info, data, ssid);
- break;
+ return cfg80211_ibss_wext_giwessid(dev, info, data, ssid);
case NL80211_IFTYPE_STATION:
- ret = cfg80211_mgd_wext_giwessid(dev, info, data, ssid);
- break;
+ return cfg80211_mgd_wext_giwessid(dev, info, data, ssid);
default:
- ret = -EOPNOTSUPP;
- break;
+ return -EOPNOTSUPP;
}
- wiphy_unlock(&rdev->wiphy);
-
- return ret;
}
static int cfg80211_wext_siwpmksa(struct net_device *dev,
@@ -1537,7 +1455,6 @@ static int cfg80211_wext_siwpmksa(struct net_device *dev,
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
struct cfg80211_pmksa cfg_pmksa;
struct iw_pmksa *pmksa = (struct iw_pmksa *)extra;
- int ret;
memset(&cfg_pmksa, 0, sizeof(struct cfg80211_pmksa));
@@ -1547,39 +1464,27 @@ static int cfg80211_wext_siwpmksa(struct net_device *dev,
cfg_pmksa.bssid = pmksa->bssid.sa_data;
cfg_pmksa.pmkid = pmksa->pmkid;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
switch (pmksa->cmd) {
case IW_PMKSA_ADD:
- if (!rdev->ops->set_pmksa) {
- ret = -EOPNOTSUPP;
- break;
- }
+ if (!rdev->ops->set_pmksa)
+ return -EOPNOTSUPP;
- ret = rdev_set_pmksa(rdev, dev, &cfg_pmksa);
- break;
+ return rdev_set_pmksa(rdev, dev, &cfg_pmksa);
case IW_PMKSA_REMOVE:
- if (!rdev->ops->del_pmksa) {
- ret = -EOPNOTSUPP;
- break;
- }
+ if (!rdev->ops->del_pmksa)
+ return -EOPNOTSUPP;
- ret = rdev_del_pmksa(rdev, dev, &cfg_pmksa);
- break;
+ return rdev_del_pmksa(rdev, dev, &cfg_pmksa);
case IW_PMKSA_FLUSH:
- if (!rdev->ops->flush_pmksa) {
- ret = -EOPNOTSUPP;
- break;
- }
+ if (!rdev->ops->flush_pmksa)
+ return -EOPNOTSUPP;
- ret = rdev_flush_pmksa(rdev, dev);
- break;
+ return rdev_flush_pmksa(rdev, dev);
default:
- ret = -EOPNOTSUPP;
- break;
+ return -EOPNOTSUPP;
}
- wiphy_unlock(&rdev->wiphy);
-
- return ret;
}
static const iw_handler cfg80211_handlers[] = {
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c
index 8edd9ada69d0bd..573b6b15a446ec 100644
--- a/net/wireless/wext-sme.c
+++ b/net/wireless/wext-sme.c
@@ -302,8 +302,8 @@ int cfg80211_wext_siwgenie(struct net_device *dev,
struct iw_point *data = &wrqu->data;
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
+ int ie_len = data->length;
u8 *ie = extra;
- int ie_len = data->length, err;
if (wdev->iftype != NL80211_IFTYPE_STATION)
return -EOPNOTSUPP;
@@ -311,39 +311,31 @@ int cfg80211_wext_siwgenie(struct net_device *dev,
if (!ie_len)
ie = NULL;
- wiphy_lock(wdev->wiphy);
+ guard(wiphy)(wdev->wiphy);
/* no change */
- err = 0;
if (wdev->wext.ie_len == ie_len &&
memcmp(wdev->wext.ie, ie, ie_len) == 0)
- goto out;
+ return 0;
if (ie_len) {
ie = kmemdup(extra, ie_len, GFP_KERNEL);
- if (!ie) {
- err = -ENOMEM;
- goto out;
- }
- } else
+ if (!ie)
+ return -ENOMEM;
+ } else {
ie = NULL;
+ }
kfree(wdev->wext.ie);
wdev->wext.ie = ie;
wdev->wext.ie_len = ie_len;
- if (wdev->conn) {
- err = cfg80211_disconnect(rdev, dev,
- WLAN_REASON_DEAUTH_LEAVING, false);
- if (err)
- goto out;
- }
+ if (wdev->conn)
+ return cfg80211_disconnect(rdev, dev,
+ WLAN_REASON_DEAUTH_LEAVING, false);
/* userspace better not think we'll reconnect */
- err = 0;
- out:
- wiphy_unlock(wdev->wiphy);
- return err;
+ return 0;
}
int cfg80211_wext_siwmlme(struct net_device *dev,
@@ -353,7 +345,6 @@ int cfg80211_wext_siwmlme(struct net_device *dev,
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct iw_mlme *mlme = (struct iw_mlme *)extra;
struct cfg80211_registered_device *rdev;
- int err;
if (!wdev)
return -EOPNOTSUPP;
@@ -366,17 +357,13 @@ int cfg80211_wext_siwmlme(struct net_device *dev,
if (mlme->addr.sa_family != ARPHRD_ETHER)
return -EINVAL;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
switch (mlme->cmd) {
case IW_MLME_DEAUTH:
case IW_MLME_DISASSOC:
- err = cfg80211_disconnect(rdev, dev, mlme->reason_code, true);
- break;
+ return cfg80211_disconnect(rdev, dev, mlme->reason_code, true);
default:
- err = -EOPNOTSUPP;
- break;
+ return -EOPNOTSUPP;
}
- wiphy_unlock(&rdev->wiphy);
-
- return err;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 064/602] wifi: cfg80211: convert pmsr_free_wk to wiphy_work to fix deadlock
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (62 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 063/602] wifi: cfg80211: define and use wiphy guard Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 065/602] wifi: nl80211: free RNR data on MBSSID mismatch Greg Kroah-Hartman
` (541 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Peddolla Harshavardhan Reddy,
Johannes Berg, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
[ Upstream commit 2b0eab425e1f658d8fe1df7590e3b9af5959505e ]
When a netlink socket that owns a PMSR session is closed,
cfg80211_release_pmsr() clears the request's nl_portid and queues
pmsr_free_wk to call cfg80211_pmsr_process_abort() asynchronously.
If the interface tears down concurrently, cfg80211_pmsr_wdev_down()
is called under wiphy_lock and calls cancel_work_sync(&pmsr_free_wk)
to wait for any running work. The work function acquires wiphy_lock
via guard(wiphy) before calling process_abort.
This is a deadlock: wdev_down holds wiphy_lock and blocks inside
cancel_work_sync(); pmsr_free_wk blocks trying to acquire that same
wiphy_lock. Neither thread can proceed.
The same deadlock is reachable from cfg80211_leave_locked(), which
calls cfg80211_pmsr_wdev_down() for all interface types under
wiphy_lock.
Fix this by converting pmsr_free_wk from a plain work_struct to a
wiphy_work. The wiphy_work dispatcher holds wiphy_lock when running
work items, so the explicit guard(wiphy) in the work function is no
longer needed. wiphy_work_cancel() can be called safely while holding
wiphy_lock - since wiphy_lock prevents the work from running
concurrently, wiphy_work_cancel() never blocks, eliminating the
deadlock.
Remove the cancel_work_sync() for pmsr_free_wk from the
NETDEV_GOING_DOWN handler. cfg80211_leave(), called unconditionally
just before it, already cancels any pending work under wiphy_lock
via wiphy_work_cancel() inside cfg80211_pmsr_wdev_down().
Fixes: 6dccbc9f3e1d ("wifi: cfg80211: cancel pmsr_free_wk in cfg80211_pmsr_wdev_down")
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy@oss.qualcomm.com>
Link: https://patch.msgid.link/20260703082523.2629324-1-peddolla.reddy@oss.qualcomm.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
include/net/cfg80211.h | 2 +-
net/wireless/core.c | 3 +--
net/wireless/core.h | 2 +-
net/wireless/pmsr.c | 8 +++-----
4 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a76e0459a8e63b..8dcb218e08047b 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -6414,7 +6414,7 @@ struct wireless_dev {
struct list_head pmsr_list;
spinlock_t pmsr_lock;
- struct work_struct pmsr_free_wk;
+ struct wiphy_work pmsr_free_wk;
unsigned long unprot_beacon_reported;
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 7799cec95a9d99..5bc3e12e7b2de0 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -1418,7 +1418,7 @@ void cfg80211_init_wdev(struct wireless_dev *wdev)
INIT_LIST_HEAD(&wdev->mgmt_registrations);
INIT_LIST_HEAD(&wdev->pmsr_list);
spin_lock_init(&wdev->pmsr_lock);
- INIT_WORK(&wdev->pmsr_free_wk, cfg80211_pmsr_free_wk);
+ wiphy_work_init(&wdev->pmsr_free_wk, cfg80211_pmsr_free_wk);
#ifdef CONFIG_CFG80211_WEXT
wdev->wext.default_key = -1;
@@ -1551,7 +1551,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
}
/* since we just did cfg80211_leave() nothing to do there */
cancel_work_sync(&wdev->disconnect_wk);
- cancel_work_sync(&wdev->pmsr_free_wk);
break;
case NETDEV_DOWN:
wiphy_lock(&rdev->wiphy);
diff --git a/net/wireless/core.h b/net/wireless/core.h
index a60883b6e43105..b02b456cfca379 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -560,7 +560,7 @@ cfg80211_get_6ghz_power_type(const u8 *elems, size_t elems_len);
void cfg80211_release_pmsr(struct wireless_dev *wdev, u32 portid);
void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev);
-void cfg80211_pmsr_free_wk(struct work_struct *work);
+void cfg80211_pmsr_free_wk(struct wiphy *wiphy, struct wiphy_work *work);
void cfg80211_remove_link(struct wireless_dev *wdev, unsigned int link_id);
void cfg80211_remove_links(struct wireless_dev *wdev);
diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c
index 13801cf35e9fca..d2546c27879fa4 100644
--- a/net/wireless/pmsr.c
+++ b/net/wireless/pmsr.c
@@ -625,13 +625,11 @@ static void cfg80211_pmsr_process_abort(struct wireless_dev *wdev)
}
}
-void cfg80211_pmsr_free_wk(struct work_struct *work)
+void cfg80211_pmsr_free_wk(struct wiphy *wiphy, struct wiphy_work *work)
{
struct wireless_dev *wdev = container_of(work, struct wireless_dev,
pmsr_free_wk);
- guard(wiphy)(wdev->wiphy);
-
cfg80211_pmsr_process_abort(wdev);
}
@@ -647,7 +645,7 @@ void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev)
}
spin_unlock_bh(&wdev->pmsr_lock);
- cancel_work_sync(&wdev->pmsr_free_wk);
+ wiphy_work_cancel(wdev->wiphy, &wdev->pmsr_free_wk);
if (found)
cfg80211_pmsr_process_abort(wdev);
@@ -662,7 +660,7 @@ void cfg80211_release_pmsr(struct wireless_dev *wdev, u32 portid)
list_for_each_entry(req, &wdev->pmsr_list, list) {
if (req->nl_portid == portid) {
req->nl_portid = 0;
- schedule_work(&wdev->pmsr_free_wk);
+ wiphy_work_queue(wdev->wiphy, &wdev->pmsr_free_wk);
}
}
spin_unlock_bh(&wdev->pmsr_lock);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 065/602] wifi: nl80211: free RNR data on MBSSID mismatch
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (63 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 064/602] wifi: cfg80211: convert pmsr_free_wk to wiphy_work to fix deadlock Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 066/602] wifi: cfg80211: derive S1G beacon TSF from S1G fields Greg Kroah-Hartman
` (540 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Zhao Li, Johannes Berg, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhao Li <enderaoelyther@gmail.com>
[ Upstream commit 07a95ec2b54774201fdf4ef7ffb0ca2ab19ed29c ]
nl80211_parse_beacon() rejects EMA RNR data when there are fewer RNR
entries than MBSSID entries.
The rejected RNR allocation has not been attached to the beacon data yet,
so free it before returning the error.
Fixes: dbbb27e183b1 ("cfg80211: support RNR for EMA AP")
Signed-off-by: Zhao Li <enderaoelyther@gmail.com>
Link: https://patch.msgid.link/20260610112208.1308-2-enderaoelyther@gmail.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/wireless/nl80211.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 0af78812e38efe..60e00a24bc249a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -5711,8 +5711,10 @@ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
if (IS_ERR(rnr))
return PTR_ERR(rnr);
- if (rnr && rnr->cnt < bcn->mbssid_ies->cnt)
+ if (rnr && rnr->cnt < bcn->mbssid_ies->cnt) {
+ kfree(rnr);
return -EINVAL;
+ }
bcn->rnr_ies = rnr;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 066/602] wifi: cfg80211: derive S1G beacon TSF from S1G fields
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (64 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 065/602] wifi: nl80211: free RNR data on MBSSID mismatch Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 067/602] wifi: nl80211: validate nested MBSSID IE blobs Greg Kroah-Hartman
` (539 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Zhao Li, Lachlan Hodges,
Johannes Berg, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhao Li <enderaoelyther@gmail.com>
[ Upstream commit 4e5a4641e7b4763656336b7891d01359aaf363cd ]
cfg80211_inform_bss_frame_data() parses S1G beacons with the extension
frame layout, but still reads the TSF from the regular probe response
layout after the S1G branch. For S1G beacons that reads bytes at the
regular management-frame timestamp offset instead of the S1G timestamp.
Use the 32-bit S1G beacon timestamp and the S1G Beacon Compatibility
element's TSF completion field when informing an S1G BSS. Keep the
regular management-frame timestamp read in the non-S1G branch.
Fixes: 9eaffe5078ca ("cfg80211: convert S1G beacon to scan results")
Signed-off-by: Zhao Li <enderaoelyther@gmail.com>
Tested-by: Lachlan Hodges <lachlan.hodges@morsemicro.com>
Reviewed-by: Lachlan Hodges <lachlan.hodges@morsemicro.com>
Link: https://patch.msgid.link/20260611161943.91069-6-enderaoelyther@gmail.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/wireless/scan.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 44973529687486..b249f29454f9e1 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -3262,14 +3262,15 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
bssid = ext->u.s1g_beacon.sa;
capability = le16_to_cpu(compat->compat_info);
beacon_interval = le16_to_cpu(compat->beacon_int);
+ tsf = le32_to_cpu(ext->u.s1g_beacon.timestamp);
+ tsf |= (u64)le32_to_cpu(compat->tsf_completion) << 32;
} else {
bssid = mgmt->bssid;
beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
+ tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
}
- tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
-
if (ieee80211_is_probe_resp(mgmt->frame_control))
ftype = CFG80211_BSS_FTYPE_PRESP;
else if (ext)
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 067/602] wifi: nl80211: validate nested MBSSID IE blobs
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (65 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 066/602] wifi: cfg80211: derive S1G beacon TSF from S1G fields Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 068/602] wifi: cfg80211: validate PMSR measurement type data Greg Kroah-Hartman
` (538 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Zhao Li, Johannes Berg, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhao Li <enderaoelyther@gmail.com>
[ Upstream commit 7f4b01812323443b55e4c65381c9dc851ff009e3 ]
Validate each nested NL80211_ATTR_MBSSID_ELEMS entry as a well-formed
information-element stream before storing it for beacon construction.
RNR parsing already validates each nested blob with validate_ie_attr()
before storing it. Apply the same syntactic IE validation to MBSSID
entries before counting and copying their data and length pointers.
Fixes: dc1e3cb8da8b ("nl80211: MBSSID and EMA support in AP mode")
Assisted-by: Codex:gpt-5.5
Assisted-by: Claude:claude-opus-4.8
Signed-off-by: Zhao Li <enderaoelyther@gmail.com>
Link: https://patch.msgid.link/20260612131854.43575-3-enderaoelyther@gmail.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/wireless/nl80211.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 60e00a24bc249a..1702616d9e1c9a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -5513,7 +5513,8 @@ static int nl80211_parse_mbssid_config(struct wiphy *wiphy,
}
static struct cfg80211_mbssid_elems *
-nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs)
+nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs,
+ struct netlink_ext_ack *extack)
{
struct nlattr *nl_elems;
struct cfg80211_mbssid_elems *elems;
@@ -5524,6 +5525,12 @@ nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs)
return ERR_PTR(-EINVAL);
nla_for_each_nested(nl_elems, attrs, rem_elems) {
+ int ret;
+
+ ret = validate_ie_attr(nl_elems, extack);
+ if (ret)
+ return ERR_PTR(ret);
+
if (num_elems >= 255)
return ERR_PTR(-EINVAL);
num_elems++;
@@ -5695,7 +5702,8 @@ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
if (attrs[NL80211_ATTR_MBSSID_ELEMS]) {
struct cfg80211_mbssid_elems *mbssid =
nl80211_parse_mbssid_elems(&rdev->wiphy,
- attrs[NL80211_ATTR_MBSSID_ELEMS]);
+ attrs[NL80211_ATTR_MBSSID_ELEMS],
+ extack);
if (IS_ERR(mbssid))
return PTR_ERR(mbssid);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 068/602] wifi: cfg80211: validate PMSR measurement type data
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (66 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 067/602] wifi: nl80211: validate nested MBSSID IE blobs Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 069/602] wifi: cfg80211: validate PMSR FTM preamble range Greg Kroah-Hartman
` (537 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Zhao Li, Johannes Berg, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhao Li <enderaoelyther@gmail.com>
[ Upstream commit 41aa973eb05922848dded26875c55ef982ac1c49 ]
PMSR request parsing accepts missing or duplicated measurement type
entries in NL80211_PMSR_REQ_ATTR_DATA.
Track whether one measurement type was already provided, reject a
second one immediately, and return an error if the request data block
contains no measurement type at all.
Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API")
Assisted-by: Codex:gpt-5.5
Assisted-by: Claude:claude-opus-4.8
Signed-off-by: Zhao Li <enderaoelyther@gmail.com>
Link: https://patch.msgid.link/20260612133656.92900-2-enderaoelyther@gmail.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/wireless/pmsr.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c
index d2546c27879fa4..fd14a3c2eab45b 100644
--- a/net/wireless/pmsr.c
+++ b/net/wireless/pmsr.c
@@ -196,6 +196,7 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev,
{
struct nlattr *tb[NL80211_PMSR_PEER_ATTR_MAX + 1];
struct nlattr *req[NL80211_PMSR_REQ_ATTR_MAX + 1];
+ bool have_measurement_type = false;
struct nlattr *treq;
int err, rem;
@@ -248,6 +249,14 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev,
}
nla_for_each_nested(treq, req[NL80211_PMSR_REQ_ATTR_DATA], rem) {
+ if (have_measurement_type) {
+ NL_SET_ERR_MSG_ATTR(info->extack, treq,
+ "multiple measurement types in request data");
+ return -EINVAL;
+ }
+
+ have_measurement_type = true;
+
switch (nla_type(treq)) {
case NL80211_PMSR_TYPE_FTM:
err = pmsr_parse_ftm(rdev, treq, out, info);
@@ -257,10 +266,16 @@ static int pmsr_parse_peer(struct cfg80211_registered_device *rdev,
"unsupported measurement type");
err = -EINVAL;
}
+ if (err)
+ return err;
}
- if (err)
- return err;
+ if (!have_measurement_type) {
+ NL_SET_ERR_MSG_ATTR(info->extack,
+ req[NL80211_PMSR_REQ_ATTR_DATA],
+ "missing measurement type in request data");
+ return -EINVAL;
+ }
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 069/602] wifi: cfg80211: validate PMSR FTM preamble range
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (67 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 068/602] wifi: cfg80211: validate PMSR measurement type data Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 070/602] wifi: cfg80211: reject unsupported PMSR FTM location requests Greg Kroah-Hartman
` (536 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Zhao Li, Johannes Berg, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhao Li <enderaoelyther@gmail.com>
[ Upstream commit 36230936468f0ba4930e94aef496fc229d4bb951 ]
PMSR FTM request parsing accepts preamble values outside the
enumerated nl80211 preamble range.
Reject out-of-range values before using them in the parser capability
bit test using the policy.
Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API")
Assisted-by: Codex:gpt-5.5
Assisted-by: Claude:claude-opus-4.8
Signed-off-by: Zhao Li <enderaoelyther@gmail.com>
Link: https://patch.msgid.link/20260612133703.93274-2-enderaoelyther@gmail.com
[drop unnecessary check]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/wireless/nl80211.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 1702616d9e1c9a..b54da0f83247a9 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -312,7 +312,9 @@ nl80211_ftm_responder_policy[NL80211_FTM_RESP_ATTR_MAX + 1] = {
static const struct nla_policy
nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = {
[NL80211_PMSR_FTM_REQ_ATTR_ASAP] = { .type = NLA_FLAG },
- [NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE] = { .type = NLA_U32 },
+ [NL80211_PMSR_FTM_REQ_ATTR_PREAMBLE] =
+ NLA_POLICY_RANGE(NLA_U32, NL80211_PREAMBLE_LEGACY,
+ NL80211_PREAMBLE_HE),
[NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP] =
NLA_POLICY_MAX(NLA_U8, 15),
[NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD] = { .type = NLA_U16 },
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 070/602] wifi: cfg80211: reject unsupported PMSR FTM location requests
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (68 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 069/602] wifi: cfg80211: validate PMSR FTM preamble range Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 071/602] wifi: mac80211: free AP_VLAN bc_buf SKBs outside IRQ lock Greg Kroah-Hartman
` (535 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Zhao Li, Johannes Berg, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhao Li <enderaoelyther@gmail.com>
[ Upstream commit 69ef6a7ec277f16d216be8da2b3cbe872786c999 ]
PMSR FTM location request flags are syntactically valid, but they must
be rejected when the device capability does not advertise support for
them.
Return an error immediately after rejecting unsupported LCI or civic
location request bits so the request cannot reach the driver.
Fixes: 9bb7e0f24e7e7 ("cfg80211: add peer measurement with FTM initiator API")
Assisted-by: Codex:gpt-5.5
Assisted-by: Claude:claude-opus-4.8
Signed-off-by: Zhao Li <enderaoelyther@gmail.com>
Link: https://patch.msgid.link/20260612133710.93544-2-enderaoelyther@gmail.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/wireless/pmsr.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c
index fd14a3c2eab45b..06563f60848705 100644
--- a/net/wireless/pmsr.c
+++ b/net/wireless/pmsr.c
@@ -114,6 +114,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev,
NL_SET_ERR_MSG_ATTR(info->extack,
tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI],
"FTM: LCI request not supported");
+ return -EOPNOTSUPP;
}
out->ftm.request_civicloc =
@@ -122,6 +123,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev,
NL_SET_ERR_MSG_ATTR(info->extack,
tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC],
"FTM: civic location request not supported");
+ return -EOPNOTSUPP;
}
out->ftm.trigger_based =
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 071/602] wifi: mac80211: free AP_VLAN bc_buf SKBs outside IRQ lock
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (69 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 070/602] wifi: cfg80211: reject unsupported PMSR FTM location requests Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 072/602] wifi: brcmfmac: initialize SDIO data work before cleanup Greg Kroah-Hartman
` (534 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Cen Zhang, Johannes Berg,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cen Zhang <zzzccc427@gmail.com>
[ Upstream commit f3858d5b1432098c1936e03d6e03dd0e33facf60 ]
ieee80211_do_stop() removes AP_VLAN packets from the parent AP
ps->bc_buf while holding ps->bc_buf.lock with IRQs disabled. It then
calls ieee80211_free_txskb() before dropping the lock.
ieee80211_free_txskb() is not just a passive SKB release. For SKBs with
TX status state it can report a dropped frame through cfg80211/nl80211,
and that path can reach netlink tap transmit. This is the same reason
the pending queue cleanup in ieee80211_do_stop() already unlinks SKBs
under the queue lock and frees them after IRQ state is restored.
The buggy scenario involves two paths, with each column showing the
order within that path:
AP_VLAN management TX: AP_VLAN stop:
1. attach ACK-status state 1. clear the running state
2. queue a multicast SKB on 2. take ps->bc_buf.lock with IRQs
parent ps->bc_buf disabled
3. unlink the AP_VLAN SKB
4. call ieee80211_free_txskb()
Unlink matching AP_VLAN SKBs from ps->bc_buf under the existing lock,
but move them to a local free queue. Drop the lock and restore IRQ state
before calling ieee80211_free_txskb().
WARNING: kernel/softirq.c:430 at __local_bh_enable_ip
Fixes: 397a7a24ef8c ("mac80211: free ps->bc_buf skbs on vlan device stop")
Assisted-by: Codex:gpt-5.5
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Link: https://patch.msgid.link/20260706140841.581566-1-zzzccc427@gmail.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/mac80211/iface.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 7e1b6a9d9f3ad8..7a79b40d23b36b 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -590,6 +590,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
WARN_ON(!list_empty(&sdata->u.ap.vlans));
} else if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
/* remove all packets in parent bc_buf pointing to this dev */
+ __skb_queue_head_init(&freeq);
ps = &sdata->bss->ps;
spin_lock_irqsave(&ps->bc_buf.lock, flags);
@@ -597,10 +598,15 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
if (skb->dev == sdata->dev) {
__skb_unlink(skb, &ps->bc_buf);
local->total_ps_buffered--;
- ieee80211_free_txskb(&local->hw, skb);
+ __skb_queue_tail(&freeq, skb);
}
}
spin_unlock_irqrestore(&ps->bc_buf.lock, flags);
+
+ skb_queue_walk_safe(&freeq, skb, tmp) {
+ __skb_unlink(skb, &freeq);
+ ieee80211_free_txskb(&local->hw, skb);
+ }
}
if (going_down)
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 072/602] wifi: brcmfmac: initialize SDIO data work before cleanup
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (70 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 071/602] wifi: mac80211: free AP_VLAN bc_buf SKBs outside IRQ lock Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 073/602] wifi: cfg80211: bound element ID read when checking non-inheritance Greg Kroah-Hartman
` (533 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Runyu Xiao, Arend van Spriel,
Johannes Berg, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Runyu Xiao <runyu.xiao@seu.edu.cn>
[ Upstream commit 2a665946e0407a05a3f81bd56a08553c446498e0 ]
brcmf_sdio_probe() stores the newly allocated bus in sdiodev->bus before
allocating the ordered workqueue. If that allocation fails, the function
jumps to fail and calls brcmf_sdio_remove().
brcmf_sdio_remove() unconditionally cancels bus->datawork. Initialize the
work item before the first failure path that can reach brcmf_sdio_remove(),
so the cleanup path always observes a valid work object.
This issue was found by our static analysis tool and then confirmed by
manual review of the probe error path and the remove-time work drain. The
problem pattern is an early setup failure that reaches a cleanup helper
which cancels an embedded work item before its initializer has run.
A QEMU PoC forced alloc_ordered_workqueue() to fail at the same point in
brcmf_sdio_probe(), before INIT_WORK(&bus->datawork) is reached. The
resulting fail path calls brcmf_sdio_remove(), and DEBUG_OBJECTS reports
the invalid work drain with brcmf_sdio_probe() and brcmf_sdio_remove() in
the stack.
Fixes: 9982464379e8 ("brcmfmac: make sdio suspend wait for threads to freeze")
Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn>
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Link: https://patch.msgid.link/20260619064401.1048976-1-runyu.xiao@seu.edu.cn
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 71bb8b699731ba..a1b26144607698 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -4458,6 +4458,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
bus->sdiodev = sdiodev;
sdiodev->bus = bus;
skb_queue_head_init(&bus->glom);
+ INIT_WORK(&bus->datawork, brcmf_sdio_dataworker);
bus->txbound = BRCMF_TXBOUND;
bus->rxbound = BRCMF_RXBOUND;
bus->txminmax = BRCMF_TXMINMAX;
@@ -4471,7 +4472,6 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
goto fail;
}
brcmf_sdiod_freezer_count(sdiodev);
- INIT_WORK(&bus->datawork, brcmf_sdio_dataworker);
bus->brcmf_wq = wq;
/* attempt to attach to the dongle */
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 073/602] wifi: cfg80211: bound element ID read when checking non-inheritance
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (71 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 072/602] wifi: brcmfmac: initialize SDIO data work before cleanup Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 074/602] ASoC: meson: aiu: fifo-spdif: soft reset the S/PDIF datapath on start/stop Greg Kroah-Hartman
` (532 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, HE WEI , Johannes Berg, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: HE WEI (ギカク) <skyexpoc@gmail.com>
[ Upstream commit cb8afea4655ff004fa7feee825d5c79783525383 ]
cfg80211_is_element_inherited() reads the first data octet of the
candidate element (id = elem->data[0]) to look it up in an extension
non-inheritance list. It does so after testing elem->id, but without
verifying that the element actually has a data octet. A zero-length
extension element (WLAN_EID_EXTENSION with length 0) therefore makes it
read one octet past the end of the element.
_ieee802_11_parse_elems_full() runs this check for every element of a
frame once a non-inheritance context exists -- e.g. while parsing a
per-STA profile of a Multi-Link element in a (re)association response,
or a non-transmitted BSS profile -- so a crafted frame from an AP can
trigger a one-octet slab-out-of-bounds read during element parsing:
BUG: KASAN: slab-out-of-bounds in cfg80211_is_element_inherited
Read of size 1 ... in net/wireless/scan.c
Return early (treat the element as inherited) when an extension element
carries no data, mirroring the existing handling of empty ID lists.
The bug was found by fuzzing ieee802_11_parse_elems_full() under KASAN.
Fixes: f7dacfb11475 ("cfg80211: support non-inheritance element")
Signed-off-by: HE WEI (ギカク) <skyexpoc@gmail.com>
Link: https://patch.msgid.link/20260707094828.16465-1-skyexpoc@gmail.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/wireless/scan.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index b249f29454f9e1..3c439841578c49 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -205,7 +205,7 @@ bool cfg80211_is_element_inherited(const struct element *elem,
return true;
if (elem->id == WLAN_EID_EXTENSION) {
- if (!ext_id_len)
+ if (!ext_id_len || !elem->datalen)
return true;
loop_len = ext_id_len;
list = &non_inherit_elem->data[3 + id_len];
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 074/602] ASoC: meson: aiu: fifo-spdif: soft reset the S/PDIF datapath on start/stop
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (72 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 073/602] wifi: cfg80211: bound element ID read when checking non-inheritance Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 075/602] ASoC: amd: ps: fix wrong ACP version string in pci_request_regions() Greg Kroah-Hartman
` (531 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Christian Hewitt,
Martin Blumenstingl, Mark Brown, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Hewitt <christianshewitt@gmail.com>
[ Upstream commit 6b59c53c8adc2b522327407af5e1793a65b67e4b ]
The I2S FIFO soft-resets its fast domain on start (AIU_RST_SOFT bit 0 +
AIU_I2S_SYNC read in aiu_fifo_i2s_trigger), mirroring the downstream
vendor driver's audio_out_i2s_enable(). The S/PDIF FIFO has no equivalent:
it only toggles the IEC958 DCU, so a stale datapath FIFO can be replayed,
producing the "machine gun noise" buffer underrun - on start when switching
outputs, and on stop when playback ends. The latter is audible on devices
with an always-on S/PDIF-fed DAC (e.g. the ES7144 on the WeTek Play2).
The vendor driver resets the IEC958 fast domain (AIU_RST_SOFT bit 2) on
both enable and disable (audio_hw_958_enable), and when reconfiguring
(audio_hw_958_reset clears AIU_958_DCU_FF_CTRL then resets). Do the same:
reset before enabling the DCU on start, and before disabling on stop.
Fixes: 6ae9ca9ce986bf ("ASoC: meson: aiu: add i2s and spdif support")
Signed-off-by: Christian Hewitt <christianshewitt@gmail.com>
Reviewed-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Link: https://patch.msgid.link/20260627131205.808800-1-christianshewitt@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
sound/soc/meson/aiu-fifo-spdif.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/sound/soc/meson/aiu-fifo-spdif.c b/sound/soc/meson/aiu-fifo-spdif.c
index e0e00ec026dcc4..a9861c5d663745 100644
--- a/sound/soc/meson/aiu-fifo-spdif.c
+++ b/sound/soc/meson/aiu-fifo-spdif.c
@@ -24,6 +24,7 @@
#define AIU_MEM_IEC958_CONTROL_MODE_16BIT BIT(7)
#define AIU_MEM_IEC958_CONTROL_MODE_LINEAR BIT(8)
#define AIU_MEM_IEC958_BUF_CNTL_INIT BIT(0)
+#define AIU_RST_SOFT_958_FAST BIT(2)
#define AIU_FIFO_SPDIF_BLOCK 8
@@ -68,11 +69,15 @@ static int fifo_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ snd_soc_component_write(component, AIU_RST_SOFT,
+ AIU_RST_SOFT_958_FAST);
fifo_spdif_dcu_enable(component, true);
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_STOP:
+ snd_soc_component_write(component, AIU_RST_SOFT,
+ AIU_RST_SOFT_958_FAST);
fifo_spdif_dcu_enable(component, false);
break;
default:
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 075/602] ASoC: amd: ps: fix wrong ACP version string in pci_request_regions()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (73 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 074/602] ASoC: meson: aiu: fifo-spdif: soft reset the S/PDIF datapath on start/stop Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 076/602] ASoC: cs42l43: Correct report for forced microphone jack Greg Kroah-Hartman
` (530 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Vijendar Mukunda,
Mario Limonciello (AMD), Mark Brown, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
[ Upstream commit f7697ecf6eab9d4887dd731038b3dc405c7e755e ]
The driver handles ACP6.3/7.0/7.1/7.2 platforms but the region was
claimed with the stale name "AMD ACP6.2 audio" left over from the
original ACP6.2 driver. Correct it to "AMD ACP6.3 audio".
Fixes: 95e43a170bb1 ("ASoC: amd: add Pink Sardine ACP PCI driver")
Signed-off-by: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
Link: https://patch.msgid.link/20260707060130.2514138-3-Vijendar.Mukunda@amd.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
sound/soc/amd/ps/pci-ps.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c
index aec3150ecf5812..eb4b552c942417 100644
--- a/sound/soc/amd/ps/pci-ps.c
+++ b/sound/soc/amd/ps/pci-ps.c
@@ -570,7 +570,7 @@ static int snd_acp63_probe(struct pci_dev *pci,
return -ENODEV;
}
- ret = pci_request_regions(pci, "AMD ACP6.2 audio");
+ ret = pci_request_regions(pci, "AMD ACP6.3 audio");
if (ret < 0) {
dev_err(&pci->dev, "pci_request_regions failed\n");
goto disable_pci;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 076/602] ASoC: cs42l43: Correct report for forced microphone jack
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (74 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 075/602] ASoC: amd: ps: fix wrong ACP version string in pci_request_regions() Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 077/602] ASoC: tas2562: fix deprecated shut-down GPIO always cleared after lookup Greg Kroah-Hartman
` (529 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Charles Keepax, Mark Brown,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Charles Keepax <ckeepax@opensource.cirrus.com>
[ Upstream commit f74e6e15485b68b92b2807071e822db6309b7e38 ]
Currently if the jack is forced to the microphone mode, it will report
as line in. Correct the report to microphone.
Fixes: fc918cbe874e ("ASoC: cs42l43: Add support for the cs42l43")
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Link: https://patch.msgid.link/20260708103430.1395207-1-ckeepax@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
sound/soc/codecs/cs42l43-jack.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/sound/soc/codecs/cs42l43-jack.c b/sound/soc/codecs/cs42l43-jack.c
index 3a61f222d85fee..57626db1140a2c 100644
--- a/sound/soc/codecs/cs42l43-jack.c
+++ b/sound/soc/codecs/cs42l43-jack.c
@@ -311,6 +311,7 @@ irqreturn_t cs42l43_bias_detect_clamp(int irq, void *data)
#define CS42L43_JACK_ABSENT 0x0
#define CS42L43_JACK_OPTICAL (SND_JACK_MECHANICAL | SND_JACK_AVOUT)
+#define CS42L43_JACK_MICROPHONE (SND_JACK_MECHANICAL | SND_JACK_MICROPHONE)
#define CS42L43_JACK_HEADPHONE (SND_JACK_MECHANICAL | SND_JACK_HEADPHONE)
#define CS42L43_JACK_HEADSET (SND_JACK_MECHANICAL | SND_JACK_HEADSET)
#define CS42L43_JACK_LINEOUT (SND_JACK_MECHANICAL | SND_JACK_LINEOUT)
@@ -879,7 +880,7 @@ static const struct cs42l43_jack_override_mode {
.hsdet_mode = CS42L43_JACK_3_POLE_SWITCHES,
.mic_ctrl = (0x3 << CS42L43_JACK_STEREO_CONFIG_SHIFT) |
CS42L43_HS1_BIAS_EN_MASK | CS42L43_HS2_BIAS_EN_MASK,
- .report = CS42L43_JACK_LINEIN,
+ .report = CS42L43_JACK_MICROPHONE,
},
[CS42L43_JACK_RAW_OPTICAL] = {
.hsdet_mode = CS42L43_JACK_3_POLE_SWITCHES,
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 077/602] ASoC: tas2562: fix deprecated shut-down GPIO always cleared after lookup
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (75 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 076/602] ASoC: cs42l43: Correct report for forced microphone jack Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 078/602] firmware: arm_scmi: Rate-limit queue-full warnings in IRQ context Greg Kroah-Hartman
` (528 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Uday Khare, Mark Brown, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uday Khare <udaykhare77@gmail.com>
[ Upstream commit 3238c634725afbb2a137fdda762208510828f71d ]
In tas2562_parse_dt(), the fallback lookup for the deprecated
"shut-down" GPIO property is broken due to a missing pair of braces.
The code intends to reset sdz_gpio to NULL only when the lookup
returns an error that is not -EPROBE_DEFER (so the driver gracefully
continues without a GPIO). However, without braces the statement:
tas2562->sdz_gpio = NULL;
falls outside the IS_ERR() check and is executed unconditionally
for every path through the if block, including a successful GPIO
lookup.
This means any device using the deprecated 'shut-down' DT property
will always have sdz_gpio == NULL after probe, making the GPIO
completely non-functional.
Fix this by adding the missing braces to scope the NULL assignment
inside the IS_ERR() branch, matching the pattern already used for
the primary 'shutdown' GPIO lookup above.
Fixes: f78a97003b8b ("ASoC: tas2562: Update shutdown GPIO property")
Signed-off-by: Uday Khare <udaykhare77@gmail.com>
Link: https://patch.msgid.link/20260706153109.10953-1-udaykhare77@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
sound/soc/codecs/tas2562.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/sound/soc/codecs/tas2562.c b/sound/soc/codecs/tas2562.c
index 54561ae598b87a..7daa9e9e0f60e9 100644
--- a/sound/soc/codecs/tas2562.c
+++ b/sound/soc/codecs/tas2562.c
@@ -683,11 +683,12 @@ static int tas2562_parse_dt(struct tas2562_data *tas2562)
if (tas2562->sdz_gpio == NULL) {
tas2562->sdz_gpio = devm_gpiod_get_optional(dev, "shut-down",
GPIOD_OUT_HIGH);
- if (IS_ERR(tas2562->sdz_gpio))
+ if (IS_ERR(tas2562->sdz_gpio)) {
if (PTR_ERR(tas2562->sdz_gpio) == -EPROBE_DEFER)
return -EPROBE_DEFER;
- tas2562->sdz_gpio = NULL;
+ tas2562->sdz_gpio = NULL;
+ }
}
if (tas2562->model_id == TAS2110)
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 078/602] firmware: arm_scmi: Rate-limit queue-full warnings in IRQ context
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (76 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 077/602] ASoC: tas2562: fix deprecated shut-down GPIO always cleared after lookup Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 079/602] cpufreq: Make cpufreq_update_pressure() fall back to cpuinfo.max_freq Greg Kroah-Hartman
` (527 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Pushpendra Singh, Sudeep Holla,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pushpendra Singh <pushpendra.singh@oss.qualcomm.com>
[ Upstream commit a4447c0693830d5ecadd6e755cb7fdc55d86aacc ]
The scmi_notify() function is called from interrupt context to queue
received notification events onto a per-protocol kfifo. When the kfifo
is full, it logs a warning via dev_warn() for every dropped event.
Under conditions where the platform sends a burst of SCMI notifications
faster than the deferred worker can drain the queue, this results in a
flood of dev_warn() calls from IRQ context. Each call acquires the
console lock and may execute blocking console writes, causing the CPU
to be held in interrupt context for an extended period and leading to
observable system stalls.
Fix this by switching to dev_warn_ratelimited() to limit the frequency
of log messages when the notification queue is full. This reduces
console overhead in interrupt context and prevents CPU stalls caused by
excessive logging, while still preserving diagnostic visibility.
Fixes: bd31b249692e ("firmware: arm_scmi: Add notification dispatch and delivery")
Signed-off-by: Pushpendra Singh <pushpendra.singh@oss.qualcomm.com>
Link: https://patch.msgid.link/20260708072339.3021140-1-pushpendra.singh@oss.qualcomm.com
Signed-off-by: Sudeep Holla <sudeep.holla@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/firmware/arm_scmi/notify.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/firmware/arm_scmi/notify.c b/drivers/firmware/arm_scmi/notify.c
index e160ecb22948fc..f042fb8a050265 100644
--- a/drivers/firmware/arm_scmi/notify.c
+++ b/drivers/firmware/arm_scmi/notify.c
@@ -596,9 +596,9 @@ int scmi_notify(const struct scmi_handle *handle, u8 proto_id, u8 evt_id,
return -EINVAL;
}
if (kfifo_avail(&r_evt->proto->equeue.kfifo) < sizeof(eh) + len) {
- dev_warn(handle->dev,
- "queue full, dropping proto_id:%d evt_id:%d ts:%lld\n",
- proto_id, evt_id, ktime_to_ns(ts));
+ dev_warn_ratelimited(handle->dev,
+ "queue full, dropping proto_id:%d evt_id:%d ts:%lld\n",
+ proto_id, evt_id, ktime_to_ns(ts));
return -ENOMEM;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 079/602] cpufreq: Make cpufreq_update_pressure() fall back to cpuinfo.max_freq
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (77 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 078/602] firmware: arm_scmi: Rate-limit queue-full warnings in IRQ context Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 080/602] ppp: defer channel free to an RCU grace period to fix pppol2tp RX UAF Greg Kroah-Hartman
` (526 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Rafael J. Wysocki, Viresh Kumar,
Zhongqiu Han, Vincent Guittot, Sasha Levin, Ricardo Neri
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
[ Upstream commit d2d5c129d07ea8eb91cd8a8633b5774116c4d171 ]
If arch_scale_freq_ref() is not defined for a given arch (like x86, for
example), cpufreq_update_pressure() will always set cpufreq_pressure to
zero for all CPUs in the system, which is generally problematic on
systems with asymmetric capacity [1].
However, in the absence of arch_scale_freq_ref(), it is reasonable
to assume that cpuinfo.max_freq is the maximum sustainable frequency
for the given cpufreq policy. Moreover, there are cases in which
arch_scale_freq_ref() would need to be defined to return essentially
the cpuinfo.max_freq value anyway (for example, intel_pstate on
hybrid platforms).
For the above reasons, update cpufreq_update_pressure() to fall back to
using cpuinfo.max_freq as the reference frequency if zero is returned by
arch_scale_freq_ref().
Fixes: 75d659317bb1 ("cpufreq: Add a cpufreq pressure feedback for the scheduler")
Link: https://lore.kernel.org/lkml/CAKfTPtBuRLfYNnR4w--cFZYZy-R8gaPEgVwCcaMmbCcJ2H-muQ@mail.gmail.com/ [1]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Reviewed-by: Zhongqiu Han <zhongqiu.han@oss.qualcomm.com>
Tested-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com> # cluster scheduling
Acked-by: Vincent Guittot <vincent.guittot@linaro.org>
Link: https://patch.msgid.link/5086499.GXAFRqVoOG@rafael.j.wysocki
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/cpufreq/cpufreq.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 17df96564ad6f2..2c86539eb4bc38 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -2601,6 +2601,9 @@ static void cpufreq_update_pressure(struct cpufreq_policy *policy)
cpu = cpumask_first(policy->related_cpus);
max_freq = arch_scale_freq_ref(cpu);
+ if (!max_freq)
+ max_freq = policy->cpuinfo.max_freq;
+
capped_freq = policy->max;
/*
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 080/602] ppp: defer channel free to an RCU grace period to fix pppol2tp RX UAF
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (78 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 079/602] cpufreq: Make cpufreq_update_pressure() fall back to cpuinfo.max_freq Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 081/602] ipv4: fib: free fib_alias with kfree_rcu() on insert error path Greg Kroah-Hartman
` (525 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Norbert Szetei, Qingfang Deng,
Paolo Abeni, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Norbert Szetei <norbert@doyensec.com>
[ Upstream commit ec4215683e47424c9c4762fd3c60f552a3119142 ]
pppol2tp_recv() runs in the L2TP UDP-encap softirq RX path:
l2tp_udp_encap_recv() -> l2tp_recv_common() -> pppol2tp_recv()
-> ppp_input(&po->chan)
It runs under rcu_read_lock() holding only an l2tp_session reference and
takes NO reference on the internal PPP channel (struct channel,
chan->ppp) that ppp_input() dereferences.
The pppox socket is SOCK_RCU_FREE, so 'po' and the embedded ppp_channel
are RCU-safe. But the internal struct channel is a separate allocation
that ppp_release_channel() frees with a plain kfree():
close(data socket) -> pppol2tp_release() -> pppox_unbind_sock()
-> ppp_unregister_channel() -> ppp_release_channel() -> kfree(pch)
For a channel that is bound (PPPIOCGCHAN) but not attached to a ppp unit
(no PPPIOCCONNECT, pch->ppp == NULL) and not bridged, teardown skips
both ppp_disconnect_channel()'s synchronize_net() and
ppp_unbridge_channels()'s synchronize_rcu(), so the kfree() has no grace
period. rcu_read_lock() in pppol2tp_recv() does not protect against a
plain kfree(), so an in-flight ppp_input() on one CPU can dereference
the channel just freed by close() on another CPU.
The bug is reachable by an unprivileged user.
Defer the channel free to an RCU callback via call_rcu() so the grace
period fences any in-flight ppp_input(). The disconnect and unbridge
teardown paths already fence with synchronize_net()/synchronize_rcu();
call_rcu() does the same here without stalling the close() path.
Fixes: ee40fb2e1eb5 ("l2tp: protect sock pointer of struct pppol2tp_session with RCU")
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Norbert Szetei <norbert@doyensec.com>
Reviewed-by: Qingfang Deng <qingfang.deng@linux.dev>
Link: https://patch.msgid.link/E793FCF2-58DE-4387-A983-C7B4BC3158BD@doyensec.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ppp/ppp_generic.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index c70994c6a265e3..9f787adef3eb38 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -192,6 +192,7 @@ struct channel {
struct list_head clist; /* link in list of channels per unit */
rwlock_t upl; /* protects `ppp' and 'bridge' */
struct channel __rcu *bridge; /* "bridged" ppp channel */
+ struct rcu_head rcu; /* for RCU-deferred free of the channel */
#ifdef CONFIG_PPP_MULTILINK
u8 avail; /* flag used in multilink stuff */
u8 had_frag; /* >= 1 fragments have been sent */
@@ -3555,6 +3556,18 @@ ppp_disconnect_channel(struct channel *pch)
return err;
}
+/* Purge after the grace period: a late ppp_input() may still queue an
+ * skb on pch->file.rq before the last RCU reader drains.
+ */
+static void ppp_release_channel_free(struct rcu_head *rcu)
+{
+ struct channel *pch = container_of(rcu, struct channel, rcu);
+
+ skb_queue_purge(&pch->file.xq);
+ skb_queue_purge(&pch->file.rq);
+ kfree(pch);
+}
+
/*
* Free up the resources used by a ppp channel.
*/
@@ -3570,9 +3583,7 @@ static void ppp_destroy_channel(struct channel *pch)
pr_err("ppp: destroying undead channel %p !\n", pch);
return;
}
- skb_queue_purge(&pch->file.xq);
- skb_queue_purge(&pch->file.rq);
- kfree(pch);
+ call_rcu(&pch->rcu, ppp_release_channel_free);
}
static void __exit ppp_cleanup(void)
@@ -3585,6 +3596,7 @@ static void __exit ppp_cleanup(void)
device_destroy(&ppp_class, MKDEV(PPP_MAJOR, 0));
class_unregister(&ppp_class);
unregister_pernet_device(&ppp_net_ops);
+ rcu_barrier(); /* wait for RCU callbacks before module unload */
}
/*
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 081/602] ipv4: fib: free fib_alias with kfree_rcu() on insert error path
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (79 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 080/602] ppp: defer channel free to an RCU grace period to fix pppol2tp RX UAF Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 082/602] net/iucv: take a reference on the socket found in afiucv_hs_rcv() Greg Kroah-Hartman
` (524 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Xiang Mei, Weiming Shi, Ido Schimmel,
Paolo Abeni, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiming Shi <bestswngs@gmail.com>
[ Upstream commit f2f152e94a67bc746afaf05a1b2702c195553112 ]
fib_table_insert() publishes new_fa into the leaf's fa_list with
fib_insert_alias() before calling the fib entry notifiers. When a
notifier fails, the error path removes new_fa with fib_remove_alias()
(hlist_del_rcu) and frees it right away with kmem_cache_free().
fib_table_lookup() walks that list under rcu_read_lock() only, so a
concurrent lookup that already reached new_fa keeps reading it after the
free:
BUG: KASAN: slab-use-after-free in fib_table_lookup (net/ipv4/fib_trie.c:1601)
Read of size 1 at addr ffff88810676d4eb by task exploit/297
Call Trace:
fib_table_lookup (net/ipv4/fib_trie.c:1601)
ip_route_output_key_hash_rcu (net/ipv4/route.c:2814)
ip_route_output_key_hash (net/ipv4/route.c:2705)
__ip4_datagram_connect (net/ipv4/datagram.c:49)
udp_connect (net/ipv4/udp.c:2144)
__sys_connect (net/socket.c:2167)
__x64_sys_connect (net/socket.c:2173)
do_syscall_64
entry_SYSCALL_64_after_hwframe
which belongs to the cache ip_fib_alias of size 56
Triggering the error path needs CAP_NET_ADMIN and a registered fib
notifier that can reject a route; a netdevsim device whose IPv4 FIB
resource is exhausted is enough.
Free new_fa with alias_free_mem_rcu(), as fib_table_delete() already
does for a fib_alias removed from the trie.
Fixes: a6c76c17df02 ("ipv4: Notify route after insertion to the routing table")
Reported-by: Xiang Mei <xmei5@asu.edu>
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Weiming Shi <bestswngs@gmail.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20260704171421.1786806-1-bestswngs@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/ipv4/fib_trie.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index ee47b67a087034..3d2df1d435ae10 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1391,7 +1391,7 @@ int fib_table_insert(struct net *net, struct fib_table *tb,
out_remove_new_fa:
fib_remove_alias(t, tp, l, new_fa);
out_free_new_fa:
- kmem_cache_free(fn_alias_kmem, new_fa);
+ alias_free_mem_rcu(new_fa);
out:
fib_release_info(fi);
err:
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 082/602] net/iucv: take a reference on the socket found in afiucv_hs_rcv()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (80 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 081/602] ipv4: fib: free fib_alias with kfree_rcu() on insert error path Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 083/602] udmabuf: Ensure to perform cache synchronisation in begin_cpu_udmabuf() Greg Kroah-Hartman
` (523 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Bryam Vargas, Hidayath Khan,
Paolo Abeni, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <hexlabsecurity@proton.me>
[ Upstream commit 4fa349156043dc119721d067329714179f501749 ]
afiucv_hs_rcv() looks up the destination socket under iucv_sk_list.lock,
drops the lock, and then passes the socket to the afiucv_hs_callback_*()
handlers without holding a reference. AF_IUCV sockets are not
RCU-protected and are freed synchronously by iucv_sock_kill() ->
sock_put(), so a concurrent close can free the socket in the window
between read_unlock() and the handler, which then dereferences freed
memory (for example sk->sk_data_ready() in afiucv_hs_callback_syn()).
Take a reference with sock_hold() while the socket is still on the list
and release it with sock_put() once the handler has run.
Fixes: 3881ac441f64 ("af_iucv: add HiperSockets transport")
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
Reviewed-by: Hidayath Khan <hidayath@linux.ibm.com>
Link: https://patch.msgid.link/20260705-b4-disp-fc79c0dc-v1-1-d2cdcb57afa9@proton.me
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/iucv/af_iucv.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index 1a0b41fcea8131..bb54e23397e8c6 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -2088,6 +2088,8 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev,
}
}
}
+ if (sk)
+ sock_hold(sk);
read_unlock(&iucv_sk_list.lock);
if (!iucv)
sk = NULL;
@@ -2137,6 +2139,8 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev,
kfree_skb(skb);
}
+ if (sk)
+ sock_put(sk);
return err;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 083/602] udmabuf: Ensure to perform cache synchronisation in begin_cpu_udmabuf()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (81 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 082/602] net/iucv: take a reference on the socket found in afiucv_hs_rcv() Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 084/602] scsi: core: wake eh reliably when using scsi_schedule_eh Greg Kroah-Hartman
` (522 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Robert Mader, Mikhail Gavrilov,
Vivek Kasireddy, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Robert Mader <robert.mader@collabora.com>
[ Upstream commit 1d0e25c1ddf2063c499264fb2ba0fa6a3e4f8a00 ]
The message of commit 504e2b4ab97a ("dma-buf/udmabuf: skip redundant cpu sync to
fix cacheline EEXIST warning") says:
> The CPU sync at map/unmap time is also redundant for udmabuf:
> begin_cpu_udmabuf() and end_cpu_udmabuf() already perform explicit
> cache synchronization via dma_sync_sgtable_for_cpu/device() when CPU
> access is requested through the dma-buf interface.
This, however, does not apply to the first time begin_cpu_udmabuf() is
called on an udmabuf, in which case the implementation previously relied on
get_sg_table() to perform the cache synchronisation.
Ensure to call dma_sync_sgtable_for_cpu() in that case as well.
Fixes: 504e2b4ab97a ("dma-buf/udmabuf: skip redundant cpu sync to fix cacheline EEXIST warning")
Signed-off-by: Robert Mader <robert.mader@collabora.com>
Reviewed-by: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
Link: https://patch.msgid.link/20260627105725.9083-1-robert.mader@collabora.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/dma-buf/udmabuf.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c
index 5c92834f3fc86d..b81fd91e30e777 100644
--- a/drivers/dma-buf/udmabuf.c
+++ b/drivers/dma-buf/udmabuf.c
@@ -207,21 +207,22 @@ static int begin_cpu_udmabuf(struct dma_buf *buf,
{
struct udmabuf *ubuf = buf->priv;
struct device *dev = ubuf->device->this_device;
- int ret = 0;
if (!ubuf->sg) {
ubuf->sg = get_sg_table(dev, buf, direction);
if (IS_ERR(ubuf->sg)) {
+ int ret;
+
ret = PTR_ERR(ubuf->sg);
ubuf->sg = NULL;
+ return ret;
} else {
ubuf->sg_dir = direction;
}
- } else {
- dma_sync_sgtable_for_cpu(dev, ubuf->sg, direction);
}
- return ret;
+ dma_sync_sgtable_for_cpu(dev, ubuf->sg, direction);
+ return 0;
}
static int end_cpu_udmabuf(struct dma_buf *buf,
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 084/602] scsi: core: wake eh reliably when using scsi_schedule_eh
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (82 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 083/602] udmabuf: Ensure to perform cache synchronisation in begin_cpu_udmabuf() Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 085/602] ata: sata_dwc_460ex: enable SATA interrupts only after IRQ handler is registered Greg Kroah-Hartman
` (521 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Jeffery, Martin K. Petersen,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Jeffery <djeffery@redhat.com>
[ Upstream commit dccf3b1798b70f94e958b3d00b83010399e6fb05 ]
Drivers which use the scsi_schedule_eh function to run the error handler
currently risk the error handler thread never waking once all commands are
timed out or inactive. There is no enforced memory order between setting
the host into error recovery state and counting busy commands. This can
result in a race with scsi_dec_host_busy where neither CPU sees both
conditions of all commands inactive and the host error state to request
waking the error handler.
To fix this, run the scsi_schedule_eh's scsi_eh_wakeup from a new work item
which will use rcu to ensure scsi_schedule_eh's call to scsi_host_busy will
occur after the error state is globally visible and will be seen by any
current scsi_dec_host_busy callers.
Fixes: 6eb045e092ef ("scsi: core: avoid host-wide host_busy counter for scsi_mq")
Signed-off-by: David Jeffery <djeffery@redhat.com>
Link: https://patch.msgid.link/20260615174630.11492-1-djeffery@redhat.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/scsi/hosts.c | 2 ++
drivers/scsi/scsi_error.c | 22 +++++++++++++++++++++-
drivers/scsi/scsi_priv.h | 1 +
include/scsi/scsi_host.h | 3 +++
4 files changed, 27 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 5cf13d019a15e9..e617b98ce84cf2 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -343,6 +343,7 @@ static void scsi_host_dev_release(struct device *dev)
/* Wait for functions invoked through call_rcu(&scmd->rcu, ...) */
rcu_barrier();
+ cancel_work_sync(&shost->eh_work);
if (shost->tmf_work_q)
destroy_workqueue(shost->tmf_work_q);
if (shost->ehandler)
@@ -408,6 +409,7 @@ struct Scsi_Host *scsi_host_alloc(const struct scsi_host_template *sht, int priv
INIT_LIST_HEAD(&shost->starved_list);
init_waitqueue_head(&shost->host_wait);
mutex_init(&shost->scan_mutex);
+ INIT_WORK(&shost->eh_work, scsi_rcu_eh_wakeup);
index = ida_alloc(&host_index_ida, GFP_KERNEL);
if (index < 0) {
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 9a89a94784cd0c..03fadefa1cee8e 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -73,6 +73,26 @@ void scsi_eh_wakeup(struct Scsi_Host *shost, unsigned int busy)
}
}
+void scsi_rcu_eh_wakeup(struct work_struct *work)
+{
+ struct Scsi_Host *shost = container_of(work, struct Scsi_Host, eh_work);
+ unsigned long flags;
+ unsigned int busy;
+
+ /*
+ * Ensure any running scsi_dec_host_busy has completed its rcu section
+ * so changes to host state and host_eh_scheduled are visible to all
+ * future calls of scsi_dec_host_busy
+ */
+ synchronize_rcu();
+
+ busy = scsi_host_busy(shost);
+
+ spin_lock_irqsave(shost->host_lock, flags);
+ scsi_eh_wakeup(shost, busy);
+ spin_unlock_irqrestore(shost->host_lock, flags);
+}
+
/**
* scsi_schedule_eh - schedule EH for SCSI host
* @shost: SCSI host to invoke error handling on.
@@ -88,7 +108,7 @@ void scsi_schedule_eh(struct Scsi_Host *shost)
if (scsi_host_set_state(shost, SHOST_RECOVERY) == 0 ||
scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY) == 0) {
shost->host_eh_scheduled++;
- scsi_eh_wakeup(shost, scsi_host_busy(shost));
+ queue_work(shost->tmf_work_q, &shost->eh_work);
}
spin_unlock_irqrestore(shost->host_lock, flags);
diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h
index 9fc397a9ce7a4f..7238d53883be76 100644
--- a/drivers/scsi/scsi_priv.h
+++ b/drivers/scsi/scsi_priv.h
@@ -93,6 +93,7 @@ extern enum blk_eh_timer_return scsi_timeout(struct request *req);
extern int scsi_error_handler(void *host);
extern enum scsi_disposition scsi_decide_disposition(struct scsi_cmnd *cmd);
extern void scsi_eh_wakeup(struct Scsi_Host *shost, unsigned int busy);
+extern void scsi_rcu_eh_wakeup(struct work_struct *work);
extern void scsi_eh_scmd_add(struct scsi_cmnd *);
void scsi_eh_ready_devs(struct Scsi_Host *shost,
struct list_head *work_q,
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 2b4ab0369ffbe9..990747f803feff 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -718,6 +718,9 @@ struct Scsi_Host {
*/
struct device *dma_dev;
+ /* Used for an rcu-synchronizing eh wakeup */
+ struct work_struct eh_work;
+
/* Delay for runtime autosuspend */
int rpm_autosuspend_delay;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 085/602] ata: sata_dwc_460ex: enable SATA interrupts only after IRQ handler is registered
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (83 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 084/602] scsi: core: wake eh reliably when using scsi_schedule_eh Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 086/602] ata: sata_dwc_460ex: use platform_get_irq() Greg Kroah-Hartman
` (520 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Rosen Penev, Damien Le Moal,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rosen Penev <rosenp@gmail.com>
[ Upstream commit 4bbc16a353a98023e5ddfca7c1fc0e49971cf4d0 ]
sata_dwc_enable_interrupts() is called before platform_get_irq() and
ata_host_activate(), leaving the SATA controller's interrupt mask
enabled without a registered handler. If a later step fails (irq
request, phy init, etc.) or if the controller asserts an interrupt
during probe, the irq line may fire with no handler, causing a
spurious interrupt storm.
Move sata_dwc_enable_interrupts() after ata_host_activate() so that
interrupts are only unmasked once the handler is registered and the
core is fully initialized.
Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex")
Assisted-by: opencode:big-pickle
Signed-off-by: Rosen Penev <rosenp@gmail.com>
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/ata/sata_dwc_460ex.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 52f5168e4db542..16c1deef389d10 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -1168,9 +1168,6 @@ static int sata_dwc_probe(struct platform_device *ofdev)
/* Save dev for later use in dev_xxx() routines */
hsdev->dev = dev;
- /* Enable SATA Interrupts */
- sata_dwc_enable_interrupts(hsdev);
-
/* Get SATA interrupt number */
irq = irq_of_parse_and_map(np, 0);
if (!irq) {
@@ -1203,6 +1200,8 @@ static int sata_dwc_probe(struct platform_device *ofdev)
if (err)
dev_err(dev, "failed to activate host");
+ /* Enable SATA Interrupts */
+ sata_dwc_enable_interrupts(hsdev);
return 0;
error_out:
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 086/602] ata: sata_dwc_460ex: use platform_get_irq()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (84 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 085/602] ata: sata_dwc_460ex: enable SATA interrupts only after IRQ handler is registered Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 087/602] ata: sata_dwc_460ex: fix clear_interrupt_bit() clearing all pending interrupts Greg Kroah-Hartman
` (519 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Rosen Penev, Damien Le Moal,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rosen Penev <rosenp@gmail.com>
[ Upstream commit a4af122106f73ea510bb35a9ea1dedd980fc0db7 ]
Replace irq_of_parse_and_map() with platform_get_irq() in both
sata_dwc_dma_init_old() and sata_dwc_probe(). This is the preferred
way to obtain IRQs for platform devices and provides better error
reporting. Remove the now-unnecessary #include <linux/of_irq.h>.
irq_of_parse_and_map() requires irq_dispose_mapping(), which is missing.
Also fix unused variable when CONFIG_SATA_DWC_OLD_DMA is disabled.
Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex")
Assisted-by: opencode:big-pickle
Signed-off-by: Rosen Penev <rosenp@gmail.com>
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/ata/sata_dwc_460ex.c | 21 +++++++--------------
1 file changed, 7 insertions(+), 14 deletions(-)
diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 16c1deef389d10..97b934fa116e26 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -19,7 +19,6 @@
#include <linux/device.h>
#include <linux/dmaengine.h>
#include <linux/of.h>
-#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/phy/phy.h>
#include <linux/libata.h>
@@ -226,7 +225,6 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev,
struct sata_dwc_device *hsdev)
{
struct device *dev = &pdev->dev;
- struct device_node *np = dev->of_node;
hsdev->dma = devm_kzalloc(dev, sizeof(*hsdev->dma), GFP_KERNEL);
if (!hsdev->dma)
@@ -236,11 +234,9 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev,
hsdev->dma->id = pdev->id;
/* Get SATA DMA interrupt number */
- hsdev->dma->irq = irq_of_parse_and_map(np, 1);
- if (!hsdev->dma->irq) {
- dev_err(dev, "no SATA DMA irq\n");
- return -ENODEV;
- }
+ hsdev->dma->irq = platform_get_irq(pdev, 1);
+ if (hsdev->dma->irq < 0)
+ return hsdev->dma->irq;
/* Get physical SATA DMA register base address */
hsdev->dma->regs = devm_platform_ioremap_resource(pdev, 1);
@@ -1125,7 +1121,6 @@ static const struct ata_port_info sata_dwc_port_info[] = {
static int sata_dwc_probe(struct platform_device *ofdev)
{
struct device *dev = &ofdev->dev;
- struct device_node *np = dev->of_node;
struct sata_dwc_device *hsdev;
u32 idr, versionr;
char *ver = (char *)&versionr;
@@ -1169,14 +1164,12 @@ static int sata_dwc_probe(struct platform_device *ofdev)
hsdev->dev = dev;
/* Get SATA interrupt number */
- irq = irq_of_parse_and_map(np, 0);
- if (!irq) {
- dev_err(dev, "no SATA DMA irq\n");
- return -ENODEV;
- }
+ irq = platform_get_irq(ofdev, 0);
+ if (irq < 0)
+ return irq;
#ifdef CONFIG_SATA_DWC_OLD_DMA
- if (!of_property_present(np, "dmas")) {
+ if (!of_property_present(dev->of_node, "dmas")) {
err = sata_dwc_dma_init_old(ofdev, hsdev);
if (err)
return err;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 087/602] ata: sata_dwc_460ex: fix clear_interrupt_bit() clearing all pending interrupts
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (85 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 086/602] ata: sata_dwc_460ex: use platform_get_irq() Greg Kroah-Hartman
@ 2026-07-30 14:07 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 088/602] ata: sata_dwc_460ex: fix infinite loop in NCQ tag completion bit-scanning Greg Kroah-Hartman
` (518 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:07 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Rosen Penev, Damien Le Moal,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rosen Penev <rosenp@gmail.com>
[ Upstream commit 66c4e310ad71f41e41736d33dd8a1fb5eaaec7f3 ]
clear_interrupt_bit() ignores the bit argument and performs a
read-write-back of the entire INTPR register. If INTPR uses standard
Write-1-to-Clear semantics, this clears every pending interrupt bit,
not just the intended one. Coalesced interrupts (e.g. DMAT + NEWFP)
would be cleared together, silently losing the second event.
Write only the specific bit to clear so that other pending interrupts
are preserved.
Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex")
Assisted-by: opencode:big-pickle
Signed-off-by: Rosen Penev <rosenp@gmail.com>
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/ata/sata_dwc_460ex.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 97b934fa116e26..74514608a7fada 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -394,8 +394,7 @@ static void clear_serror(struct ata_port *ap)
static void clear_interrupt_bit(struct sata_dwc_device *hsdev, u32 bit)
{
- sata_dwc_writel(&hsdev->sata_dwc_regs->intpr,
- sata_dwc_readl(&hsdev->sata_dwc_regs->intpr));
+ sata_dwc_writel(&hsdev->sata_dwc_regs->intpr, bit);
}
static u32 qcmd_tag_to_mask(u8 tag)
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 088/602] ata: sata_dwc_460ex: fix infinite loop in NCQ tag completion bit-scanning
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (86 preceding siblings ...)
2026-07-30 14:07 ` [PATCH 6.12 087/602] ata: sata_dwc_460ex: fix clear_interrupt_bit() clearing all pending interrupts Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 089/602] accel/ivpu: Fix wrong register read in LNL failure diagnostics Greg Kroah-Hartman
` (517 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Rosen Penev, Damien Le Moal,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rosen Penev <rosenp@gmail.com>
[ Upstream commit c2130f6553f4a5cbdc259de069600117a995f197 ]
The hand-rolled bit-scanning loop in the NCQ completion path has an
infinite loop bug. When tag_mask has only high bits set (e.g.
0x80000000), the inner while loop left-shifts tag_mask until it
overflows to 0. At that point !(0 & 1) is always true and 0 <<= 1
stays 0, causing an infinite loop in hardirq context with a spinlock
held.
Replace the open-coded bit-scanning with __ffs() which correctly
finds the least significant set bit and is bounded by the width of
the argument.
Fixes: 62936009f35a ("[libata] Add 460EX on-chip SATA driver, sata_dwc_460ex")
Assisted-by: opencode:big-pickle
Signed-off-by: Rosen Penev <rosenp@gmail.com>
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/ata/sata_dwc_460ex.c | 9 ++-------
1 file changed, 2 insertions(+), 7 deletions(-)
diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index 74514608a7fada..66db8dd8ec2670 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -607,14 +607,9 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance)
status = ap->ops->sff_check_status(ap);
dev_dbg(ap->dev, "%s ATA status register=0x%x\n", __func__, status);
- tag = 0;
while (tag_mask) {
- while (!(tag_mask & 0x00000001)) {
- tag++;
- tag_mask <<= 1;
- }
-
- tag_mask &= (~0x00000001);
+ tag = __ffs(tag_mask);
+ tag_mask &= ~(1U << tag);
qc = ata_qc_from_tag(ap, tag);
if (unlikely(!qc)) {
dev_err(ap->dev, "failed to get qc");
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 089/602] accel/ivpu: Fix wrong register read in LNL failure diagnostics
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (87 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 088/602] ata: sata_dwc_460ex: fix infinite loop in NCQ tag completion bit-scanning Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 090/602] ALSA: usb-audio: Skip DSD quirk for Musical Fidelity M6s DAC Greg Kroah-Hartman
` (516 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Andrzej Kacprowski, Karol Wachowski,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Karol Wachowski <karol.wachowski@linux.intel.com>
[ Upstream commit e4159045c2704dfe146f0ccb0445d9d074cd6882 ]
diagnose_failure_lnl() read VPU_HW_BTRS_MTL_INTERRUPT_STAT instead of
VPU_HW_BTRS_LNL_INTERRUPT_STAT, which on LNL and newer parts is a
different register with a different bit layout, so failure diagnostics
decoded the wrong register and reported a bogus error cause.
Read the LNL interrupt status register instead.
Fixes: 8a27ad81f7d3 ("accel/ivpu: Split IP and buttress code")
Reviewed-by: Andrzej Kacprowski <andrzej.kacprowski@linux.intel.com>
Signed-off-by: Karol Wachowski <karol.wachowski@linux.intel.com>
Link: https://patch.msgid.link/20260710101331.1899505-1-karol.wachowski@linux.intel.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/accel/ivpu/ivpu_hw_btrs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/accel/ivpu/ivpu_hw_btrs.c b/drivers/accel/ivpu/ivpu_hw_btrs.c
index 4af1b164d85a73..c9e1922aff5e84 100644
--- a/drivers/accel/ivpu/ivpu_hw_btrs.c
+++ b/drivers/accel/ivpu/ivpu_hw_btrs.c
@@ -852,7 +852,7 @@ static void diagnose_failure_mtl(struct ivpu_device *vdev)
static void diagnose_failure_lnl(struct ivpu_device *vdev)
{
- u32 reg = REGB_RD32(VPU_HW_BTRS_MTL_INTERRUPT_STAT) & BTRS_LNL_IRQ_MASK;
+ u32 reg = REGB_RD32(VPU_HW_BTRS_LNL_INTERRUPT_STAT) & BTRS_LNL_IRQ_MASK;
if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, ATS_ERR, reg)) {
ivpu_err(vdev, "ATS_ERR_LOG1 0x%08x ATS_ERR_LOG2 0x%08x\n",
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 090/602] ALSA: usb-audio: Skip DSD quirk for Musical Fidelity M6s DAC
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (88 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 089/602] accel/ivpu: Fix wrong register read in LNL failure diagnostics Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 091/602] Bluetooth: qca: fix NVM tag length underflow in TLV parser Greg Kroah-Hartman
` (515 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Salvador Blaya, Takashi Iwai,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <tiwai@suse.de>
[ Upstream commit 93b47e66cc6d6c6382d44b44f5e7f6fc3a7b38c3 ]
Salvador reported that the recent fix for applying the DSD quirk to
Musical Fidelity devices broke for his M6s DAC model (2772:0502).
Although this is basically a firmware bug, the model in question is
fairly old, and no further firmware update can be expected, so it'd be
better to address in the driver side.
As an ad hoc workaround, skip the DSD quirk for this device by adding
an empty quirk entry of 2772:0502; this essentially skips the later
DSD quirk entry by the match with the vendor 2772.
Fixes: da3a7efff64e ("ALSA: usb-audio: Update for native DSD support quirks")
Reported-by: Salvador Blaya <tiniebla6@gmail.com>
Closes: https://lore.kernel.org/CAOdyq+qFaqCh=tK_wNnA64hv5pQuA1Y09ANxQ=xK8yR-t4mf9Q@mail.gmail.com
Tested-by: Salvador Blaya <tiniebla6@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/20260709095614.1418838-1-tiwai@suse.de
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
sound/usb/quirks.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 489dd84e20967c..ea2ec3507521ef 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -2369,6 +2369,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_DSD_RAW),
DEVICE_FLG(0x2708, 0x0002, /* Audient iD14 */
QUIRK_FLAG_IGNORE_CTL_ERROR),
+ DEVICE_FLG(0x2772, 0x0502, /* Musical Fidelity M6s DAC */
+ 0), /* for avoiding QUIRK_FLAG_DSD_RAW with vendor match */
DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */
QUIRK_FLAG_GET_SAMPLE_RATE),
DEVICE_FLG(0x2a70, 0x1881, /* OnePlus Technology (Shenzhen) Co., Ltd. BE02T */
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 091/602] Bluetooth: qca: fix NVM tag length underflow in TLV parser
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (89 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 090/602] ALSA: usb-audio: Skip DSD quirk for Musical Fidelity M6s DAC Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 092/602] Bluetooth: MGMT: revalidate LOAD_CONN_PARAM queued update Greg Kroah-Hartman
` (514 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Weiming Shi, Xiang Mei, Johan Hovold,
Bartosz Golaszewski, Luiz Augusto von Dentz, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei <xmei5@asu.edu>
[ Upstream commit c90164ca0f7036942ba088eb7ea8d3f6c2352020 ]
In the TLV_TYPE_NVM branch of qca_tlv_check_data() the tag loop bound is
"while (idx < length - sizeof(struct tlv_type_nvm))". "length" is a signed
int from the firmware TLV header and sizeof(struct tlv_type_nvm) is a
size_t (12), so "length" is converted to size_t and any firmware-supplied
"length" < 12 makes the subtraction wrap to a huge value. The loop body
then reads a 12-byte struct tlv_type_nvm past the end of the short
vmalloc'd firmware buffer (and the EDL_TAG_ID_* handlers can write past it).
Rewrite the bound as "idx + sizeof(struct tlv_type_nvm) <= length"; both
operands are non-negative, so it no longer underflows and a "length" too
small for one record correctly skips the loop.
BUG: KASAN: vmalloc-out-of-bounds in qca_download_firmware.isra.0 (drivers/bluetooth/btqca.c:421)
Read of size 2 at addr ffffc900000e5004 by task kworker/u9:0/52
Workqueue: hci0 hci_power_on
Call Trace:
...
kasan_report (mm/kasan/report.c:595)
qca_download_firmware.isra.0 (drivers/bluetooth/btqca.c:421 drivers/bluetooth/btqca.c:617)
qca_uart_setup (drivers/bluetooth/btqca.c:948)
qca_setup (drivers/bluetooth/hci_qca.c:2029)
hci_uart_setup (drivers/bluetooth/hci_ldisc.c:438)
hci_dev_open_sync (net/bluetooth/hci_sync.c:5227)
hci_power_on (net/bluetooth/hci_core.c:920)
process_one_work (kernel/workqueue.c:3322)
worker_thread (kernel/workqueue.c:3486)
kthread (kernel/kthread.c:436)
ret_from_fork (arch/x86/kernel/process.c:158)
ret_from_fork_asm (arch/x86/entry/entry_64.S:245)
Fixes: 2e4edfa1e2bd ("Bluetooth: qca: add missing firmware sanity checks")
Reported-by: Weiming Shi <bestswngs@gmail.com>
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Xiang Mei <xmei5@asu.edu>
Reported-by: Weiming Shi <bestswngs@gmail.com>
Reviewed-by: Johan Hovold <johan@kernel.org>
Acked-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/bluetooth/btqca.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
index 372427747cd649..083a599eec74db 100644
--- a/drivers/bluetooth/btqca.c
+++ b/drivers/bluetooth/btqca.c
@@ -413,7 +413,7 @@ static int qca_tlv_check_data(struct hci_dev *hdev,
idx = 0;
data = tlv->data;
- while (idx < length - sizeof(struct tlv_type_nvm)) {
+ while (idx + sizeof(struct tlv_type_nvm) <= length) {
tlv_nvm = (struct tlv_type_nvm *)(data + idx);
tag_id = le16_to_cpu(tlv_nvm->tag_id);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 092/602] Bluetooth: MGMT: revalidate LOAD_CONN_PARAM queued update
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (90 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 091/602] Bluetooth: qca: fix NVM tag length underflow in TLV parser Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 093/602] Bluetooth: mgmt: fix locking in unpair_device/disconnect_sync Greg Kroah-Hartman
` (513 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Luiz Augusto von Dentz, Cen Zhang,
Luiz Augusto von Dentz, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cen Zhang <zzzccc427@gmail.com>
[ Upstream commit 2bf282f8f715f5d05d6f4c49ffb3bd241c5e667e ]
MGMT_OP_LOAD_CONN_PARAM queues conn_update_sync() when a single parameter
update changes an existing LE central connection. The queued work currently
stores a borrowed hci_conn_params entry from hdev->le_conn_params. A later
LOAD_CONN_PARAM request can clear disabled parameters and free that entry
before hci_cmd_sync_work() runs the queued callback.
Do not keep the borrowed hci_conn_params pointer in queued work. Queue the
hci_conn instead and hold a reference until the queued callback completes.
When the work runs, revalidate that the connection is still present, look
up the current hci_conn_params entry, and cancel the update if userspace
removed that entry while the work was pending.
Copy the interval values from the current params entry under hdev->lock,
then drop the lock and keep using hci_le_conn_update_sync() to issue the
update.
Validation reproduced this kernel report:
BUG: KASAN: slab-use-after-free in conn_update_sync+0x2a/0xf0 [bluetooth]
Read of size 1 at addr ffff88810c697126 by task kworker/u17:0/377
Workqueue: hci0 hci_cmd_sync_work [bluetooth]
Call Trace:
<TASK>
dump_stack_lvl+0x66/0xa0
print_report+0xce/0x5f0
kasan_report+0xe0/0x110
conn_update_sync+0x2a/0xf0 [bluetooth]
hci_cmd_sync_work+0x187/0x210 [bluetooth]
process_one_work+0x4fd/0xbc0
worker_thread+0x2d8/0x570
kthread+0x1ad/0x1f0
ret_from_fork+0x3c9/0x540
ret_from_fork_asm+0x1a/0x30
Allocated by task 466:
hci_conn_params_add+0xa6/0x240 [bluetooth]
load_conn_param+0x4e1/0x850 [bluetooth]
hci_sock_sendmsg+0x96b/0xf80 [bluetooth]
Freed by task 474:
kfree+0x313/0x590
hci_conn_params_clear_disabled+0x9b/0xc0 [bluetooth]
load_conn_param+0x4bf/0x850 [bluetooth]
hci_sock_sendmsg+0x96b/0xf80 [bluetooth]
Fixes: 0ece498c27d8c ("Bluetooth: MGMT: Make MGMT_OP_LOAD_CONN_PARAM update existing connection")
Suggested-by: Luiz Augusto von Dentz <luiz.dentz@gmail.com>
Assisted-by: Codex:gpt-5.5
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/bluetooth/mgmt.c | 44 +++++++++++++++++++++++++++++++++++---------
1 file changed, 35 insertions(+), 9 deletions(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 6280fcfcdd0c6a..0c09cb5a78e028 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -8024,14 +8024,36 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev,
static int conn_update_sync(struct hci_dev *hdev, void *data)
{
- struct hci_conn_params *params = data;
- struct hci_conn *conn;
+ struct hci_conn *conn = data;
+ struct hci_conn_params *params;
+ struct hci_conn_params local = {};
- conn = hci_conn_hash_lookup_le(hdev, ¶ms->addr, params->addr_type);
- if (!conn)
- return -ECANCELED;
+ hci_dev_lock(hdev);
+
+ if (!hci_conn_valid(hdev, conn) || conn->role != HCI_ROLE_MASTER)
+ goto cancel;
+
+ params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
+ if (!params)
+ goto cancel;
+
+ local.conn_min_interval = params->conn_min_interval;
+ local.conn_max_interval = params->conn_max_interval;
+ local.conn_latency = params->conn_latency;
+ local.supervision_timeout = params->supervision_timeout;
- return hci_le_conn_update_sync(hdev, conn, params);
+ hci_dev_unlock(hdev);
+
+ return hci_le_conn_update_sync(hdev, conn, &local);
+
+cancel:
+ hci_dev_unlock(hdev);
+ return -ECANCELED;
+}
+
+static void conn_update_sync_destroy(struct hci_dev *hdev, void *data, int err)
+{
+ hci_conn_put(data);
}
static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
@@ -8141,9 +8163,13 @@ static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
(conn->le_conn_min_interval != min ||
conn->le_conn_max_interval != max ||
conn->le_conn_latency != latency ||
- conn->le_supv_timeout != timeout))
- hci_cmd_sync_queue(hdev, conn_update_sync,
- hci_param, NULL);
+ conn->le_supv_timeout != timeout)) {
+ hci_conn_get(conn);
+ if (hci_cmd_sync_queue(hdev, conn_update_sync,
+ conn,
+ conn_update_sync_destroy) < 0)
+ hci_conn_put(conn);
+ }
}
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 093/602] Bluetooth: mgmt: fix locking in unpair_device/disconnect_sync
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (91 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 092/602] Bluetooth: MGMT: revalidate LOAD_CONN_PARAM queued update Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 094/602] Bluetooth: mgmt: hold reference for hci_conn in mgmt_pending_cmds Greg Kroah-Hartman
` (512 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Pauli Virtanen,
Luiz Augusto von Dentz, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <pav@iki.fi>
[ Upstream commit 16cd66443957e4ad42155c6fec401012f600c6f8 ]
Dereferencing RCU-protected pointers outside critical sections is
invalid and may lead to UAF.
Take hdev->lock for hci_conn lookup and hci_abort_conn(). Don't use RCU
to ensure the conn is fully initialized at this point.
Fixes: 227a0cdf4a028 ("Bluetooth: MGMT: Fix not generating command complete for MGMT_OP_DISCONNECT")
Signed-off-by: Pauli Virtanen <pav@iki.fi>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/bluetooth/mgmt.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 0c09cb5a78e028..a5945cfd71c5a5 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3012,6 +3012,8 @@ static int unpair_device_sync(struct hci_dev *hdev, void *data)
struct mgmt_cp_unpair_device *cp = cmd->param;
struct hci_conn *conn;
+ hci_dev_lock(hdev);
+
if (cp->addr.type == BDADDR_BREDR)
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
&cp->addr.bdaddr);
@@ -3019,6 +3021,11 @@ static int unpair_device_sync(struct hci_dev *hdev, void *data)
conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr,
le_addr_type(cp->addr.type));
+ if (conn)
+ hci_conn_get(conn);
+
+ hci_dev_unlock(hdev);
+
if (!conn)
return 0;
@@ -3026,6 +3033,7 @@ static int unpair_device_sync(struct hci_dev *hdev, void *data)
* will clean up the connection no matter the error.
*/
hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM);
+ hci_conn_put(conn);
return 0;
}
@@ -3173,6 +3181,8 @@ static int disconnect_sync(struct hci_dev *hdev, void *data)
struct mgmt_cp_disconnect *cp = cmd->param;
struct hci_conn *conn;
+ hci_dev_lock(hdev);
+
if (cp->addr.type == BDADDR_BREDR)
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
&cp->addr.bdaddr);
@@ -3180,6 +3190,11 @@ static int disconnect_sync(struct hci_dev *hdev, void *data)
conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr,
le_addr_type(cp->addr.type));
+ if (conn)
+ hci_conn_get(conn);
+
+ hci_dev_unlock(hdev);
+
if (!conn)
return -ENOTCONN;
@@ -3187,6 +3202,7 @@ static int disconnect_sync(struct hci_dev *hdev, void *data)
* will clean up the connection no matter the error.
*/
hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM);
+ hci_conn_put(conn);
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 094/602] Bluetooth: mgmt: hold reference for hci_conn in mgmt_pending_cmds
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (92 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 093/602] Bluetooth: mgmt: fix locking in unpair_device/disconnect_sync Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 095/602] Bluetooth: hci_qca: Clear memdump state on invalid dump size Greg Kroah-Hartman
` (511 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Pauli Virtanen,
Luiz Augusto von Dentz, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <pav@iki.fi>
[ Upstream commit da55f570191d5d72f10c607a7043b947eb05ea46 ]
Dereferencing RCU-protected pointers outside critical sections is
invalid and may lead to UAF. Use of hci_conn in hci_sync callbacks also
needs to hold refcount to avoid UAF.
Take appropriate locks for hci_conn lookups, and take refcount for
hci_conn pointers stored in mgmt_pending_cmd so that the pointer stays
valid.
When accessing conn->state, ensure hdev->lock is held to avoid data
race.
Fixes: 7b445e220db9 ("Bluetooth: MGMT: Fix holding hci_conn reference while command is queued")
Signed-off-by: Pauli Virtanen <pav@iki.fi>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/bluetooth/mgmt.c | 26 ++++++++++++++++++++++----
1 file changed, 22 insertions(+), 4 deletions(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index a5945cfd71c5a5..f472ce8fb978bd 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -7425,6 +7425,9 @@ static void get_conn_info_complete(struct hci_dev *hdev, void *data, int err)
rp.max_tx_power = HCI_TX_POWER_INVALID;
}
+ if (conn)
+ hci_conn_put(conn);
+
mgmt_cmd_complete(cmd->sk, cmd->hdev->id, MGMT_OP_GET_CONN_INFO, status,
&rp, sizeof(rp));
@@ -7439,6 +7442,8 @@ static int get_conn_info_sync(struct hci_dev *hdev, void *data)
int err;
__le16 handle;
+ hci_dev_lock(hdev);
+
/* Make sure we are still connected */
if (cp->addr.type == BDADDR_BREDR)
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
@@ -7446,12 +7451,16 @@ static int get_conn_info_sync(struct hci_dev *hdev, void *data)
else
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
- if (!conn || conn->state != BT_CONNECTED)
+ if (!conn || conn->state != BT_CONNECTED) {
+ hci_dev_unlock(hdev);
return MGMT_STATUS_NOT_CONNECTED;
+ }
- cmd->user_data = conn;
+ cmd->user_data = hci_conn_get(conn);
handle = cpu_to_le16(conn->handle);
+ hci_dev_unlock(hdev);
+
/* Refresh RSSI each time */
err = hci_read_rssi_sync(hdev, handle);
@@ -7585,6 +7594,9 @@ static void get_clock_info_complete(struct hci_dev *hdev, void *data, int err)
}
complete:
+ if (conn)
+ hci_conn_put(conn);
+
mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, status, &rp,
sizeof(rp));
@@ -7601,15 +7613,21 @@ static int get_clock_info_sync(struct hci_dev *hdev, void *data)
memset(&hci_cp, 0, sizeof(hci_cp));
hci_read_clock_sync(hdev, &hci_cp);
+ hci_dev_lock(hdev);
+
/* Make sure connection still exists */
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
- if (!conn || conn->state != BT_CONNECTED)
+ if (!conn || conn->state != BT_CONNECTED) {
+ hci_dev_unlock(hdev);
return MGMT_STATUS_NOT_CONNECTED;
+ }
- cmd->user_data = conn;
+ cmd->user_data = hci_conn_get(conn);
hci_cp.handle = cpu_to_le16(conn->handle);
hci_cp.which = 0x01; /* Piconet clock */
+ hci_dev_unlock(hdev);
+
return hci_read_clock_sync(hdev, &hci_cp);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 095/602] Bluetooth: hci_qca: Clear memdump state on invalid dump size
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (93 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 094/602] Bluetooth: mgmt: hold reference for hci_conn in mgmt_pending_cmds Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 096/602] smb/client: handle overlapping allocated ranges in fallocate Greg Kroah-Hartman
` (510 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Ruoyu Wang, Paul Menzel, Zijun Hu,
Luiz Augusto von Dentz, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <ruoyuw560@gmail.com>
[ Upstream commit bf587a10c33e5571a299742e45bc18960b9912e7 ]
qca_controller_memdump() allocates qca->qca_memdump before processing
the first dump packet. For a sequence-zero packet it then disables IBS,
marks memdump collection active, and reads the advertised dump size.
If the controller reports a zero dump size, the error path frees the
local qca_memdump object and returns without clearing qca->qca_memdump
or undoing the collection state. A later memdump work item initializes
its local pointer from qca->qca_memdump and skips allocation when that
pointer is non-NULL, so it can operate on freed memory. The stale
collection and IBS-disabled flags can also leave waiters or later
transmit handling blocked behind an aborted dump.
Clear the saved pointer and memdump state before returning from the
invalid-size path, matching the cleanup used when hci_devcd_init() fails.
A static analysis checker reported the stale memdump state, and manual
source review confirmed the invalid-size failure path.
Fixes: 06d3fdfcdf5c ("Bluetooth: hci_qca: Add qcom devcoredump support")
Signed-off-by: Ruoyu Wang <ruoyuw560@gmail.com>
Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
Reviewed-by: Zijun Hu <zijun.hu@oss.qualcomm.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/bluetooth/hci_qca.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index de9fd0e77d398a..524fc638ceb49f 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -1070,6 +1070,10 @@ static void qca_controller_memdump(struct work_struct *work)
if (!(qca_memdump->ram_dump_size)) {
bt_dev_err(hu->hdev, "Rx invalid memdump size");
kfree(qca_memdump);
+ qca->qca_memdump = NULL;
+ qca->memdump_state = QCA_MEMDUMP_COLLECTED;
+ clear_and_wake_up_bit(QCA_MEMDUMP_COLLECTION, &qca->flags);
+ clear_bit(QCA_IBS_DISABLED, &qca->flags);
kfree_skb(skb);
mutex_unlock(&qca->hci_memdump_lock);
return;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 096/602] smb/client: handle overlapping allocated ranges in fallocate
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (94 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 095/602] Bluetooth: hci_qca: Clear memdump state on invalid dump size Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 097/602] drm/i915/gt: use correct selftest config symbol Greg Kroah-Hartman
` (509 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Huiwen He, ChenXiaoSong,
Steve French, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Huiwen He <hehuiwen@kylinos.cn>
[ Upstream commit b09ae45d85dc816987a71db9eebc54b0ae288e94 ]
smb3_simple_fallocate_range() can skip holes when an allocated range
returned by the server starts before the current fallocate offset. The
skipped hole is not zero-filled, but fallocate still returns success. A
later write to that hole may therefore fail with ENOSPC.
The function queries allocated ranges so that it can preserve existing
contents and write zeroes only into holes. However, the server may return
a range that starts before the current fallocate offset.
For example, assume the fallocate request is [100, 400) and the only
allocated range returned by the server is [0, 200):
Request: [100, 400)
Server range: [ 0, 200) allocated
Correct:
[100, 200) allocated data, skip
[200, 400) hole, zero-fill
Current:
[100, 300) skipped
[300, 400) zero-filled afterwards
The current code adds the full server range length, 200, to the current
offset 100 and moves to 300. As a result, the hole in [200, 300) is
skipped without being zero-filled.
Fix this by advancing only over the part of the allocated range that
overlaps the current fallocate offset. Ignore ranges that end before the
current offset and reject ranges whose end offset overflows.
This also prevents a malformed range length from causing an out-of-bounds
zero-buffer read.
Fixes: 966a3cb7c7db ("cifs: improve fallocate emulation")
Signed-off-by: Huiwen He <hehuiwen@kylinos.cn>
Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/smb/client/smb2ops.c | 25 ++++++++++++++++++-------
1 file changed, 18 insertions(+), 7 deletions(-)
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index f63361bc1641d5..61309fead04e57 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -3482,6 +3482,7 @@ static int smb3_simple_fallocate_range(unsigned int xid,
struct file_allocated_range_buffer in_data, *out_data = NULL, *tmp_data;
u32 out_data_len;
char *buf = NULL;
+ u64 range_start, range_len, range_end;
loff_t l;
int rc;
@@ -3518,13 +3519,21 @@ static int smb3_simple_fallocate_range(unsigned int xid,
goto out;
}
- if (off < le64_to_cpu(tmp_data->file_offset)) {
+ range_start = le64_to_cpu(tmp_data->file_offset);
+ range_len = le64_to_cpu(tmp_data->length);
+ if (check_add_overflow(range_start, range_len, &range_end) ||
+ range_end > S64_MAX) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ if (off < range_start) {
/*
* We are at a hole. Write until the end of the region
* or until the next allocated data,
* whichever comes next.
*/
- l = le64_to_cpu(tmp_data->file_offset) - off;
+ l = range_start - off;
if (len < l)
l = len;
rc = smb3_simple_fallocate_write_range(xid, tcon,
@@ -3541,11 +3550,13 @@ static int smb3_simple_fallocate_range(unsigned int xid,
* until the end of the data or the end of the region
* we are supposed to fallocate, whichever comes first.
*/
- l = le64_to_cpu(tmp_data->length);
- if (len < l)
- l = len;
- off += l;
- len -= l;
+ if (off < range_end) {
+ l = range_end - off;
+ if (len < l)
+ l = len;
+ off += l;
+ len -= l;
+ }
tmp_data = &tmp_data[1];
out_data_len -= sizeof(struct file_allocated_range_buffer);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 097/602] drm/i915/gt: use correct selftest config symbol
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (95 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 096/602] smb/client: handle overlapping allocated ranges in fallocate Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 098/602] powerpc/85xx: Add fsl,ifc to common device ids Greg Kroah-Hartman
` (508 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Pengpeng Hou, Tvrtko Ursulin,
Rodrigo Vivi, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <pengpeng@iscas.ac.cn>
[ Upstream commit a82f1bb8191aec98a971a2196136016ef70c0880 ]
intel_engine_user.c checks CONFIG_DRM_I915_SELFTESTS before running
the engine UABI isolation check. Kconfig defines DRM_I915_SELFTEST,
without the trailing "S", and the rest of i915 uses
CONFIG_DRM_I915_SELFTEST.
Because CONFIG_DRM_I915_SELFTESTS is not backed by any Kconfig symbol,
the IS_ENABLED() test is always false. Use the existing selftest symbol
so the debug/selftest guarded path can be reached when selftests are
enabled.
This is a source-level fix. It does not claim dynamic hardware
reproduction; the evidence is the Kconfig definition and the inconsistent
guard in intel_engine_user.c.
Fixes: 750e76b4f9f6 ("drm/i915/gt: Move the [class][inst] lookup for engines onto the GT")
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Signed-off-by: Tvrtko Ursulin <tursulin@ursulin.net>
Link: https://lore.kernel.org/r/20260705080225.436-1-pengpeng@iscas.ac.cn
(cherry picked from commit 14a2012a490258f3f93857bc4f1b203405964be7)
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/i915/gt/intel_engine_user.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_user.c b/drivers/gpu/drm/i915/gt/intel_engine_user.c
index 833987015b8bbc..ed42b9d05a07d5 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_user.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_user.c
@@ -257,7 +257,7 @@ void intel_engines_driver_register(struct drm_i915_private *i915)
p = &prev->rb_right;
}
- if (IS_ENABLED(CONFIG_DRM_I915_SELFTESTS) &&
+ if (IS_ENABLED(CONFIG_DRM_I915_SELFTEST) &&
IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) {
struct intel_engine_cs *engine;
unsigned int isolation;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 098/602] powerpc/85xx: Add fsl,ifc to common device ids
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (96 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 097/602] drm/i915/gt: use correct selftest config symbol Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 099/602] powerpc/time: Prepare to stop elapsing in dynticks-idle Greg Kroah-Hartman
` (507 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Rosen Penev, Madhavan Srinivasan,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rosen Penev <rosenp@gmail.com>
[ Upstream commit 25957f7c3dac3265332d766b71233e3622f17e14 ]
Add fsl,ifc to mpc85xx_common_ids so that of_platform_bus_probe
creates a platform device for the IFC node even without 'simple-bus'
in its compatible property. On P1010 and similar platforms the IFC
node is a direct child of the root, so it must be explicitly matched
to be populated.
Fixes: 0bf51cc9e9e5 ("powerpc: dts: mpc85xx: remove "simple-bus" compatible from ifc node")
Assisted-by: opencode:big-pickle
Signed-off-by: Rosen Penev <rosenp@gmail.com>
Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
Link: https://patch.msgid.link/20260604043309.91280-1-rosenp@gmail.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
arch/powerpc/platforms/85xx/common.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/powerpc/platforms/85xx/common.c b/arch/powerpc/platforms/85xx/common.c
index 757811155587db..c11deb2f50ed45 100644
--- a/arch/powerpc/platforms/85xx/common.c
+++ b/arch/powerpc/platforms/85xx/common.c
@@ -42,6 +42,8 @@ static const struct of_device_id mpc85xx_common_ids[] __initconst = {
{ .compatible = "fsl,qoriq-pcie-v2.3", },
{ .compatible = "fsl,qoriq-pcie-v2.2", },
{ .compatible = "fsl,fman", },
+ /* IFC NAND and NOR controllers */
+ { .compatible = "fsl,ifc", },
{},
};
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 099/602] powerpc/time: Prepare to stop elapsing in dynticks-idle
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (97 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 098/602] powerpc/85xx: Add fsl,ifc to common device ids Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 100/602] powerpc/vtime: Initialize starttime at boot for native accounting Greg Kroah-Hartman
` (506 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Frederic Weisbecker, Thomas Gleixner,
Shrikanth Hegde, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Frederic Weisbecker <frederic@kernel.org>
[ Upstream commit c8ba971cf8567d49eb5f43ee90c4e50424331c18 ]
Currently the tick subsystem stores the idle cputime accounting in
private fields, allowing cohabitation with architecture idle vtime
accounting. The former is fetched on online CPUs, the latter on offline
CPUs.
For consolidation purpose, architecture vtime accounting will continue
to account the cputime but will make a break when the idle tick is
stopped. The dyntick cputime accounting will then be relayed by the tick
subsystem so that the idle cputime is still seen advancing coherently
even when the tick isn't there to flush the idle vtime.
Prepare for that and introduce three new APIs which will be used in
subsequent patches:
- vtime_dynticks_start() is deemed to be called when idle enters in
dyntick mode. The idle cputime that elapsed so far is accumulated.
- vtime_dynticks_stop() is deemed to be called when idle exits from
dyntick mode. The vtime entry clocks are fast-forward to current time
so that idle accounting restarts elapsing from now.
- vtime_reset() is deemed to be called from dynticks idle IRQ entry to
fast-forward the clock to current time so that the IRQ time is still
accounted by vtime while nohz cputime is paused.
Also accumulated vtime won't be flushed from dyntick-idle ticks to avoid
accounting twice the idle cputime, along with nohz accounting.
Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Tested-by: Shrikanth Hegde <sshegde@linux.ibm.com>
Reviewed-by: Shrikanth Hegde <sshegde@linux.ibm.com>
Link: https://patch.msgid.link/20260508131647.43868-6-frederic@kernel.org
Stable-dep-of: c1c1ffa490fc ("powerpc/vtime: Initialize starttime at boot for native accounting")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
arch/powerpc/kernel/time.c | 41 ++++++++++++++++++++++++++++++++++++++
include/linux/vtime.h | 6 ++++++
2 files changed, 47 insertions(+)
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index ce7f91172ec2b6..c8beb00e6a27c6 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -376,6 +376,47 @@ void vtime_task_switch(struct task_struct *prev)
acct->starttime = acct0->starttime;
}
}
+
+#ifdef CONFIG_NO_HZ_COMMON
+/**
+ * vtime_reset - Fast forward vtime entry clocks
+ *
+ * Called from dynticks idle IRQ entry to fast-forward the clocks to current time
+ * so that the IRQ time is still accounted by vtime while nohz cputime is paused.
+ */
+void vtime_reset(void)
+{
+ struct cpu_accounting_data *acct = get_accounting(current);
+
+ acct->starttime = mftb();
+#ifdef CONFIG_ARCH_HAS_SCALED_CPUTIME
+ acct->startspurr = read_spurr(acct->starttime);
+#endif
+}
+
+/**
+ * vtime_dyntick_start - Inform vtime about entry to idle-dynticks
+ *
+ * Called when idle enters in dyntick mode. The idle cputime that elapsed so far
+ * is accumulated and the tick subsystem takes over the idle cputime accounting.
+ */
+void vtime_dyntick_start(void)
+{
+ vtime_account_idle(current);
+}
+
+/**
+ * vtime_dyntick_stop - Inform vtime about exit from idle-dynticks
+ *
+ * Called when idle exits from dyntick mode. The vtime entry clocks are
+ * fast-forward to current time so that idle accounting restarts elapsing from
+ * now.
+ */
+void vtime_dyntick_stop(void)
+{
+ vtime_reset();
+}
+#endif /* CONFIG_NO_HZ_COMMON */
#endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
void __no_kcsan __delay(unsigned long loops)
diff --git a/include/linux/vtime.h b/include/linux/vtime.h
index 29dd5b91dd7d66..3fc04b849e4e30 100644
--- a/include/linux/vtime.h
+++ b/include/linux/vtime.h
@@ -32,11 +32,17 @@ extern void vtime_account_irq(struct task_struct *tsk, unsigned int offset);
extern void vtime_account_softirq(struct task_struct *tsk);
extern void vtime_account_hardirq(struct task_struct *tsk);
extern void vtime_flush(struct task_struct *tsk);
+extern void vtime_reset(void);
+extern void vtime_dyntick_start(void);
+extern void vtime_dyntick_stop(void);
#else /* !CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */
static inline void vtime_account_irq(struct task_struct *tsk, unsigned int offset) { }
static inline void vtime_account_softirq(struct task_struct *tsk) { }
static inline void vtime_account_hardirq(struct task_struct *tsk) { }
static inline void vtime_flush(struct task_struct *tsk) { }
+static inline void vtime_reset(void) { }
+static inline void vtime_dyntick_start(void) { }
+static inline void vtime_dyntick_stop(void) { }
#endif
/*
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 100/602] powerpc/vtime: Initialize starttime at boot for native accounting
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (98 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 099/602] powerpc/time: Prepare to stop elapsing in dynticks-idle Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 101/602] bpf, sockmap: Reject unhashed UDP sockets on sockmap update Greg Kroah-Hartman
` (505 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Christophe Leroy (CS GROUP),
Shrikanth Hegde, Madhavan Srinivasan, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shrikanth Hegde <sshegde@linux.ibm.com>
[ Upstream commit c1c1ffa490fc33591e90852ed0d38804dd20bc36 ]
It was observed that /proc/stat had very large value for one ore more
CPUs. It was more visible after recent code simplifications around
cpustats.
System has 240 CPUs.
cat /proc/uptime;
194.18 46500.55
cat /proc/stat
cpu 5966 39 837032887 4650070 164 185 100 0 0 0
cpu0 108 0 837030890 19109 24 4 23 0 0 0
Since uptime is 194s, system time of each CPU can't be more than 19400.
Sum of system time of all CPUs can't be more than 19400*240 4656000.
In fact huge value is close to mftb(). Note mftb doesn't reset on powerVM
when the LPAR restart. It only resets when whole system resets. The same
issue exists for kexec too.
This happens since starttime is not setup at init time. Once it is set
then subsequent vtime_delta will return the right delta.
Fix it by initializing the starttime during CPU initialization. This
fixes the large times seen.
cat /proc/uptime; cat /proc/stat
15.78 3694.63
cpu 6035 35 1347 369479 23 144 49 0 0 0
cpu0 19 0 38 1508 0 1 14 0 0 0
Now, system time is reported as expected.
Fixes: cf9efce0ce31 ("powerpc: Account time using timebase rather than PURR")
Reviewed-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
Suggested-by: Christophe Leroy (CS GROUP) <chleroy@kernel.org>
Signed-off-by: Shrikanth Hegde <sshegde@linux.ibm.com>
Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
Link: https://patch.msgid.link/20260605124329.377533-1-sshegde@linux.ibm.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
arch/powerpc/kernel/time.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index c8beb00e6a27c6..c69c0f23f5212a 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -377,7 +377,6 @@ void vtime_task_switch(struct task_struct *prev)
}
}
-#ifdef CONFIG_NO_HZ_COMMON
/**
* vtime_reset - Fast forward vtime entry clocks
*
@@ -394,6 +393,7 @@ void vtime_reset(void)
#endif
}
+#ifdef CONFIG_NO_HZ_COMMON
/**
* vtime_dyntick_start - Inform vtime about entry to idle-dynticks
*
@@ -927,6 +927,7 @@ static void __init set_decrementer_max(void)
static void __init init_decrementer_clockevent(void)
{
register_decrementer_clockevent(smp_processor_id());
+ vtime_reset();
}
void secondary_cpu_time_init(void)
@@ -942,6 +943,7 @@ void secondary_cpu_time_init(void)
/* FIME: Should make unrelated change to move snapshot_timebase
* call here ! */
register_decrementer_clockevent(smp_processor_id());
+ vtime_reset();
}
/* This function is only called on the boot processor */
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 101/602] bpf, sockmap: Reject unhashed UDP sockets on sockmap update
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (99 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 100/602] powerpc/vtime: Initialize starttime at boot for native accounting Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 102/602] s390/checksum: Fix csum_partial() without vector facility Greg Kroah-Hartman
` (504 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Kuniyuki Iwashima, Michal Luczaj,
Jakub Sitnicki, John Fastabend, Kumar Kartikeya Dwivedi,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michal Luczaj <mhal@rbox.co>
[ Upstream commit 66efd3368ae10d05e08fbe6425b50fdec7186ac7 ]
UDP sockets get SOCK_RCU_FREE set when (auto-)bound. This means
sk_is_refcounted(unbound) = true, while sk_is_refcounted(bound) = false.
Because sockmap accepts unbound UDP sockets, a BPF program can increment a
socket's refcount via lookup. If the socket is subsequently bound, the
transition from unbound to bound causes bpf_sk_release() to skip the
decrement of the refcount, causing a memory leak.
unreferenced object 0xffff88810bc2eb40 (size 1984):
comm "test_progs", pid 2451, jiffies 4295320596
hex dump (first 32 bytes):
7f 00 00 01 7f 00 00 01 d2 04 1b b7 04 d2 00 00 ................
02 00 01 40 00 00 00 00 00 00 00 00 00 00 00 00 ...@............
backtrace (crc bdee079d):
kmem_cache_alloc_noprof+0x557/0x660
sk_prot_alloc+0x69/0x240
sk_alloc+0x30/0x460
inet_create+0x2ce/0xf80
__sock_create+0x25b/0x5c0
__sys_socket+0x119/0x1d0
__x64_sys_socket+0x72/0xd0
do_syscall_64+0xa1/0x5f0
entry_SYSCALL_64_after_hwframe+0x76/0x7e
Instead of special-casing for refcounted sockets, reject unhashed UDP
sockets during sockmap updates, as there is no benefit to supporting those.
This effectively reverts the commit under Fixes, with two exceptions:
1. sock_map_sk_state_allowed() maintains a fall-through `return true`.
2. In the spirit of commit b8b8315e39ff ("bpf, sockmap: Remove unhash
handler for BPF sockmap usage"), the proto::unhash BPF handler is not
reintroduced.
Historical note: this issue is related to commit 67312adc96b5 ("bpf: reject
unhashed sockets in bpf_sk_assign").
Fixes: 0c48eefae712 ("sock_map: Lift socket state restriction for datagram sockets")
Suggested-by: Kuniyuki Iwashima <kuniyu@google.com>
Signed-off-by: Michal Luczaj <mhal@rbox.co>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
Reviewed-by: John Fastabend <john.fastabend@gmail.com>
Link: https://lore.kernel.org/bpf/20260707-sockmap-lookup-udp-leak-v4-2-f878346f27ab@rbox.co
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/core/sock_map.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/core/sock_map.c b/net/core/sock_map.c
index 82a14f131d00c6..6440ce16fc6214 100644
--- a/net/core/sock_map.c
+++ b/net/core/sock_map.c
@@ -542,6 +542,8 @@ static bool sock_map_sk_state_allowed(const struct sock *sk)
{
if (sk_is_tcp(sk))
return (1 << sk->sk_state) & (TCPF_ESTABLISHED | TCPF_LISTEN);
+ if (sk_is_udp(sk))
+ return sk_hashed(sk);
if (sk_is_stream_unix(sk))
return (1 << sk->sk_state) & TCPF_ESTABLISHED;
if (sk_is_vsock(sk) &&
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 102/602] s390/checksum: Fix csum_partial() without vector facility
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (100 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 101/602] bpf, sockmap: Reject unhashed UDP sockets on sockmap update Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 103/602] riscv: hwprobe: Avoid uninitialized read in hwprobe_get_cpus() Greg Kroah-Hartman
` (503 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Heiko Carstens, Vasily Gorbik,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vasily Gorbik <gor@linux.ibm.com>
[ Upstream commit 4bb06b60d982355e22647b3d12d6619419f8c1fa ]
Currently csum_partial() calls csum_copy() with copy=false and dst=NULL.
On machines without the vector facility, csum_copy() falls back to
cksm(dst, ...), causing the checksum to be calculated from address zero
instead of the source buffer.
The VX implementation already checksums data loaded from src. Make the
fallback do the same by passing src to cksm().
Fixes: dcd3e1de9d17 ("s390/checksum: provide csum_partial_copy_nocheck()")
Reviewed-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
arch/s390/lib/csum-partial.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/s390/lib/csum-partial.c b/arch/s390/lib/csum-partial.c
index 458abd9bac7025..9d74ceff136c54 100644
--- a/arch/s390/lib/csum-partial.c
+++ b/arch/s390/lib/csum-partial.c
@@ -23,7 +23,7 @@ static __always_inline __wsum csum_copy(void *dst, const void *src, int len, __w
if (!cpu_has_vx()) {
if (copy)
memcpy(dst, src, len);
- return cksm(dst, len, sum);
+ return cksm(src, len, sum);
}
kernel_fpu_begin(&vxstate, KERNEL_VXR_V16V23);
fpu_vlvgf(16, (__force u32)sum, 1);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 103/602] riscv: hwprobe: Avoid uninitialized read in hwprobe_get_cpus()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (101 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 102/602] s390/checksum: Fix csum_partial() without vector facility Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 104/602] can: j1939: fix lockless local-destination check Greg Kroah-Hartman
` (502 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Mark Harris, Nam Cao,
Michael Ellerman, Paul Walmsley, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mark Harris <mark.hsj@gmail.com>
[ Upstream commit 5caae1deee89a6582c761d5dcd4b924b744426cc ]
When cpusetsize < cpumask_size(), hwprobe_get_cpus() did not fully
initialize its copy of the cpu mask, which could cause non-deterministic
results from the riscv_hwprobe syscall on a system with more than 8 CPUs
when the supplied cpu mask is empty. Address this by fully initializing
the cpu mask.
Fixes: e178bf146e4b ("RISC-V: hwprobe: Introduce which-cpus flag")
Signed-off-by: Mark Harris <mark.hsj@gmail.com>
Reviewed-by: Nam Cao <namcao@linutronix.de>
Reviewed-by: Michael Ellerman <mpe@kernel.org>
Link: https://patch.msgid.link/20260714003056.73707-1-mark.hsj@gmail.com
Signed-off-by: Paul Walmsley <pjw@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
arch/riscv/kernel/sys_hwprobe.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c
index fc62548888c587..d273080bec34d8 100644
--- a/arch/riscv/kernel/sys_hwprobe.c
+++ b/arch/riscv/kernel/sys_hwprobe.c
@@ -336,6 +336,7 @@ static int hwprobe_get_cpus(struct riscv_hwprobe __user *pairs,
if (cpusetsize > cpumask_size())
cpusetsize = cpumask_size();
+ cpumask_clear(&cpus);
ret = copy_from_user(&cpus, cpus_user, cpusetsize);
if (ret)
return -EFAULT;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 104/602] can: j1939: fix lockless local-destination check
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (102 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 103/602] riscv: hwprobe: Avoid uninitialized read in hwprobe_get_cpus() Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 105/602] drm/xe/wopcm: fix WOPCM size for LNL+ Greg Kroah-Hartman
` (501 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Shuhao Fu, Oleksij Rempel,
Marc Kleine-Budde, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shuhao Fu <sfual@cse.ust.hk>
[ Upstream commit e4e8af62adab2fdcca230006f829407a953070cd ]
j1939_priv.ents[].nusers is documented as protected by priv->lock, and
its updates already happen under that lock. j1939_can_recv() also reads
it under read_lock_bh(). However, j1939_session_skb_queue() and
j1939_tp_send() still read priv->ents[da].nusers without taking the
lock.
Those transport-side checks decide whether to set J1939_ECU_LOCAL_DST, so
they can race with j1939_local_ecu_get() and j1939_local_ecu_put() while
userspace is binding or releasing sockets concurrently with TP traffic.
This can misclassify TP/ETP sessions as local or remote and take the wrong
transport path.
Fix both transport paths by routing the destination-locality check through
a helper that reads ents[].nusers under read_lock_bh(&priv->lock).
Fixes: 9d71dd0c7009 ("can: add support of SAE J1939 protocol")
Signed-off-by: Shuhao Fu <sfual@cse.ust.hk>
Tested-by: Oleksij Rempel <o.rempel@pengutronix.de>
Acked-by: Oleksij Rempel <o.rempel@pengutronix.de>
Link: https://patch.msgid.link/20260419140614.GA4041240@chcpu16
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/can/j1939/transport.c | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c
index 6c37562a50f72e..d8dada03b3cd12 100644
--- a/net/can/j1939/transport.c
+++ b/net/can/j1939/transport.c
@@ -350,6 +350,18 @@ static void j1939_session_skb_drop_old(struct j1939_session *session)
}
}
+static bool j1939_address_is_local(struct j1939_priv *priv, u8 addr)
+{
+ bool local = false;
+
+ read_lock_bh(&priv->lock);
+ if (j1939_address_is_unicast(addr) && priv->ents[addr].nusers)
+ local = true;
+ read_unlock_bh(&priv->lock);
+
+ return local;
+}
+
void j1939_session_skb_queue(struct j1939_session *session,
struct sk_buff *skb)
{
@@ -358,8 +370,7 @@ void j1939_session_skb_queue(struct j1939_session *session,
j1939_ac_fixup(priv, skb);
- if (j1939_address_is_unicast(skcb->addr.da) &&
- priv->ents[skcb->addr.da].nusers)
+ if (j1939_address_is_local(priv, skcb->addr.da))
skcb->flags |= J1939_ECU_LOCAL_DST;
skcb->flags |= J1939_ECU_LOCAL_SRC;
@@ -2021,8 +2032,7 @@ struct j1939_session *j1939_tp_send(struct j1939_priv *priv,
return ERR_PTR(ret);
/* fix DST flags, it may be used there soon */
- if (j1939_address_is_unicast(skcb->addr.da) &&
- priv->ents[skcb->addr.da].nusers)
+ if (j1939_address_is_local(priv, skcb->addr.da))
skcb->flags |= J1939_ECU_LOCAL_DST;
/* src is always local, I'm sending ... */
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 105/602] drm/xe/wopcm: fix WOPCM size for LNL+
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (103 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 104/602] can: j1939: fix lockless local-destination check Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 106/602] smb: move some duplicate definitions to common/cifsglob.h Greg Kroah-Hartman
` (500 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Daniele Ceraolo Spurio, Rodrigo Vivi,
Shuicheng Lin, Matt Roper, Thomas Hellström, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
[ Upstream commit ad87e2476b3b246580f407afc8ffa91d621bc849 ]
Starting on LNL the WOPCM size is 8MB instead of 4, so we need to avoid
using the [0, 8MB) range of the GGTT as that can be unaccessible from
the microcontrollers.
Note that the proper long-term fix here is to read the WOPCM size from
the HW, but that is a more serious rework that would be difficult to
backport, so we can do that as a follow-up.
Fixes: 9c57bc08652a ("drm/xe/lnl: Drop force_probe requirement")
Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Shuicheng Lin <shuicheng.lin@intel.com>
Cc: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: Shuicheng Lin <shuicheng.lin@intel.com>
Link: https://patch.msgid.link/20260713221758.3285744-2-daniele.ceraolospurio@intel.com
(cherry picked from commit 3033b0b24ed0e2f5e56bdd4d9c183417c365a45b)
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/xe/xe_wopcm.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_wopcm.c b/drivers/gpu/drm/xe/xe_wopcm.c
index d3a99157e52338..b7de817cce8870 100644
--- a/drivers/gpu/drm/xe/xe_wopcm.c
+++ b/drivers/gpu/drm/xe/xe_wopcm.c
@@ -47,9 +47,9 @@
*/
/* Default WOPCM size is 2MB from Gen11, 1MB on previous platforms */
-/* FIXME: Larger size require for 2 tile PVC, do a proper probe sooner or later */
+/* FIXME: Larger size require for some platforms, do a proper probe sooner or later */
#define DGFX_WOPCM_SIZE SZ_4M
-/* FIXME: Larger size require for MTL, do a proper probe sooner or later */
+#define LNL_WOPCM_SIZE SZ_8M
#define MTL_WOPCM_SIZE SZ_4M
#define WOPCM_SIZE SZ_2M
@@ -179,9 +179,14 @@ static int __wopcm_init_regs(struct xe_device *xe, struct xe_gt *gt,
u32 xe_wopcm_size(struct xe_device *xe)
{
- return IS_DGFX(xe) ? DGFX_WOPCM_SIZE :
- xe->info.platform == XE_METEORLAKE ? MTL_WOPCM_SIZE :
- WOPCM_SIZE;
+ if (xe->info.platform >= XE_LUNARLAKE)
+ return LNL_WOPCM_SIZE;
+ else if (IS_DGFX(xe))
+ return DGFX_WOPCM_SIZE;
+ else if (xe->info.platform == XE_METEORLAKE)
+ return MTL_WOPCM_SIZE;
+ else
+ return WOPCM_SIZE;
}
/**
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 106/602] smb: move some duplicate definitions to common/cifsglob.h
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (104 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 105/602] drm/xe/wopcm: fix WOPCM size for LNL+ Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 107/602] ksmbd: pin conn during async oplock break notification Greg Kroah-Hartman
` (499 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, ChenXiaoSong, ZhangGuoDong,
Steve French, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: ZhangGuoDong <zhangguodong@kylinos.cn>
[ Upstream commit d877470b59910b5c50383d634dda3782386bba51 ]
In order to maintain the code more easily, move duplicate definitions to
new common header file.
Co-developed-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
Signed-off-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
Signed-off-by: ZhangGuoDong <zhangguodong@kylinos.cn>
Signed-off-by: Steve French <stfrench@microsoft.com>
Stable-dep-of: aa5d8f3f96aa ("ksmbd: pin conn during async oplock break notification")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/smb/client/cifsglob.h | 19 +------------------
fs/smb/common/cifsglob.h | 30 ++++++++++++++++++++++++++++++
fs/smb/server/smb_common.h | 14 +-------------
3 files changed, 32 insertions(+), 31 deletions(-)
create mode 100644 fs/smb/common/cifsglob.h
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
index dcfadbc20723f0..c054ee44269416 100644
--- a/fs/smb/client/cifsglob.h
+++ b/fs/smb/client/cifsglob.h
@@ -25,6 +25,7 @@
#include "cifsacl.h"
#include <crypto/internal/hash.h>
#include <uapi/linux/cifs/cifs_mount.h>
+#include "../common/cifsglob.h"
#include "../common/smb2pdu.h"
#include "smb2pdu.h"
#include <linux/filelock.h>
@@ -669,12 +670,6 @@ get_rfc1002_length(void *buf)
return be32_to_cpu(*((__be32 *)buf)) & 0xffffff;
}
-static inline void
-inc_rfc1001_len(void *buf, int count)
-{
- be32_add_cpu((__be32 *)buf, count);
-}
-
struct TCP_Server_Info {
struct list_head tcp_ses_list;
struct list_head smb_ses_list;
@@ -986,8 +981,6 @@ compare_mid(__u16 mid, const struct smb_hdr *smb)
#define CIFS_MAX_RFC1002_WSIZE ((1<<17) - 1 - sizeof(WRITE_REQ) + 4)
#define CIFS_MAX_RFC1002_RSIZE ((1<<17) - 1 - sizeof(READ_RSP) + 4)
-#define CIFS_DEFAULT_IOSIZE (1024 * 1024)
-
/*
* Windows only supports a max of 60kb reads and 65535 byte writes. Default to
* those values when posix extensions aren't in force. In actuality here, we
@@ -2094,30 +2087,20 @@ extern mempool_t cifs_io_request_pool;
extern mempool_t cifs_io_subrequest_pool;
/* Operations for different SMB versions */
-#define SMB1_VERSION_STRING "1.0"
-#define SMB20_VERSION_STRING "2.0"
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
extern struct smb_version_operations smb1_operations;
extern struct smb_version_values smb1_values;
extern struct smb_version_operations smb20_operations;
extern struct smb_version_values smb20_values;
#endif /* CIFS_ALLOW_INSECURE_LEGACY */
-#define SMB21_VERSION_STRING "2.1"
extern struct smb_version_operations smb21_operations;
extern struct smb_version_values smb21_values;
-#define SMBDEFAULT_VERSION_STRING "default"
extern struct smb_version_values smbdefault_values;
-#define SMB3ANY_VERSION_STRING "3"
extern struct smb_version_values smb3any_values;
-#define SMB30_VERSION_STRING "3.0"
extern struct smb_version_operations smb30_operations;
extern struct smb_version_values smb30_values;
-#define SMB302_VERSION_STRING "3.02"
-#define ALT_SMB302_VERSION_STRING "3.0.2"
/*extern struct smb_version_operations smb302_operations;*/ /* not needed yet */
extern struct smb_version_values smb302_values;
-#define SMB311_VERSION_STRING "3.1.1"
-#define ALT_SMB311_VERSION_STRING "3.11"
extern struct smb_version_operations smb311_operations;
extern struct smb_version_values smb311_values;
diff --git a/fs/smb/common/cifsglob.h b/fs/smb/common/cifsglob.h
new file mode 100644
index 00000000000000..00fd215e3eb547
--- /dev/null
+++ b/fs/smb/common/cifsglob.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: LGPL-2.1 */
+/*
+ *
+ * Copyright (C) International Business Machines Corp., 2002,2008
+ * Author(s): Steve French (sfrench@us.ibm.com)
+ * Jeremy Allison (jra@samba.org)
+ *
+ */
+#ifndef _COMMON_CIFS_GLOB_H
+#define _COMMON_CIFS_GLOB_H
+
+static inline void inc_rfc1001_len(void *buf, int count)
+{
+ be32_add_cpu((__be32 *)buf, count);
+}
+
+#define SMB1_VERSION_STRING "1.0"
+#define SMB20_VERSION_STRING "2.0"
+#define SMB21_VERSION_STRING "2.1"
+#define SMBDEFAULT_VERSION_STRING "default"
+#define SMB3ANY_VERSION_STRING "3"
+#define SMB30_VERSION_STRING "3.0"
+#define SMB302_VERSION_STRING "3.02"
+#define ALT_SMB302_VERSION_STRING "3.0.2"
+#define SMB311_VERSION_STRING "3.1.1"
+#define ALT_SMB311_VERSION_STRING "3.11"
+
+#define CIFS_DEFAULT_IOSIZE (1024 * 1024)
+
+#endif /* _COMMON_CIFS_GLOB_H */
diff --git a/fs/smb/server/smb_common.h b/fs/smb/server/smb_common.h
index a3d8a905b07e07..a353e187dfd7ad 100644
--- a/fs/smb/server/smb_common.h
+++ b/fs/smb/server/smb_common.h
@@ -10,6 +10,7 @@
#include "glob.h"
#include "nterr.h"
+#include "../common/cifsglob.h"
#include "../common/smb2pdu.h"
#include "smb2pdu.h"
@@ -26,16 +27,8 @@
#define SMB311_PROT 6
#define BAD_PROT 0xFFFF
-#define SMB1_VERSION_STRING "1.0"
-#define SMB20_VERSION_STRING "2.0"
-#define SMB21_VERSION_STRING "2.1"
-#define SMB30_VERSION_STRING "3.0"
-#define SMB302_VERSION_STRING "3.02"
-#define SMB311_VERSION_STRING "3.1.1"
-
#define SMB_ECHO_INTERVAL (60 * HZ)
-#define CIFS_DEFAULT_IOSIZE (64 * 1024)
#define MAX_CIFS_SMALL_BUFFER_SIZE 448 /* big enough for most */
#define MAX_STREAM_PROT_LEN 0x00FFFFFF
@@ -462,9 +455,4 @@ static inline unsigned int get_rfc1002_len(void *buf)
{
return be32_to_cpu(*((__be32 *)buf)) & 0xffffff;
}
-
-static inline void inc_rfc1001_len(void *buf, int count)
-{
- be32_add_cpu((__be32 *)buf, count);
-}
#endif /* __SMB_COMMON_H__ */
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 107/602] ksmbd: pin conn during async oplock break notification
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (105 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 106/602] smb: move some duplicate definitions to common/cifsglob.h Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 108/602] ksmbd: validate compound request size before reading StructureSize2 Greg Kroah-Hartman
` (498 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Qihang, Namjae Jeon, Steve French,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qihang <q.h.hack.winter@gmail.com>
[ Upstream commit aa5d8f3f96aa11a4a54ce993c11ce8af11c546f9 ]
smb2_oplock_break_noti() and smb2_lease_break_noti() store a ksmbd_conn
pointer in an async ksmbd_work and then queue that work on ksmbd-io. The
work only increments conn->r_count, which prevents teardown from passing
the pending-request wait after the increment, but it does not pin the
struct ksmbd_conn object.
If connection teardown races with an oplock break notification, the last
conn reference can be dropped before the queued worker finishes. The
worker then uses the freed conn in ksmbd_conn_write() and
ksmbd_conn_r_count_dec().
Take a real conn reference when publishing the conn pointer to the async
work item, and drop it after the notification work has decremented
r_count. Apply the same lifetime rule to lease break notification, which
uses the same work->conn pattern.
Fixes: 3aa660c05924 ("ksmbd: prevent connection release during oplock break notification")
Signed-off-by: Qihang <q.h.hack.winter@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/smb/server/oplock.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c
index a019c4496ae433..ff0dbf3f8cbf49 100644
--- a/fs/smb/server/oplock.c
+++ b/fs/smb/server/oplock.c
@@ -705,6 +705,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk)
out:
ksmbd_free_work_struct(work);
ksmbd_conn_r_count_dec(conn);
+ ksmbd_conn_put(conn);
}
/**
@@ -740,7 +741,7 @@ static int smb2_oplock_break_noti(struct oplock_info *opinfo)
br_info->open_trunc = opinfo->open_trunc;
work->request_buf = (char *)br_info;
- work->conn = conn;
+ work->conn = ksmbd_conn_get(conn);
work->sess = opinfo->sess;
ksmbd_conn_r_count_inc(conn);
@@ -814,6 +815,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk)
out:
ksmbd_free_work_struct(work);
ksmbd_conn_r_count_dec(conn);
+ ksmbd_conn_put(conn);
}
/**
@@ -853,7 +855,7 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo)
memcpy(br_info->lease_key, lease->lease_key, SMB2_LEASE_KEY_SIZE);
work->request_buf = (char *)br_info;
- work->conn = conn;
+ work->conn = ksmbd_conn_get(conn);
work->sess = opinfo->sess;
ksmbd_conn_r_count_inc(conn);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 108/602] ksmbd: validate compound request size before reading StructureSize2
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (106 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 107/602] ksmbd: pin conn during async oplock break notification Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 109/602] drm/i915/selftests: Fix GT PM sort comparators Greg Kroah-Hartman
` (497 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, AutonomousCodeSecurity,
Xiang Mei (Microsoft), Namjae Jeon, Steve French, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei (Microsoft) <xmei5@asu.edu>
[ Upstream commit 15b38176fd1530372905c602fde51fe89ec8c877 ]
When ksmbd validates a compound (chained) SMB2 request,
ksmbd_smb2_check_message() reads pdu->StructureSize2 without first
checking that the compound element is large enough to contain it.
StructureSize2 is a 2-byte field at offset 64
(__SMB2_HEADER_STRUCTURE_SIZE) from the start of each element.
The compound-walking logic only guarantees that a full 64-byte SMB2
header is present for the trailing element: when NextCommand is 0, len is
reduced to the number of bytes remaining after next_smb2_rcv_hdr_off. A
remote client can craft a compound request whose last element has exactly
64 bytes, so the 2-byte StructureSize2 read at offset 64 extends one byte
past the receive buffer, producing a slab-out-of-bounds read.
BUG: KASAN: slab-out-of-bounds in ksmbd_smb2_check_message (fs/smb/server/smb2misc.c:402)
Read of size 2 at addr ffff888012ae31ac by task kworker/0:1/14
The buggy address is located 172 bytes inside of allocated 173-byte region
Workqueue: ksmbd-io handle_ksmbd_work
Call Trace:
...
kasan_report (mm/kasan/report.c:595)
ksmbd_smb2_check_message (fs/smb/server/smb2misc.c:402)
handle_ksmbd_work (fs/smb/server/server.c:119)
process_one_work (kernel/workqueue.c:3314)
worker_thread (kernel/workqueue.c:3397)
kthread (kernel/kthread.c:436)
ret_from_fork (arch/x86/kernel/process.c:158)
ret_from_fork_asm (arch/x86/entry/entry_64.S:245)
Reject any compound element that is too small to hold StructureSize2
before dereferencing it.
Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3")
Reported-by: AutonomousCodeSecurity@microsoft.com
Signed-off-by: Xiang Mei (Microsoft) <xmei5@asu.edu>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/smb/server/smb2misc.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/fs/smb/server/smb2misc.c b/fs/smb/server/smb2misc.c
index ae501024665e1f..6317edbfe4fa43 100644
--- a/fs/smb/server/smb2misc.c
+++ b/fs/smb/server/smb2misc.c
@@ -400,6 +400,11 @@ int ksmbd_smb2_check_message(struct ksmbd_work *work)
return 1;
}
+ if (len < __SMB2_HEADER_STRUCTURE_SIZE + sizeof(__le16)) {
+ ksmbd_debug(SMB, "Message is too small for StructureSize2\n");
+ return 1;
+ }
+
if (smb2_req_struct_sizes[command] != pdu->StructureSize2) {
if (!(command == SMB2_OPLOCK_BREAK_HE &&
(le16_to_cpu(pdu->StructureSize2) == OP_BREAK_STRUCT_SIZE_20 ||
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 109/602] drm/i915/selftests: Fix GT PM sort comparators
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (107 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 108/602] ksmbd: validate compound request size before reading StructureSize2 Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 110/602] net/sched: act_tunnel_key: Defer dst_release to RCU callback Greg Kroah-Hartman
` (496 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Emre Cecanpunar, Tvrtko Ursulin,
Rodrigo Vivi, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Emre Cecanpunar <emreleno@gmail.com>
[ Upstream commit 612978b83f45bf7018815209db5395d759db6f26 ]
Compare the sampled clock values instead of their addresses. Comparing
addresses leaves the samples unsorted, preventing the code from discarding
the minimum and maximum samples.
Fixes: 1a5392479207 ("drm/i915/selftests: Measure CS_TIMESTAMP")
Signed-off-by: Emre Cecanpunar <emreleno@gmail.com>
Signed-off-by: Tvrtko Ursulin <tursulin@ursulin.net>
Link: https://lore.kernel.org/r/20260714220430.238433-1-emreleno@gmail.com
(cherry picked from commit 682ea2d28d18bb06f9fc663cb5ab7e80dc0e606a)
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/i915/gt/selftest_gt_pm.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c
index 33351deeea4f0b..07eaf71955c447 100644
--- a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c
+++ b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c
@@ -16,9 +16,9 @@ static int cmp_u64(const void *A, const void *B)
{
const u64 *a = A, *b = B;
- if (a < b)
+ if (*a < *b)
return -1;
- else if (a > b)
+ else if (*a > *b)
return 1;
else
return 0;
@@ -28,9 +28,9 @@ static int cmp_u32(const void *A, const void *B)
{
const u32 *a = A, *b = B;
- if (a < b)
+ if (*a < *b)
return -1;
- else if (a > b)
+ else if (*a > *b)
return 1;
else
return 0;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 110/602] net/sched: act_tunnel_key: Defer dst_release to RCU callback
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (108 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 109/602] drm/i915/selftests: Fix GT PM sort comparators Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 111/602] sctp: fix auth_hmacs array size in struct sctp_cookie Greg Kroah-Hartman
` (495 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, zdi-disclosures, Victor Nogueira,
Jamal Hadi Salim, Davide Caratti, Paolo Abeni, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jamal Hadi Salim <jhs@mojatatu.com>
[ Upstream commit f1f5c8a3955f8fda3f84ed883ac8daa1847e724c ]
Fix a race-condition use-after-free in tunnel_key_release_params().
The function releases the metadata_dst of the old params synchronously
via dst_release() while deferring the params struct free with
kfree_rcu(). A concurrent tunnel_key_act() reader on the datapath may
still hold the old params pointer (under rcu_read_lock_bh) and proceed
to call dst_clone(¶ms->tcft_enc_metadata->dst) after the writer's
dst_release has already pushed the dst's rcuref to RCUREF_DEAD.
zdi-disclosures@trendmicro.com produced a poc which i (and Victor) verified
that KASAN reports:
==================================================================
BUG: KASAN: slab-use-after-free in instrument_atomic_read_write include/linux/instrumented.h:112
BUG: KASAN: slab-use-after-free in atomic_sub_return_release include/linux/atomic/atomic-instrumented.h:326
BUG: KASAN: slab-use-after-free in __rcuref_put include/linux/rcuref.h:109
BUG: KASAN: slab-use-after-free in rcuref_put include/linux/rcuref.h:173
BUG: KASAN: slab-use-after-free in dst_release+0x5b/0x370 net/core/dst.c:168
Write of size 4 at addr ffff88806158de40 by task poc/9388
CPU: 0 UID: 0 PID: 9388 Comm: poc Tainted: G W 7.1.0-rc7 #7 PREEMPT(lazy)
Tainted: [W]=WARN
Hardware name: QEMU Ubuntu 25.10 PC v2 (i440FX + PIIX, + 10.1 machine, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:94
dump_stack_lvl+0x100/0x190 lib/dump_stack.c:120
print_address_description mm/kasan/report.c:378
print_report+0x139/0x4ad mm/kasan/report.c:482
kasan_report+0xe4/0x1d0 mm/kasan/report.c:595
check_region_inline mm/kasan/generic.c:186
kasan_check_range+0x125/0x200 mm/kasan/generic.c:200
instrument_atomic_read_write include/linux/instrumented.h:112
atomic_sub_return_release include/linux/atomic/atomic-instrumented.h:326
__rcuref_put include/linux/rcuref.h:109
rcuref_put include/linux/rcuref.h:173
dst_release+0x5b/0x370 net/core/dst.c:168
refdst_drop include/net/dst.h:272
skb_dst_drop include/net/dst.h:284
skb_release_head_state+0x293/0x400 net/core/skbuff.c:1163
skb_release_all net/core/skbuff.c:1187
[..]
Allocated by task 9391:
kasan_save_stack+0x30/0x50 mm/kasan/common.c:57
kasan_save_track+0x14/0x30 mm/kasan/common.c:78
poison_kmalloc_redzone mm/kasan/common.c:398
__kasan_kmalloc+0x9a/0xb0 mm/kasan/common.c:415
kasan_kmalloc include/linux/kasan.h:263
__do_kmalloc_node mm/slub.c:5296
__kmalloc_noprof+0x2f1/0x830 mm/slub.c:5308
kmalloc_noprof include/linux/slab.h:954
kzalloc_noprof include/linux/slab.h:1188
offload_action_alloc+0x2f/0x130 net/core/flow_offload.c:35
tcf_action_offload_add_ex+0x1ba/0x880 net/sched/act_api.c:258
tcf_action_offload_add net/sched/act_api.c:293
tcf_action_init+0x66e/0xa20 net/sched/act_api.c:1547
tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101
[..]
Freed by task 9391:
kasan_save_stack+0x30/0x50 mm/kasan/common.c:57
kasan_save_track+0x14/0x30 mm/kasan/common.c:78
kasan_save_free_info+0x3b/0x70 mm/kasan/generic.c:584
poison_slab_object mm/kasan/common.c:253
__kasan_slab_free+0x6b/0x90 mm/kasan/common.c:285
kasan_slab_free include/linux/kasan.h:235
slab_free_hook mm/slub.c:2689
slab_free mm/slub.c:6251
kfree+0x21f/0x6b0 mm/slub.c:6566
tcf_action_offload_add_ex+0x4ad/0x880 net/sched/act_api.c:284
tcf_action_offload_add net/sched/act_api.c:293
tcf_action_init+0x66e/0xa20 net/sched/act_api.c:1547
tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101
The buggy address belongs to the object at ffff88806158de00
which belongs to the cache kmalloc-256 of size 256
The buggy address is located 64 bytes inside of
freed 256-byte region [ffff88806158de00, ffff88806158df00)
The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffff88806158d600 pfn:0x6158c
head: order:1 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
flags: 0x4fff00000000240(workingset|head|node=1|zone=1|lastcpupid=0x7ff)
page_type: f5(slab)
raw: 04fff00000000240 ffff88801c841b40 ffffea0001856290 ffffea0001856190
raw: ffff88806158d600 0000000800100009 00000000f5000000 0000000000000000
head: 04fff00000000240 ffff88801c841b40 ffffea0001856290 ffffea0001856190
head: ffff88806158d600 0000000800100009 00000000f5000000 0000000000000000
head: 04fff00000000001 ffffffffffffff81 00000000ffffffff 00000000ffffffff
head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000002
page dumped because: kasan: bad access detected
page_owner tracks the page as allocated
page last allocated via order 1, migratetype Unmovable, gfp_mask 0xd2820(GFP_ATOMIC|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC), pid 9391, tgid 9378 (poc), ts 123227323196, free_ts 0
set_page_owner include/linux/page_owner.h:32
post_alloc_hook+0xfe/0x140 mm/page_alloc.c:1853
prep_new_page mm/page_alloc.c:1861
get_page_from_freelist+0x110c/0x2fc0 mm/page_alloc.c:3941
__alloc_frozen_pages_noprof+0x263/0x2bc0 mm/page_alloc.c:5221
alloc_slab_page mm/slub.c:3278
allocate_slab mm/slub.c:3467
new_slab+0xa6/0x690 mm/slub.c:3525
refill_objects+0x271/0x420 mm/slub.c:7272
refill_sheaf mm/slub.c:2816
__pcs_replace_empty_main+0x373/0x630 mm/slub.c:4652
alloc_from_pcs mm/slub.c:4750
slab_alloc_node mm/slub.c:4884
__do_kmalloc_node mm/slub.c:5295
__kmalloc_noprof+0x66d/0x830 mm/slub.c:5308
kmalloc_noprof include/linux/slab.h:954
metadata_dst_alloc+0x26/0x90 net/core/dst.c:298
tun_rx_dst include/net/dst_metadata.h:144
__ip_tun_set_dst include/net/dst_metadata.h:208
tunnel_key_init+0xb01/0x1b90 net/sched/act_tunnel_key.c:451
tcf_action_init_1+0x46b/0x6c0 net/sched/act_api.c:1428
tcf_action_init+0x448/0xa20 net/sched/act_api.c:1503
tcf_action_add+0xf6/0x5d0 net/sched/act_api.c:2101
[..]
==================================================================
Fix by moving dst_release() into a custom RCU callback that runs
after the grace period, matching the lifetime of the containing
params struct. Readers in the datapath therefore always find a live
rcuref when calling dst_clone().
Fixes: 9174c3df1cd18 ("net/sched: act_tunnel_key: fix memory leak in case of action replace")
Reported-by: zdi-disclosures@trendmicro.com
Tested-by: Victor Nogueira <victor@mojatatu.com>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
Reviewed-by: Davide Caratti <dcaratti@redhat.com>
Link: https://patch.msgid.link/20260711150537.7946-1-jhs@mojatatu.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/sched/act_tunnel_key.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c
index e296714803dc02..74e9b5ea76a555 100644
--- a/net/sched/act_tunnel_key.c
+++ b/net/sched/act_tunnel_key.c
@@ -344,14 +344,20 @@ static const struct nla_policy tunnel_key_policy[TCA_TUNNEL_KEY_MAX + 1] = {
[TCA_TUNNEL_KEY_ENC_TTL] = { .type = NLA_U8 },
};
-static void tunnel_key_release_params(struct tcf_tunnel_key_params *p)
+static void tunnel_key_release_params_rcu(struct rcu_head *head)
{
- if (!p)
- return;
+ struct tcf_tunnel_key_params *p = container_of(head, typeof(*p), rcu);
+
if (p->tcft_action == TCA_TUNNEL_KEY_ACT_SET)
dst_release(&p->tcft_enc_metadata->dst);
+ kfree(p);
+}
- kfree_rcu(p, rcu);
+static void tunnel_key_release_params(struct tcf_tunnel_key_params *p)
+{
+ if (!p)
+ return;
+ call_rcu(&p->rcu, tunnel_key_release_params_rcu);
}
static int tunnel_key_init(struct net *net, struct nlattr *nla,
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 111/602] sctp: fix auth_hmacs array size in struct sctp_cookie
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (109 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 110/602] net/sched: act_tunnel_key: Defer dst_release to RCU callback Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 112/602] mpls: fix NULL deref in mpls_valid_fib_dump_req() on CONFIG_INET=n Greg Kroah-Hartman
` (494 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yuan Tan, Xin Liu, Zihan Xi, Ren Wei,
Xin Long, Paolo Abeni, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xin Long <lucien.xin@gmail.com>
[ Upstream commit e0b5252a59383b77d1b8dbeda00b7184dd95f4d3 ]
The auth_hmacs array in struct sctp_cookie is supposed to store a complete
SCTP_AUTH_HMAC_ALGO parameter, which consists of a struct sctp_paramhdr
followed by N HMAC identifiers.
However, the array size was calculated using an extra 2 bytes instead of
sizeof(struct sctp_paramhdr), which is 4 bytes. When four HMAC identifiers
are configured, the HMAC-ALGO parameter stored in the endpoint is larger
than the auth_hmacs buffer in the cookie.
As a result, sctp_association_init() copies beyond the end of auth_hmacs
when initializing the association, corrupting the adjacent auth_chunks
field. This can lead to an invalid HMAC identifier being accepted and later
cause an out-of-bounds read in sctp_auth_get_hmac().
Fix the array size calculation by including the full SCTP parameter header
size.
Fixes: 1f485649f529 ("[SCTP]: Implement SCTP-AUTH internals")
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Xin Liu <dstsmallbird@foxmail.com>
Reported-by: Zihan Xi <xizh2024@lzu.edu.cn>
Reported-by: Ren Wei <enjou1224z@gmail.com>
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Link: https://patch.msgid.link/634a0de0d5de29532915e6d47c92a0cbc206e03f.1783707155.git.lucien.xin@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
include/net/sctp/structs.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index dcd288fa1bb6fb..d20c28c3105664 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -319,7 +319,8 @@ struct sctp_cookie {
__u8 auth_random[sizeof(struct sctp_paramhdr) +
SCTP_AUTH_RANDOM_LENGTH];
- __u8 auth_hmacs[SCTP_AUTH_NUM_HMACS * sizeof(__u16) + 2];
+ __u8 auth_hmacs[sizeof(struct sctp_paramhdr) +
+ SCTP_AUTH_NUM_HMACS * sizeof(__u16)];
__u8 auth_chunks[sizeof(struct sctp_paramhdr) + SCTP_AUTH_MAX_CHUNKS];
/* This is a shim for my peer's INIT packet, followed by
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 112/602] mpls: fix NULL deref in mpls_valid_fib_dump_req() on CONFIG_INET=n
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (110 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 111/602] sctp: fix auth_hmacs array size in struct sctp_cookie Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 113/602] usb: core: sysfs: add lock to bos_descriptors_read() Greg Kroah-Hartman
` (493 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Xiang Mei, Weiming Shi, David Ahern,
Paolo Abeni, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiming Shi <bestswngs@gmail.com>
[ Upstream commit 56d96fededd61192cd7cc8d2b0f36adfd59036c3 ]
On CONFIG_INET=n builds, mpls_valid_fib_dump_req() walks the parsed
attribute table itself instead of calling ip_valid_fib_dump_req(). The
RTA_OIF arm passes tb[RTA_OIF] to nla_get_u32() without checking it is
present, so an RTM_GETROUTE dump for AF_MPLS with strict checking and no
RTA_OIF hits a NULL dereference.
RTM_GETROUTE is RTNL_KIND_GET, which rtnetlink_rcv_msg() permits without
CAP_NET_ADMIN, so an unprivileged user can trigger it.
Oops: general protection fault, probably for non-canonical address
0xdffffc0000000000: 0000 [#1] SMP KASAN NOPTI
KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
RIP: 0010:mpls_valid_fib_dump_req (net/mpls/af_mpls.c:2189)
Call Trace:
mpls_dump_routes (net/mpls/af_mpls.c:2236)
netlink_dump (net/netlink/af_netlink.c:2331)
__netlink_dump_start (net/netlink/af_netlink.c:2446)
rtnetlink_rcv_msg (net/core/rtnetlink.c:7033)
netlink_rcv_skb (net/netlink/af_netlink.c:2556)
netlink_unicast (net/netlink/af_netlink.c:1345)
netlink_sendmsg (net/netlink/af_netlink.c:1900)
__sock_sendmsg (net/socket.c:790)
____sys_sendmsg (net/socket.c:2684)
___sys_sendmsg (net/socket.c:2738)
__sys_sendmsg (net/socket.c:2770)
do_syscall_64 (arch/x86/entry/syscall_64.c:94)
entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
Skip unset attributes, as ip_valid_fib_dump_req() does.
Fixes: 196cfebf8972 ("net/mpls: Handle kernel side filtering of route dumps")
Assisted-by: Claude:claude-opus-4-8
Reported-by: Xiang Mei <xmei5@asu.edu>
Signed-off-by: Weiming Shi <bestswngs@gmail.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Link: https://patch.msgid.link/20260711114958.1009619-3-bestswngs@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/mpls/af_mpls.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index 719dabb76ea218..98816e51e01a49 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -2123,6 +2123,9 @@ static int mpls_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh,
int ifindex;
if (i == RTA_OIF) {
+ if (!tb[i])
+ continue;
+
ifindex = nla_get_u32(tb[i]);
filter->dev = __dev_get_by_index(net, ifindex);
if (!filter->dev)
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 113/602] usb: core: sysfs: add lock to bos_descriptors_read()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (111 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 112/602] mpls: fix NULL deref in mpls_valid_fib_dump_req() on CONFIG_INET=n Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 114/602] wifi: at76c50x-usb: avoid length underflow in at76_guess_freq() Greg Kroah-Hartman
` (492 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Griffin Kroah-Hartman, Alan Stern,
stable
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Griffin Kroah-Hartman <griffin@kroah.com>
commit 4e0197fbb0eec588795d5431716a244d9ac8fa93 upstream.
Add a lock to the function bos_descriptors_read().
This function accesses udev->bos, which could be simultaneously freed in
usb_reset_and_verify_device(), a function that is commonly called in
drivers all over the kernel.
Assisted-by: gkh_clanker_t1000
Signed-off-by: Griffin Kroah-Hartman <griffin@kroah.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Cc: stable <stable@kernel.org>
Link: https://patch.msgid.link/20260715-usb_core_patches_3-v1-1-53021f5576fd@kroah.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/core/sysfs.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -899,10 +899,15 @@ bos_descriptors_read(struct file *filp,
{
struct device *dev = kobj_to_dev(kobj);
struct usb_device *udev = to_usb_device(dev);
- struct usb_host_bos *bos = udev->bos;
+ struct usb_host_bos *bos;
struct usb_bos_descriptor *desc;
size_t desclen, n = 0;
+ int rc;
+ rc = usb_lock_device_interruptible(udev);
+ if (rc < 0)
+ return -EINTR;
+ bos = udev->bos;
if (bos) {
desc = bos->desc;
desclen = le16_to_cpu(desc->wTotalLength);
@@ -911,6 +916,7 @@ bos_descriptors_read(struct file *filp,
memcpy(buf, (void *) desc + off, n);
}
}
+ usb_unlock_device(udev);
return n;
}
static BIN_ATTR_RO(bos_descriptors, 65535); /* max-size BOS */
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 114/602] wifi: at76c50x-usb: avoid length underflow in at76_guess_freq()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (112 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 113/602] usb: core: sysfs: add lock to bos_descriptors_read() Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 115/602] usb: core: port: Deattach Type-C connector on component unbind Greg Kroah-Hartman
` (491 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Huihui Huang, Johannes Berg
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Huihui Huang <hhhuang@smu.edu.sg>
commit 61a799ffd1e5a4fd3702d547828b7ff3d161468e upstream.
at76_guess_freq() checks only that the received frame is at least a bare
802.11 header (24 bytes) before subtracting the fixed management-body
offset:
len -= el_off;
For both beacon and probe response frames, el_off is 36. If the frame is
shorter than el_off, subtracting it causes the calculated IE length to
wrap. The length is eventually passed to cfg80211_find_elem_match() as a
very large unsigned value, so the element walk runs beyond the RX skb.
This path is reached from at76_rx_tasklet() while scanning. If the device
delivers a truncated beacon or probe response, the oversized IE length
causes an out-of-bounds read during scanning.
Skip the IE lookup if the frame does not reach the variable elements,
before subtracting el_off.
Fixes: 1264b951463a ("at76c50x-usb: add driver")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Huihui Huang <hhhuang@smu.edu.sg>
Link: https://patch.msgid.link/20260715140815.1242033-1-hhhuang@smu.edu.sg
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/wireless/atmel/at76c50x-usb.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
--- a/drivers/net/wireless/atmel/at76c50x-usb.c
+++ b/drivers/net/wireless/atmel/at76c50x-usb.c
@@ -1521,13 +1521,16 @@ static inline int at76_guess_freq(struct
if (ieee80211_is_probe_resp(hdr->frame_control)) {
el_off = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
- el = ((struct ieee80211_mgmt *)hdr)->u.probe_resp.variable;
} else if (ieee80211_is_beacon(hdr->frame_control)) {
el_off = offsetof(struct ieee80211_mgmt, u.beacon.variable);
- el = ((struct ieee80211_mgmt *)hdr)->u.beacon.variable;
} else {
goto exit;
}
+
+ if (len < el_off)
+ goto exit;
+
+ el = priv->rx_skb->data + el_off;
len -= el_off;
el = cfg80211_find_ie(WLAN_EID_DS_PARAMS, el, len);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 115/602] usb: core: port: Deattach Type-C connector on component unbind
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (113 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 114/602] wifi: at76c50x-usb: avoid length underflow in at76_guess_freq() Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 116/602] USB: storage: add NO_ATA_1X quirk for Longmai USB Key Greg Kroah-Hartman
` (490 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, stable, Chia-Lin Kao (AceLan),
Heikki Krogerus
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chia-Lin Kao (AceLan) <acelan.kao@canonical.com>
commit e0b291fe117964037e0ba382eff4bb365d531c3a upstream.
connector_unbind() is the mirror of connector_bind(), but it is missing
the symmetric call to typec_deattach() that connector_bind() makes via:
if (port_dev->child)
typec_attach(port_dev->connector, &port_dev->child->dev);
When a Thunderbolt dock is unplugged, two teardown paths race:
1. The component framework calls connector_unbind() first, which sets
port_dev->connector = NULL without calling typec_deattach(). This
leaves port->usb2_dev/port->usb3_dev in struct typec_port pointing at
the USB device that is about to be freed.
2. usb_disconnect() then calls typec_deattach(port_dev->connector, ...),
but port_dev->connector is already NULL, so the call is a no-op and
port->usb2_dev is never cleared.
3. Concurrently, UCSI detects a PD partner-disconnect event and calls
typec_unregister_partner(), which reads port->usb2_dev (now a dangling
pointer to freed memory) and passes it to typec_partner_unlink_device()
-> sysfs_remove_link() -> dev_name() on the freed device, corrupting
the typec/UCSI partner state.
This corruption leaves the Thunderbolt tunnel in an inconsistent state on
the next dock hot-plug. On affected hardware the dock's I225/igc NIC fails
to enumerate: AER fires a slot reset while the igc driver is still
initialising ("PCIe link lost"), and the subsequent igc_reset attempt hits
igc_rd32 on an already-detached device:
igc 0000:2e:00.0 eth0: PCIe link lost, device now detached
igc: Failed to read reg 0x0!
WARNING: CPU: 9 PID: 129 at drivers/net/ethernet/intel/igc/igc_main.c:7005
igc_rd32+0xa4/0xc0 [igc]
Call Trace:
igc_disable_pcie_master+0x16/0xa0 [igc]
igc_reset_hw_base+0x14/0x170 [igc]
igc_reset+0x63/0x110 [igc]
igc_io_slot_reset+0x9e/0xd0 [igc]
report_slot_reset+0x5d/0xc0
pcie_do_recovery+0x209/0x400
aer_isr_one_error_type+0x235/0x430
aer_isr+0x4e/0x80
irq_thread+0xf4/0x1f0
4. UCSI later handles the PD partner-disconnect and calls
typec_unregister_partner(), which still sees the stale port->usb2_dev
and tries to remove its sysfs link a second time:
kernfs: can not remove 'typec', no directory
WARNING: CPU: 6 PID: 55 at fs/kernfs/dir.c:1706 kernfs_remove_by_name_ns+0xe9/0xf0
Workqueue: events ucsi_handle_connector_change [typec_ucsi]
Call Trace:
sysfs_remove_link+0x19/0x50
typec_unregister_partner+0x6e/0x120 [typec]
ucsi_unregister_partner+0x107/0x150 [typec_ucsi]
ucsi_handle_connector_change+0x3ec/0x490 [typec_ucsi]
process_one_work+0x18e/0x3e0
worker_thread+0x2e3/0x420
kthread+0x10a/0x230
ret_from_fork+0x121/0x140
ret_from_fork_asm+0x1a/0x30
With worse timing the same stale pointer is dereferenced after the
backing memory is freed, turning the warning into a use-after-free.
Fix the asymmetry: call typec_deattach() before clearing
port_dev->connector, matching what connector_bind() does on the bind side.
typec_partner_deattach() is already protected by port->partner_link_lock,
so it serialises safely with the concurrent typec_unregister_partner() path.
Fixes: 11110783f5ea ("usb: Inform the USB Type-C class about enumerated devices")
Cc: stable <stable@kernel.org>
Signed-off-by: Chia-Lin Kao (AceLan) <acelan.kao@canonical.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://patch.msgid.link/20260611071201.1235545-1-acelan.kao@canonical.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/core/port.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -724,6 +724,8 @@ static void connector_unbind(struct devi
sysfs_remove_link(&connector->kobj, dev_name(dev));
sysfs_remove_link(&dev->kobj, "connector");
+ if (port_dev->child)
+ typec_deattach(port_dev->connector, &port_dev->child->dev);
port_dev->connector = NULL;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 116/602] USB: storage: add NO_ATA_1X quirk for Longmai USB Key
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (114 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 115/602] usb: core: port: Deattach Type-C connector on component unbind Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 117/602] usb: chipidea: fix usage_count leak when autosuspend_delay is negative Greg Kroah-Hartman
` (489 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Ai Chao, stable, Huang Wei,
Alan Stern
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Huang Wei <huangwei@kylinos.cn>
commit 3b4ca2e01c1dd8c00b675b794732945f460a471b upstream.
The Longmai Technologies USB Key (0x04b4:0xb708) advertises itself as a
SCSI/Bulk-only mass storage device but does not correctly handle ATA
pass-through commands. When such a command (ATA_12 or ATA_16) is sent to
the device it fails to respond and the transfer eventually times out,
leaving the device unusable.
Add an unusual_devs entry for this device that sets the US_FL_NO_ATA_1X
flag, so usb-storage short-circuits ATA pass-through commands and returns
INVALID COMMAND OPERATION CODE (0x20 0x05 0x24 0x00) instead of forwarding
them to the device.
Information about the device in /sys/kernel/debug/usb/devices:
T: Bus=02 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 12 Spd=480 MxCh= 0
D: Ver= 2.00 Cls=00(>ifc ) Sub=06 Prot=50 MxPS=64 #Cfgs= 1
P: Vendor=04b4 ProdID=b708 Rev= 1.00
S: Manufacturer=Longmai Technologies
S: Product=USB Key
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr=100mA
I:* If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage
E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
Reported-by: Ai Chao <aichao@kylinos.cn>
Cc: stable <stable@kernel.org>
Signed-off-by: Huang Wei <huangwei@kylinos.cn>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Link: https://patch.msgid.link/20260716033341.2830872-1-huangwei@kylinos.cn
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/storage/unusual_devs.h | 7 +++++++
1 file changed, 7 insertions(+)
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -395,6 +395,13 @@ UNUSUAL_DEV( 0x04b3, 0x4001, 0x0110, 0x
USB_SC_DEVICE, USB_PR_CB, NULL,
US_FL_MAX_SECTORS_MIN),
+/* Reported by Ai Chao <aichao@kylinos.cn> */
+UNUSUAL_DEV( 0x04b4, 0xb708, 0x0000, 0xffff,
+ "Longmai Technologies",
+ "USB Key",
+ USB_SC_SCSI, USB_PR_BULK, NULL,
+ US_FL_NO_ATA_1X),
+
/*
* Reported by Simon Levitt <simon@whattf.com>
* This entry needs Sub and Proto fields
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 117/602] usb: chipidea: fix usage_count leak when autosuspend_delay is negative
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (115 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 116/602] USB: storage: add NO_ATA_1X quirk for Longmai USB Key Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 118/602] usb: gadget: dummy_hcd: prevent fifo_req reuse during giveback Greg Kroah-Hartman
` (488 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, stable, Xu Yang, Frank Li
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xu Yang <xu.yang_2@nxp.com>
commit fc3afb5728e297994863f8a2a01b88a920bbf53e upstream.
The probe() calls pm_runtime_use_autosuspend(), but remove() does not call
pm_runtime_dont_use_autosuspend(). This can lead to a usage_count leak if
autosuspend_delay is set to a negative value.
The pm_runtime_use_autosuspend() also notes that it's important to undo
this with pm_runtime_dont_use_autosuspend() at driver exit time.
Fixes: 1f874edcb731 ("usb: chipidea: add runtime power management support")
Cc: stable <stable@kernel.org>
Assisted-by: Claude:claude-sonnet-4.6
Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20260716104126.2763454-1-xu.yang_2@oss.nxp.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/chipidea/core.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -1265,6 +1265,7 @@ static void ci_hdrc_remove(struct platfo
usb_role_switch_unregister(ci->role_switch);
if (ci->supports_runtime_pm) {
+ pm_runtime_dont_use_autosuspend(&pdev->dev);
pm_runtime_get_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
pm_runtime_put_noidle(&pdev->dev);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 118/602] usb: gadget: dummy_hcd: prevent fifo_req reuse during giveback
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (116 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 117/602] usb: chipidea: fix usage_count leak when autosuspend_delay is negative Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 119/602] usb: gadget: f_midi: cancel pending IN work before freeing the midi object Greg Kroah-Hartman
` (487 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, syzbot+faf3a6cf579fc65591ca, stable,
Jinchao Wang, Alan Stern
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jinchao Wang <wangjinchao600@gmail.com>
commit d5e5cd3654d2b5359a12ea6586120f05b28634ee upstream.
dummy_hcd embeds a single shared usb_request (dum->fifo_req) that the
"emulated single-request FIFO" fast-path in dummy_queue() reuses for
small IN transfers: it copies the caller's request into it
(req->req = *_req) and queues it, treating list_empty(&fifo_req.queue)
as "the slot is free".
The completion side (dummy_timer/transfer/nuke/dummy_dequeue) follows
the standard pattern: list_del_init(&req->queue) unlinks the request,
then the lock is dropped and usb_gadget_giveback_request() invokes
req->complete(). But list_del_init() makes fifo_req.queue look empty
*before* the completion callback returns, so a concurrent dummy_queue()
on another CPU sees the slot as free, reuses fifo_req and runs
req->req = *_req -- overwriting req->complete while dummy_timer is
mid-calling it. The indirect call then jumps to a clobbered pointer,
causing a general protection fault / page fault in dummy_timer
(syzkaller extid faf3a6cf579fc65591ca). The clobbering write is an
in-bounds memcpy on a live shared object, so KASAN cannot flag it.
Add a fifo_req_busy bit covering the shared request's whole lifetime:
set it in dummy_queue() when the FIFO fast-path takes fifo_req (making
it the fast-path guard, replacing the list_empty(&fifo_req.queue)
test), and clear it after the completion callback has returned, via a
dummy_giveback() helper used at all four gadget-request giveback
sites. The shared slot can no longer be reused until its completion
callback has finished.
Reported-by: syzbot+faf3a6cf579fc65591ca@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=faf3a6cf579fc65591ca
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable <stable@kernel.org>
Signed-off-by: Jinchao Wang <wangjinchao600@gmail.com>
Reviewed-by: Alan Stern <stern@rowland.harvard.edu>
Link: https://patch.msgid.link/5db8bba5b3499a86cd2e776f9918126b68b2508b.1784198306.git.wangjinchao600@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/gadget/udc/dummy_hcd.c | 40 ++++++++++++++++++++++++-------------
1 file changed, 27 insertions(+), 13 deletions(-)
--- a/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
@@ -277,6 +277,7 @@ struct dummy {
unsigned ints_enabled:1;
unsigned udc_suspended:1;
unsigned pullup:1;
+ unsigned fifo_req_busy:1;
/*
* HOST side support
@@ -328,6 +329,26 @@ static inline struct dummy *gadget_dev_t
/* DEVICE/GADGET SIDE UTILITY ROUTINES */
+/*
+ * Give back a gadget request with dum->lock dropped around the callback.
+ * If @req is the shared fifo_req, clear fifo_req_busy afterward: the flag
+ * was set in dummy_queue() when the shared request was taken and must stay
+ * set until its completion callback has returned; list_del_init() alone
+ * makes the request look idle while the callback is still running.
+ * Caller holds dum->lock and has already done list_del_init() + status.
+ */
+static void dummy_giveback(struct dummy *dum, struct usb_ep *_ep,
+ struct dummy_request *req)
+{
+ bool fifo = req == &dum->fifo_req;
+
+ spin_unlock(&dum->lock);
+ usb_gadget_giveback_request(_ep, &req->req);
+ spin_lock(&dum->lock);
+ if (fifo)
+ dum->fifo_req_busy = 0;
+}
+
/* called with spinlock held */
static void nuke(struct dummy *dum, struct dummy_ep *ep)
{
@@ -338,9 +359,7 @@ static void nuke(struct dummy *dum, stru
list_del_init(&req->queue);
req->req.status = -ESHUTDOWN;
- spin_unlock(&dum->lock);
- usb_gadget_giveback_request(&ep->ep, &req->req);
- spin_lock(&dum->lock);
+ dummy_giveback(dum, &ep->ep, req);
}
}
@@ -727,10 +746,11 @@ static int dummy_queue(struct usb_ep *_e
/* implement an emulated single-request FIFO */
if (ep->desc && (ep->desc->bEndpointAddress & USB_DIR_IN) &&
- list_empty(&dum->fifo_req.queue) &&
+ !dum->fifo_req_busy &&
list_empty(&ep->queue) &&
_req->length <= FIFO_SIZE) {
req = &dum->fifo_req;
+ dum->fifo_req_busy = 1;
req->req = *_req;
req->req.buf = dum->fifo_buf;
memcpy(dum->fifo_buf, _req->buf, _req->length);
@@ -784,9 +804,7 @@ static int dummy_dequeue(struct usb_ep *
dev_dbg(udc_dev(dum),
"dequeued req %p from %s, len %d buf %p\n",
req, _ep->name, _req->length, _req->buf);
- spin_unlock(&dum->lock);
- usb_gadget_giveback_request(_ep, _req);
- spin_lock(&dum->lock);
+ dummy_giveback(dum, _ep, req);
}
spin_unlock_irqrestore(&dum->lock, flags);
return retval;
@@ -1522,9 +1540,7 @@ top:
if (req->req.status != -EINPROGRESS) {
list_del_init(&req->queue);
- spin_unlock(&dum->lock);
- usb_gadget_giveback_request(&ep->ep, &req->req);
- spin_lock(&dum->lock);
+ dummy_giveback(dum, &ep->ep, req);
/* requests might have been unlinked... */
rescan = 1;
@@ -1908,9 +1924,7 @@ restart:
dev_dbg(udc_dev(dum), "stale req = %p\n",
req);
- spin_unlock(&dum->lock);
- usb_gadget_giveback_request(&ep->ep, &req->req);
- spin_lock(&dum->lock);
+ dummy_giveback(dum, &ep->ep, req);
ep->already_seen = 0;
goto restart;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 119/602] usb: gadget: f_midi: cancel pending IN work before freeing the midi object
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (117 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 118/602] usb: gadget: dummy_hcd: prevent fifo_req reuse during giveback Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 120/602] usb: gadget: printer: fix infinite loop in printer_read() Greg Kroah-Hartman
` (486 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, stable, Fan Wu
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fan Wu <fanwu01@zju.edu.cn>
commit 5650c18d93a1db7e27cb5a40b394747eb4686d5b upstream.
The f_midi driver embeds a work item (midi->work) whose handler,
f_midi_in_work(), dereferences the enclosing struct f_midi through
container_of(). This work is armed from two sites: f_midi_complete(),
on a normal IN-endpoint completion, and f_midi_in_trigger(), on an ALSA
rawmidi output-stream start.
Neither f_midi_disable() nor f_midi_unbind() cancels midi->work.
f_midi_disable() only disables the endpoints and drains the in_req_fifo;
it does not synchronize the work item, and the sound card is released
asynchronously to the final free of the midi object.
The midi object is reference-counted (midi->free_ref) and is freed in
f_midi_free() only once both the usb_function reference and the rawmidi
private_data reference have been dropped. In f_midi_unbind(),
f_midi_disable() runs before the sound card is released, so while the
USB endpoints are already disabled the rawmidi device is still usable by
an open substream. A concurrent userspace write on such a substream can
reach f_midi_in_trigger() and queue midi->work again after
f_midi_disable() has returned. A work item armed this way may still be
pending when the last reference drops and f_midi_free() proceeds to
kfree(midi), letting f_midi_in_work() dereference the struct after it
has been freed, a use-after-free.
For this reason cancelling midi->work in f_midi_disable() would not be
sufficient: the ALSA trigger path can rearm the work after disable()
returns. Cancelling at the refcount-zero free site is the boundary
after which neither arming source can survive, because by then both
references that keep the midi object alive have been dropped: the USB
endpoints are already disabled and the rawmidi device has been released.
Fix this by calling cancel_work_sync(&midi->work) in the refcount-zero
block of f_midi_free(), before the embedded work_struct is freed along
with the rest of the structure. opts->lock is a sleeping mutex, so
calling cancel_work_sync() under it is permitted, and the handler takes
midi->transmit_lock rather than opts->lock, so no self-deadlock can
occur while it waits for a running instance of the work to finish.
This issue was found by an in-house static analysis tool.
Fixes: 8653d71ce3763 ("usb/gadget: f_midi: Replace tasklet with work")
Cc: stable <stable@kernel.org>
Assisted-by: Codex:gpt-5.5
Signed-off-by: Fan Wu <fanwu01@zju.edu.cn>
Link: https://patch.msgid.link/20260709150717.399083-1-fanwu01@zju.edu.cn
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/gadget/function/f_midi.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/usb/gadget/function/f_midi.c
+++ b/drivers/usb/gadget/function/f_midi.c
@@ -1302,6 +1302,7 @@ static void f_midi_free(struct usb_funct
opts = container_of(f->fi, struct f_midi_opts, func_inst);
mutex_lock(&opts->lock);
if (!--midi->free_ref) {
+ cancel_work_sync(&midi->work);
kfree(midi->id);
kfifo_free(&midi->in_req_fifo);
kfree(midi);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 120/602] usb: gadget: printer: fix infinite loop in printer_read()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (118 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 119/602] usb: gadget: f_midi: cancel pending IN work before freeing the midi object Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 121/602] USB: gadget: snps-udc: fix device name leak on probe failure Greg Kroah-Hartman
` (485 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, stable, Peter Chen, Melbin K Mathew
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Melbin K Mathew <mlbnkm1@gmail.com>
commit c2e819be6a5c7f34344926b4bd7e3dfca58cf48a upstream.
printer_read() uses the same variable for the requested copy size and
the number of bytes actually copied to user space. copy_to_user()
returns the number of bytes not copied, so when it fails to copy
anything, the computed copied length becomes zero.
In that case len, buf, current_rx_bytes and current_rx_buf are left
unchanged. If RX data is available and the user buffer remains
unwritable, the read loop can repeat indefinitely.
Track the copied length separately and return -EFAULT, or the number of
bytes already copied, if an iteration makes no progress.
Fixes: b185f01a9ab7 ("usb: gadget: printer: factor out f_printer")
Cc: stable <stable@kernel.org>
Reviewed-by: Peter Chen <peter.chen@kernel.org>
Signed-off-by: Melbin K Mathew <mlbnkm1@gmail.com>
Link: https://patch.msgid.link/20260709205622.55700-1-mlbnkm1@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/gadget/function/f_printer.c | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
--- a/drivers/usb/gadget/function/f_printer.c
+++ b/drivers/usb/gadget/function/f_printer.c
@@ -431,7 +431,7 @@ printer_read(struct file *fd, char __use
{
struct printer_dev *dev = fd->private_data;
unsigned long flags;
- size_t size;
+ size_t size, not_copied, copied;
size_t bytes_copied;
struct usb_request *req;
/* This is a pointer to the current USB rx request. */
@@ -524,10 +524,12 @@ printer_read(struct file *fd, char __use
else
size = len;
- size -= copy_to_user(buf, current_rx_buf, size);
- bytes_copied += size;
- len -= size;
- buf += size;
+ not_copied = copy_to_user(buf, current_rx_buf, size);
+ copied = size - not_copied;
+
+ bytes_copied += copied;
+ len -= copied;
+ buf += copied;
spin_lock_irqsave(&dev->lock, flags);
@@ -542,6 +544,17 @@ printer_read(struct file *fd, char __use
if (dev->interface < 0)
goto out_disabled;
+ if (!copied) {
+ dev->current_rx_req = current_rx_req;
+ dev->current_rx_bytes = current_rx_bytes;
+ dev->current_rx_buf = current_rx_buf;
+ spin_unlock_irqrestore(&dev->lock, flags);
+ mutex_unlock(&dev->lock_printer_io);
+ return bytes_copied ? bytes_copied : -EFAULT;
+ }
+
+ size = copied;
+
/* If we not returning all the data left in this RX request
* buffer then adjust the amount of data left in the buffer.
* Othewise if we are done with this RX request buffer then
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 121/602] USB: gadget: snps-udc: fix device name leak on probe failure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (119 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 120/602] usb: gadget: printer: fix infinite loop in printer_read() Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 122/602] USB: gadget: fsl-udc: " Greg Kroah-Hartman
` (484 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, stable, Johan Hovold
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <johan@kernel.org>
commit 29a142d3e8b35ebc9e0bcc78f4bc26c9b6a9ac0b upstream.
The gadget device name is set by UDC core when registering the gadget
and must not be set before to avoid leaking the name in intermediate
error paths (e.g. when detecting an older chip revision).
Fixes: 12ad0fcaf2fb ("usb: gadget: amd5536udc: let udc-core manage gadget->dev")
Cc: stable <stable@kernel.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
Link: https://patch.msgid.link/20260702141536.90887-3-johan@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/gadget/udc/snps_udc_core.c | 1 -
1 file changed, 1 deletion(-)
--- a/drivers/usb/gadget/udc/snps_udc_core.c
+++ b/drivers/usb/gadget/udc/snps_udc_core.c
@@ -3133,7 +3133,6 @@ int udc_probe(struct udc *dev)
/* device struct setup */
dev->gadget.ops = &udc_ops;
- dev_set_name(&dev->gadget.dev, "gadget");
dev->gadget.name = name;
dev->gadget.max_speed = USB_SPEED_HIGH;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 122/602] USB: gadget: fsl-udc: fix device name leak on probe failure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (120 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 121/602] USB: gadget: snps-udc: fix device name leak on probe failure Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 123/602] usb: gadget: f_ncm: validate datagram bounds in ncm_unwrap_ntb() Greg Kroah-Hartman
` (483 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, stable, Johan Hovold
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <johan@kernel.org>
commit 6b874d00c466e73c6448a89856407fe46b2f50e4 upstream.
The gadget device name is set by UDC core when registering the gadget
and must not be set before to avoid leaking the name in intermediate
error paths (e.g. on dma pool creation failure).
Fixes: eab35c4e6d95 ("usb: gadget: fsl_udc_core: let udc-core manage gadget->dev")
Cc: stable <stable@kernel.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
Link: https://patch.msgid.link/20260702141536.90887-2-johan@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/gadget/udc/fsl_udc_core.c | 1 -
1 file changed, 1 deletion(-)
--- a/drivers/usb/gadget/udc/fsl_udc_core.c
+++ b/drivers/usb/gadget/udc/fsl_udc_core.c
@@ -2473,7 +2473,6 @@ static int fsl_udc_probe(struct platform
udc_controller->gadget.name = driver_name;
/* Setup gadget.dev and register with kernel */
- dev_set_name(&udc_controller->gadget.dev, "gadget");
udc_controller->gadget.dev.of_node = pdev->dev.of_node;
if (!IS_ERR_OR_NULL(udc_controller->transceiver))
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 123/602] usb: gadget: f_ncm: validate datagram bounds in ncm_unwrap_ntb()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (121 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 122/602] USB: gadget: fsl-udc: " Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 124/602] usb: gadget: udc: bdc: free IRQ and drain func_wake_notify before teardown Greg Kroah-Hartman
` (482 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, stable, Sonali Pradhan
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sonali Pradhan <sonalipradhan@google.com>
commit 1febec7e47cdcd01f43fb0211094e3010474666e upstream.
When unpacking host-supplied NTBs, ncm_unwrap_ntb() checks datagram length
against frame_max but does not verify that the datagram fits within the
declared block length. Additionally, when decoding multiple NTBs from a
single socket buffer, subsequent block lengths are not checked against the
actual remaining buffer data.
With these checks missing, a malicious USB host can specify datagram
offsets and lengths that point beyond the block, or supply secondary NTB
headers declaring lengths larger than the buffer. skb_put_data() then
copies adjacent kernel memory from skb_shared_info into the network skb.
Fix this by verifying that sufficient buffer space remains for the NTB
header before parsing, handling zero-length block declarations, ensuring
that block lengths never exceed the remaining buffer space, and verifying
that each datagram payload stays strictly within the block boundary.
Fixes: 427694cfaafa ("usb: gadget: ncm: Handle decoding of multiple NTB's in unwrap call")
Fixes: 2b74b0a04d3e ("USB: gadget: f_ncm: add bounds checks to ncm_unwrap_ntb()")
Cc: stable <stable@kernel.org>
Assisted-by: Jetski:Gemini-2.5-Pro
Signed-off-by: Sonali Pradhan <sonalipradhan@google.com>
Link: https://patch.msgid.link/20260703083725.1903850-1-sonalipradhan@google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/gadget/function/f_ncm.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
--- a/drivers/usb/gadget/function/f_ncm.c
+++ b/drivers/usb/gadget/function/f_ncm.c
@@ -1188,6 +1188,10 @@ static int ncm_unwrap_ntb(struct gether
frame_max = ncm_opts->max_segment_size;
parse_ntb:
+ if (to_process < (int)opts->nth_size) {
+ INFO(port->func.config->cdev, "Packet too small for headers\n");
+ goto err;
+ }
tmp = (__le16 *)ntb_ptr;
/* dwSignature */
@@ -1208,8 +1212,12 @@ parse_ntb:
tmp++; /* skip wSequence */
block_len = get_ncm(&tmp, opts->block_length);
+ if (block_len == 0)
+ block_len = to_process;
+
/* (d)wBlockLength */
- if ((block_len < opts->nth_size + opts->ndp_size) || (block_len > ntb_max)) {
+ if ((block_len < opts->nth_size + opts->ndp_size) || (block_len > ntb_max) ||
+ (block_len > to_process)) {
INFO(port->func.config->cdev, "Bad block length: %#X\n", block_len);
goto err;
}
@@ -1272,7 +1280,7 @@ parse_ntb:
index = index2;
/* wDatagramIndex[0] */
if ((index < opts->nth_size) ||
- (index > block_len - opts->dpe_size)) {
+ (index > block_len)) {
INFO(port->func.config->cdev,
"Bad index: %#X\n", index);
goto err;
@@ -1284,7 +1292,8 @@ parse_ntb:
* ethernet hdr + crc or larger than max frame size
*/
if ((dg_len < 14 + crc_len) ||
- (dg_len > frame_max)) {
+ (dg_len > frame_max) ||
+ (dg_len > block_len - index)) {
INFO(port->func.config->cdev,
"Bad dgram length: %#X\n", dg_len);
goto err;
@@ -1309,7 +1318,7 @@ parse_ntb:
dg_len2 = get_ncm(&tmp, opts->dgram_item_len);
/* wDatagramIndex[1] */
- if (index2 > block_len - opts->dpe_size) {
+ if (index2 > block_len) {
INFO(port->func.config->cdev,
"Bad index: %#X\n", index2);
goto err;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 124/602] usb: gadget: udc: bdc: free IRQ and drain func_wake_notify before teardown
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (122 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 123/602] usb: gadget: f_ncm: validate datagram bounds in ncm_unwrap_ntb() Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 125/602] usb: gadget: uvc: clamp SEND_RESPONSE length to the response buffer Greg Kroah-Hartman
` (481 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, stable, Fan Wu
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fan Wu <fanwu01@zju.edu.cn>
commit 0583f2fbf8f86ae3a0ce054f96783dd83e65d9bb upstream.
The Broadcom BDC UDC driver registers its IRQ handler with
devm_request_irq() in bdc_udc_init(), so the IRQ is released by devm
only after bdc_remove() returns. devm releases resources in reverse
LIFO order, but bdc_remove() runs bdc_udc_exit() and bdc_hw_exit() ->
bdc_mem_free() manually before returning: bdc_udc_exit() tears down
individual endpoint objects via bdc_free_ep(), while bdc_hw_exit() ->
bdc_mem_free() frees and NULLs the DMA-coherent status-report ring
(bdc->srr.sr_bds) and kfree()s bdc->bdc_ep_array. Both happen while
the IRQ handler (bdc_udc_interrupt, requested with IRQF_SHARED)
remains deliverable in the window up to the post-remove devm
free_irq().
On receipt of a shared interrupt in that window, bdc_udc_interrupt()
dereferences bdc->srr.sr_bds[bdc->srr.dqp_index] (NULL or freed DMA)
and dispatches sr_handler callbacks that index into bdc_ep_array,
causing a NULL-deref or use-after-free.
The same window affects the delayed_work bdc->func_wake_notify, which is
armed from the IRQ handler via bdc_sr_uspc() -> handle_link_state_change()
-> schedule_delayed_work() and may self-rearm from its own callback
bdc_func_wake_timer(). No cancel exists anywhere in the driver, so a
queued work item that fires after bdc_remove() returns and the bdc
structure is devm-freed dereferences freed memory.
Replace devm_request_irq() with request_irq() and add an explicit
free_irq(bdc->irq, bdc) in bdc_remove(). Clear BDC_GIE before
free_irq() to stop the device from asserting interrupts, then
free_irq() drains any in-flight handler, then cancel_delayed_work_sync()
drains the func_wake_notify delayed work. This ordering ensures the
IRQ handler and delayed work cannot interfere with the subsequent
endpoint and DMA teardown in bdc_udc_exit() and bdc_hw_exit(). Wire the
matching free_irq() into the bdc_udc_init() error path so the IRQ is
released on probe failure, and route the bdc_init_ep() failure through
err0 instead of returning directly.
This issue was found by an in-house static analysis tool.
Fixes: efed421a94e6 ("usb: gadget: Add UDC driver for Broadcom USB3.0 device controller IP BDC")
Cc: stable <stable@kernel.org>
Assisted-by: Codex:gpt-5.5
Signed-off-by: Fan Wu <fanwu01@zju.edu.cn>
Link: https://patch.msgid.link/20260709020904.502611-1-fanwu01@zju.edu.cn
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/gadget/udc/bdc/bdc_core.c | 20 ++++++++++++++++++++
drivers/usb/gadget/udc/bdc/bdc_udc.c | 7 ++++---
2 files changed, 24 insertions(+), 3 deletions(-)
--- a/drivers/usb/gadget/udc/bdc/bdc_core.c
+++ b/drivers/usb/gadget/udc/bdc/bdc_core.c
@@ -586,9 +586,29 @@ disable_clk:
static void bdc_remove(struct platform_device *pdev)
{
struct bdc *bdc;
+ unsigned long flags;
+ u32 temp;
bdc = platform_get_drvdata(pdev);
dev_dbg(bdc->dev, "%s ()\n", __func__);
+ /*
+ * Disable the device interrupt source before freeing the IRQ:
+ * clear BDC_GIE so the controller stops asserting interrupts,
+ * then free_irq drains any in-flight handler.
+ */
+ spin_lock_irqsave(&bdc->lock, flags);
+ temp = bdc_readl(bdc->regs, BDC_BDCSC);
+ temp &= ~BDC_GIE;
+ bdc_writel(bdc->regs, BDC_BDCSC, temp);
+ spin_unlock_irqrestore(&bdc->lock, flags);
+ free_irq(bdc->irq, bdc);
+ /*
+ * Drain func_wake_notify after free_irq: the IRQ handler arms this
+ * delayed_work via bdc_sr_uspc -> handle_link_state_change ->
+ * schedule_delayed_work (self-rearmed in bdc_func_wake_timer), so
+ * the IRQ must be released first to prevent re-arm after cancel.
+ */
+ cancel_delayed_work_sync(&bdc->func_wake_notify);
bdc_udc_exit(bdc);
bdc_hw_exit(bdc);
bdc_phy_exit(bdc);
--- a/drivers/usb/gadget/udc/bdc/bdc_udc.c
+++ b/drivers/usb/gadget/udc/bdc/bdc_udc.c
@@ -530,8 +530,8 @@ int bdc_udc_init(struct bdc *bdc)
bdc->gadget.name = BRCM_BDC_NAME;
- ret = devm_request_irq(bdc->dev, bdc->irq, bdc_udc_interrupt,
- IRQF_SHARED, BRCM_BDC_NAME, bdc);
+ ret = request_irq(bdc->irq, bdc_udc_interrupt, IRQF_SHARED,
+ BRCM_BDC_NAME, bdc);
if (ret) {
dev_err(bdc->dev,
"failed to request irq #%d %d\n",
@@ -542,7 +542,7 @@ int bdc_udc_init(struct bdc *bdc)
ret = bdc_init_ep(bdc);
if (ret) {
dev_err(bdc->dev, "bdc init ep fail: %d\n", ret);
- return ret;
+ goto err0;
}
ret = usb_add_gadget_udc(bdc->dev, &bdc->gadget);
@@ -571,6 +571,7 @@ int bdc_udc_init(struct bdc *bdc)
err1:
usb_del_gadget_udc(&bdc->gadget);
err0:
+ free_irq(bdc->irq, bdc);
bdc_free_ep(bdc);
return ret;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 125/602] usb: gadget: uvc: clamp SEND_RESPONSE length to the response buffer
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (123 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 124/602] usb: gadget: udc: bdc: free IRQ and drain func_wake_notify before teardown Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 126/602] USB: serial: ftdi_sio: add support for E+H FXA291 Greg Kroah-Hartman
` (480 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, stable, Muhammad Bilal
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Muhammad Bilal <meatuni001@gmail.com>
commit b70dc75e85ba968b7b76eebfe5d63000080b875b upstream.
uvc_send_response() builds the UVC control response from a user-supplied
struct uvc_request_data:
req->length = min_t(unsigned int, uvc->event_length, data->length);
...
memcpy(req->buf, data->data, req->length);
req->length is clamped to uvc->event_length, which is taken from the
host control request wLength (up to UVC_MAX_REQUEST_SIZE, 64), and to
data->length, which comes from the UVCIOC_SEND_RESPONSE ioctl and is
only checked for being negative. The source buffer data->data is only
60 bytes, so a response with uvc->event_length and data->length both
greater than 60 makes memcpy() read past the end of data->data.
Clamp req->length to sizeof(data->data) as well.
Fixes: a5eaaa1f33e7 ("usb: gadget: uvc: use capped length value")
Cc: stable <stable@kernel.org>
Signed-off-by: Muhammad Bilal <meatuni001@gmail.com>
Link: https://patch.msgid.link/20260629195004.148405-1-meatuni001@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/gadget/function/uvc_v4l2.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/usb/gadget/function/uvc_v4l2.c
+++ b/drivers/usb/gadget/function/uvc_v4l2.c
@@ -191,6 +191,8 @@ uvc_send_response(struct uvc_device *uvc
return usb_ep_set_halt(cdev->gadget->ep0);
req->length = min_t(unsigned int, uvc->event_length, data->length);
+ if (req->length > sizeof(data->data))
+ req->length = sizeof(data->data);
req->zero = data->length < uvc->event_length;
memcpy(req->buf, data->data, req->length);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 126/602] USB: serial: ftdi_sio: add support for E+H FXA291
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (124 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 125/602] usb: gadget: uvc: clamp SEND_RESPONSE length to the response buffer Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 127/602] USB: serial: io_edgeport: cap received transmit credits Greg Kroah-Hartman
` (479 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Tim Pambor, Johan Hovold
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tim Pambor <timpambor@gmail.com>
commit fad0fd120e29041b3e6cdf41bb12e3184fb524a2 upstream.
The Commubox FXA291 by Endress+Hauser AG is a USB serial converter
based on FT232B which is used to communicate with field devices.
It enumerates using the FTDI vendor ID and a custom PID.
usb 1-9: New USB device found, idVendor=0403, idProduct=e510, bcdDevice= 4.00
usb 1-9: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 1-9: Product: FXA291
usb 1-9: Manufacturer: Endress+Hauser
usb 1-9: SerialNumber: 00000000
ftdi_sio 1-9:1.0: FTDI USB Serial Device converter detected
usb 1-9: Detected FT232B
usb 1-9: FTDI USB Serial Device converter now attached to ttyUSB0
Signed-off-by: Tim Pambor <timpambor@gmail.com>
Cc: stable@vger.kernel.org
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/serial/ftdi_sio.c | 2 ++
drivers/usb/serial/ftdi_sio_ids.h | 5 +++++
2 files changed, 7 insertions(+)
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1075,6 +1075,8 @@ static const struct usb_device_id id_tab
{ USB_DEVICE_INTERFACE_NUMBER(ALTERA_VID, ALTERA_UB3_602E_PID, 3) },
/* Abacus Electrics */
{ USB_DEVICE(FTDI_VID, ABACUS_OPTICAL_PROBE_PID) },
+ /* Endress+Hauser AG devices */
+ { USB_DEVICE(FTDI_VID, FTDI_EH_FXA291_PID) },
{ } /* Terminating entry */
};
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -314,6 +314,11 @@
#define FTDI_ELV_UIO88_PID 0xFB5F /* USB-I/O Interface (UIO 88) */
/*
+ * Endress+Hauser AG product ids (FTDI_VID)
+ */
+#define FTDI_EH_FXA291_PID 0xE510
+
+/*
* EVER Eco Pro UPS (http://www.ever.com.pl/)
*/
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 127/602] USB: serial: io_edgeport: cap received transmit credits
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (125 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 126/602] USB: serial: ftdi_sio: add support for E+H FXA291 Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 128/602] USB: serial: keyspan_pda: fix data loss on receive throttling Greg Kroah-Hartman
` (478 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Sunho Park, Johan Hovold
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sunho Park <shpark061104@gmail.com>
commit faaddd811c5099f11a5f52e68a6b31a5898cda4f upstream.
The interrupt-status packet reports transmit credits returned by the
device. edge_interrupt_callback() adds the 16-bit value to txCredits
without checking maxTxCredits.
edge_write() uses txCredits minus the software FIFO count as the amount
of data that fits. Since the FIFO is allocated with maxTxCredits bytes,
txCredits exceeding maxTxCredits can cause OOB write in ring buffer.
Cap accumulated credits at maxTxCredits. Conforming devices should never
hit the cap.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Assisted-by: Codex:GPT-5
Signed-off-by: Sunho Park <shpark061104@gmail.com>
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/serial/io_edgeport.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -646,7 +646,8 @@ static void edge_interrupt_callback(stru
if (edge_port && edge_port->open) {
spin_lock_irqsave(&edge_port->ep_lock,
flags);
- edge_port->txCredits += txCredits;
+ edge_port->txCredits = min(edge_port->txCredits + txCredits,
+ edge_port->maxTxCredits);
spin_unlock_irqrestore(&edge_port->ep_lock,
flags);
dev_dbg(dev, "%s - txcredits for port%d = %d\n",
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 128/602] USB: serial: keyspan_pda: fix data loss on receive throttling
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (126 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 127/602] USB: serial: io_edgeport: cap received transmit credits Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 129/602] USB: serial: option: add TDTECH MT5710-CN Greg Kroah-Hartman
` (477 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Johan Hovold
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <johan@kernel.org>
commit 42a97c0480f96a2977e6d51ce512adc780f1ef5d upstream.
Killing the interrupt-in urb when the line disciple requests throttling
may lead to data loss if an ongoing transfer is cancelled.
Instead set a flag to prevent the completion handler from resubmitting
the urb until the port is unthrottled.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/serial/keyspan_pda.c | 44 +++++++++++++++++++++++++++++++--------
1 file changed, 35 insertions(+), 9 deletions(-)
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -35,6 +35,8 @@ struct keyspan_pda_private {
struct work_struct unthrottle_work;
struct usb_serial *serial;
struct usb_serial_port *port;
+ bool throttled;
+ bool throttle_req;
};
static int keyspan_pda_write_start(struct usb_serial_port *port);
@@ -150,6 +152,7 @@ static void keyspan_pda_rx_interrupt(str
int retval;
int status = urb->status;
struct keyspan_pda_private *priv;
+ bool throttled = false;
unsigned long flags;
priv = usb_get_serial_port_data(port);
@@ -211,16 +214,24 @@ static void keyspan_pda_rx_interrupt(str
}
exit:
- retval = usb_submit_urb(urb, GFP_ATOMIC);
- if (retval)
- dev_err(&port->dev,
- "%s - usb_submit_urb failed with result %d\n",
- __func__, retval);
+ spin_lock_irqsave(&port->lock, flags);
+ if (priv->throttle_req) {
+ priv->throttled = true;
+ throttled = true;
+ }
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ if (!throttled) {
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval)
+ dev_err(&port->dev, "failed to resubmit in urb: %d\n", retval);
+ }
}
static void keyspan_pda_rx_throttle(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
+ struct keyspan_pda_private *priv = usb_get_serial_port_data(port);
/*
* Stop receiving characters. We just turn off the URB request, and
@@ -230,16 +241,29 @@ static void keyspan_pda_rx_throttle(stru
* send an XOFF, although it might make sense to foist that off upon
* the device too.
*/
- usb_kill_urb(port->interrupt_in_urb);
+ spin_lock_irq(&port->lock);
+ priv->throttle_req = true;
+ spin_unlock_irq(&port->lock);
}
static void keyspan_pda_rx_unthrottle(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
+ struct keyspan_pda_private *priv = usb_get_serial_port_data(port);
+ bool throttled;
+ int ret;
+
+ spin_lock_irq(&port->lock);
+ throttled = priv->throttled;
+ priv->throttled = false;
+ priv->throttle_req = false;
+ spin_unlock_irq(&port->lock);
- /* just restart the receive interrupt URB */
- if (usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL))
- dev_dbg(&port->dev, "usb_submit_urb(read urb) failed\n");
+ if (throttled) {
+ ret = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+ if (ret)
+ dev_err(&port->dev, "failed to submit in urb: %d\n", ret);
+ }
}
static speed_t keyspan_pda_setbaud(struct usb_serial *serial, speed_t baud)
@@ -579,6 +603,8 @@ static int keyspan_pda_open(struct tty_s
spin_lock_irq(&port->lock);
priv->tx_room = rc;
+ priv->throttled = false;
+ priv->throttle_req = false;
spin_unlock_irq(&port->lock);
rc = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 129/602] USB: serial: option: add TDTECH MT5710-CN
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (127 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 128/602] USB: serial: keyspan_pda: fix data loss on receive throttling Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 130/602] crypto: rsa-pkcs1pad: Dont WARN on an empty digest Greg Kroah-Hartman
` (476 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Chukun Pan, Johan Hovold
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chukun Pan <amadeus@jmu.edu.cn>
commit 55645e4f3c6022ffb160ad3617d2b624eaa38501 upstream.
Add support for the TDTECH MT5710-CN (5G redcap) module based on the
Huawei HiSilicon Balong chip.
T: Bus=01 Lev=02 Prnt=02 Port=00 Cnt=01 Dev#= 3 Spd=480 MxCh= 0
D: Ver= 2.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1
P: Vendor=3466 ProdID=3301 Rev=ff.ff
S: Manufacturer=TD Tech Ltd.
S: Product=TDTECH MT571X
S: SerialNumber=0123456789ABCDEF
C:* #Ifs= 6 Cfg#= 1 Atr=c0 MxPwr= 0mA
A: FirstIf#= 0 IfCount= 2 Cls=02(comm.) Sub=0d Prot=00
I:* If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=0d Prot=00 Driver=cdc_ncm
E: Ad=82(I) Atr=03(Int.) MxPS= 16 Ivl=32ms
I: If#= 1 Alt= 0 #EPs= 0 Cls=0a(data ) Sub=00 Prot=01 Driver=cdc_ncm
I:* If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=01 Driver=cdc_ncm
E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=06 Prot=13 Driver=option
E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=06 Prot=12 Driver=option
E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=06 Prot=1c Driver=option
E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:* If#= 5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=06 Prot=14 Driver=option
E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
Interface: ECM / NCM + DIAG + AT + SERIAL + GPS
Signed-off-by: Chukun Pan <amadeus@jmu.edu.cn>
Cc: stable@vger.kernel.org
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/serial/option.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -2497,6 +2497,7 @@ static const struct usb_device_id option
.driver_info = RSVD(5) },
{ USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x1003, 0xff), /* Rolling RW135R-GL (laptop MBIM) */
.driver_info = RSVD(5) },
+ { USB_DEVICE_INTERFACE_CLASS(0x3466, 0x3301, 0xff) }, /* TDTECH MT5710-CN */
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0100, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WWD for Global */
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0100, 0xff, 0x00, 0x40) },
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0100, 0xff, 0xff, 0x40) },
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 130/602] crypto: rsa-pkcs1pad: Dont WARN on an empty digest
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (128 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 129/602] USB: serial: option: add TDTECH MT5710-CN Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 131/602] Revert "drm/amd/display: Add missing kdoc for ALLM parameters" Greg Kroah-Hartman
` (475 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Doruk Tan Ozturk, Lukas Wunner,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Doruk Tan Ozturk <doruk@0sec.ai>
KEYCTL_PKEY_VERIFY lets an unprivileged caller supply a zero-length
digest (in_len == 0). keyctl_pkey_params_get_2() accepts the zero
length and the request reaches pkcs1pad_verify(), where the empty
digest is rejected but only after being passed through
WARN_ON(!digest_size). The warning is therefore directly
user-triggerable, and on kernels built with panic_on_warn=1 an
unprivileged process can panic the machine -- a local denial of
service. Reproduced as UID 65534 in a setuid sandbox.
Keep rejecting the invalid request with -EINVAL, but do not emit a
warning for the user-controlled length.
Mainline does not contain this code path; commit 1e562deacecc
("crypto: rsassa-pkcs1 - Migrate to sig_alg backend") removed
pkcs1pad_verify() in v6.13-rc1. This is a minimal fix for the
affected stable branches. It applies as-is to 6.1.y, 6.6.y and
6.12.y (identical pkcs1pad_verify); the 5.10.y/5.15.y form is sent
as a separate patch due to the older req->dst_len spelling.
Found by 0sec automated security-research tooling (https://0sec.ai).
Fixes: c7381b012872 ("crypto: akcipher - new verify API for public key algorithms")
Cc: stable@vger.kernel.org
Assisted-by: 0sec:multi-model
Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
Reviewed-by: Lukas Wunner <lukas@wunner.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
crypto/rsa-pkcs1pad.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
index cd501195f34a1a..225fcc3377dddc 100644
--- a/crypto/rsa-pkcs1pad.c
+++ b/crypto/rsa-pkcs1pad.c
@@ -557,7 +557,7 @@ static int pkcs1pad_verify(struct akcipher_request *req)
const unsigned int digest_size = req->dst_len;
int err;
- if (WARN_ON(req->dst) || WARN_ON(!digest_size) ||
+ if (WARN_ON(req->dst) || !digest_size ||
!ctx->key_size || sig_size != ctx->key_size)
return -EINVAL;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 131/602] Revert "drm/amd/display: Add missing kdoc for ALLM parameters"
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (129 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 130/602] crypto: rsa-pkcs1pad: Dont WARN on an empty digest Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 132/602] RISC-V: KVM: Serialize virtual interrupt pending state updates Greg Kroah-Hartman
` (474 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
This reverts commit 8fa292bd7ea0c19a6f87db967db823f48542e170.
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
index ae858a43c35f4a..b3d55cac35694b 100644
--- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
+++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
@@ -447,8 +447,6 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream,
*
* @stream: contains data we may need to construct VSIF (i.e. timing_3d_format, etc.)
* @info_packet: output structure where to store VSIF
- * @ALLMEnabled: indicates whether ALLM HF-VSIF should be generated
- * @ALLMValue: ALLM bit value to advertise in HF-VSIF
*/
void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream,
struct dc_info_packet *info_packet)
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 132/602] RISC-V: KVM: Serialize virtual interrupt pending state updates
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (130 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 131/602] Revert "drm/amd/display: Add missing kdoc for ALLM parameters" Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 133/602] usb: xhci-pci: Limit VIA VL805 DMA addressing to 36 bits Greg Kroah-Hartman
` (473 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Xie Bo, Anup Patel, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xie Bo <xb@ultrarisc.com>
commit d024a0a7879e6f37c0152aacf6d8e37b214a1738 upstream.
KVM RISC-V tracks guest local interrupt state with two bitmaps:
- irqs_pending: interrupts that should be visible to the guest
- irqs_pending_mask: interrupts whose pending state changed
The current code updates those bitmaps with independent atomic bitops
and assumes a multiple-producer, single-consumer protocol. That model
does not actually hold.
kvm_riscv_vcpu_sync_interrupts() is not a pure consumer. When the guest
changes guest-visible HVIP state, sync_interrupts() writes both
irqs_pending and irqs_pending_mask to reflect the new guest state back
into KVM state. As a result, irqs_pending and irqs_pending_mask form a
single logical state transition, but they are not updated atomically as
a pair.
This allows a race where a newly injected interrupt is lost. For
example:
CPU0 CPU1
---- ----
kvm_riscv_vcpu_set_interrupt(VS_SOFT)
set_bit(VS_SOFT, irqs_pending)
kvm_riscv_vcpu_sync_interrupts()
sees guest-cleared HVIP.VSSIP
sets irqs_pending_mask
clear_bit(IRQ_VS_SOFT, irqs_pending)
set_bit(VS_SOFT, irqs_pending_mask)
kvm_vcpu_kick()
After that interleaving, a later flush can update HVIP without VSSIP
even though a new virtual interrupt was injected. In practice, the
guest can remain blocked in WFI with work pending.
The same pending/mask protocol is shared by VS soft interrupts, PMU
overflow delivery, and AIA high interrupt synchronization, so the race
is not limited to one interrupt source.
Fix this by serializing all updates to irqs_pending and irqs_pending_mask
with a per-vCPU raw spinlock. This keeps the pending bit and the dirty
mask as one state transition across:
- set/unset interrupt
- guest HVIP sync
- interrupt flush to guest CSR state
- vCPU reset
- AIA CSR writes that clear dirty state
Use non-atomic bitmap operations while holding the lock. Hold the lock
across the AIA sync, flush, and pending checks as well, so both bitmap
words share the same serialization domain.
This intentionally replaces the existing lockless protocol instead of
trying to repair it with additional barriers. The problem is not memory
ordering on a single field; it is that two separate bitmaps encode one
shared state machine while both producers and sync paths can modify
them. A per-vCPU raw spinlock keeps the fix small, local, and suitable
for backporting.
Fixes: cce69aff689e ("RISC-V: KVM: Implement VCPU interrupts and requests handling")
Cc: stable@vger.kernel.org
Signed-off-by: Xie Bo <xb@ultrarisc.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20260715020359.1521354-2-xb@ultrarisc.com
Signed-off-by: Anup Patel <anup@brainfault.org>
[ bo: Adapt the reset and CSR helpers to their older signatures. ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
arch/riscv/include/asm/kvm_host.h | 10 ++---
arch/riscv/kvm/aia.c | 34 +++++++++++----
arch/riscv/kvm/vcpu.c | 69 ++++++++++++++++++++++---------
arch/riscv/kvm/vcpu_onereg.c | 8 +++-
4 files changed, 87 insertions(+), 34 deletions(-)
diff --git a/arch/riscv/include/asm/kvm_host.h b/arch/riscv/include/asm/kvm_host.h
index 2e2254fd2a2aae..7beef600abad7c 100644
--- a/arch/riscv/include/asm/kvm_host.h
+++ b/arch/riscv/include/asm/kvm_host.h
@@ -232,13 +232,13 @@ struct kvm_vcpu_arch {
/*
* VCPU interrupts
*
- * We have a lockless approach for tracking pending VCPU interrupts
- * implemented using atomic bitops. The irqs_pending bitmap represent
- * pending interrupts whereas irqs_pending_mask represent bits changed
- * in irqs_pending. Our approach is modeled around multiple producer
- * and single consumer problem where the consumer is the VCPU itself.
+ * The irqs_pending bitmap represents pending interrupts whereas
+ * irqs_pending_mask represents bits changed in irqs_pending. Updates
+ * to these bitmaps are serialized so vcpu interrupt sync/flush cannot
+ * drop a newly injected interrupt while syncing guest-visible HVIP.
*/
#define KVM_RISCV_VCPU_NR_IRQS 64
+ raw_spinlock_t irqs_pending_lock;
DECLARE_BITMAP(irqs_pending, KVM_RISCV_VCPU_NR_IRQS);
DECLARE_BITMAP(irqs_pending_mask, KVM_RISCV_VCPU_NR_IRQS);
diff --git a/arch/riscv/kvm/aia.c b/arch/riscv/kvm/aia.c
index 9f3b527596ded8..01319d8d75b0a4 100644
--- a/arch/riscv/kvm/aia.c
+++ b/arch/riscv/kvm/aia.c
@@ -71,12 +71,15 @@ void kvm_riscv_vcpu_aia_flush_interrupts(struct kvm_vcpu *vcpu)
struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
unsigned long mask, val;
+ lockdep_assert_held(&vcpu->arch.irqs_pending_lock);
+
if (!kvm_riscv_aia_available())
return;
- if (READ_ONCE(vcpu->arch.irqs_pending_mask[1])) {
- mask = xchg_acquire(&vcpu->arch.irqs_pending_mask[1], 0);
- val = READ_ONCE(vcpu->arch.irqs_pending[1]) & mask;
+ mask = vcpu->arch.irqs_pending_mask[1];
+ if (mask) {
+ vcpu->arch.irqs_pending_mask[1] = 0;
+ val = vcpu->arch.irqs_pending[1] & mask;
csr->hviph &= ~mask;
csr->hviph |= val;
@@ -87,6 +90,8 @@ void kvm_riscv_vcpu_aia_sync_interrupts(struct kvm_vcpu *vcpu)
{
struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
+ lockdep_assert_held(&vcpu->arch.irqs_pending_lock);
+
if (kvm_riscv_aia_available())
csr->vsieh = csr_read(CSR_VSIEH);
}
@@ -96,13 +101,21 @@ bool kvm_riscv_vcpu_aia_has_interrupts(struct kvm_vcpu *vcpu, u64 mask)
{
int hgei;
unsigned long seip;
+#ifdef CONFIG_32BIT
+ unsigned long flags;
+ bool pending;
+#endif
if (!kvm_riscv_aia_available())
return false;
#ifdef CONFIG_32BIT
- if (READ_ONCE(vcpu->arch.irqs_pending[1]) &
- (vcpu->arch.aia_context.guest_csr.vsieh & upper_32_bits(mask)))
+ raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
+ pending = vcpu->arch.irqs_pending[1] &
+ (vcpu->arch.aia_context.guest_csr.vsieh &
+ upper_32_bits(mask));
+ raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
+ if (pending)
return true;
#endif
@@ -190,6 +203,9 @@ int kvm_riscv_vcpu_aia_set_csr(struct kvm_vcpu *vcpu,
unsigned long val)
{
struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr;
+#ifdef CONFIG_32BIT
+ unsigned long flags;
+#endif
if (reg_num >= sizeof(struct kvm_riscv_aia_csr) / sizeof(unsigned long))
return -ENOENT;
@@ -198,8 +214,12 @@ int kvm_riscv_vcpu_aia_set_csr(struct kvm_vcpu *vcpu,
((unsigned long *)csr)[reg_num] = val;
#ifdef CONFIG_32BIT
- if (reg_num == KVM_REG_RISCV_CSR_AIA_REG(siph))
- WRITE_ONCE(vcpu->arch.irqs_pending_mask[1], 0);
+ if (reg_num == KVM_REG_RISCV_CSR_AIA_REG(siph)) {
+ raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
+ vcpu->arch.irqs_pending_mask[1] = 0;
+ raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock,
+ flags);
+ }
#endif
}
diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c
index da01c81bf41676..ad519c9c31d05a 100644
--- a/arch/riscv/kvm/vcpu.c
+++ b/arch/riscv/kvm/vcpu.c
@@ -52,6 +52,7 @@ static void kvm_riscv_reset_vcpu(struct kvm_vcpu *vcpu)
struct kvm_vcpu_csr *reset_csr = &vcpu->arch.guest_reset_csr;
struct kvm_cpu_context *cntx = &vcpu->arch.guest_context;
struct kvm_cpu_context *reset_cntx = &vcpu->arch.guest_reset_context;
+ unsigned long flags;
bool loaded;
/**
@@ -80,8 +81,10 @@ static void kvm_riscv_reset_vcpu(struct kvm_vcpu *vcpu)
kvm_riscv_vcpu_aia_reset(vcpu);
+ raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
bitmap_zero(vcpu->arch.irqs_pending, KVM_RISCV_VCPU_NR_IRQS);
bitmap_zero(vcpu->arch.irqs_pending_mask, KVM_RISCV_VCPU_NR_IRQS);
+ raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
kvm_riscv_vcpu_pmu_reset(vcpu);
@@ -126,6 +129,8 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
/* Setup VCPU hfence queue */
spin_lock_init(&vcpu->arch.hfence_lock);
+ raw_spin_lock_init(&vcpu->arch.irqs_pending_lock);
+
/* Setup reset state of shadow SSTATUS and HSTATUS CSRs */
spin_lock_init(&vcpu->arch.reset_cntx_lock);
@@ -341,10 +346,14 @@ void kvm_riscv_vcpu_flush_interrupts(struct kvm_vcpu *vcpu)
{
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
unsigned long mask, val;
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
- if (READ_ONCE(vcpu->arch.irqs_pending_mask[0])) {
- mask = xchg_acquire(&vcpu->arch.irqs_pending_mask[0], 0);
- val = READ_ONCE(vcpu->arch.irqs_pending[0]) & mask;
+ mask = vcpu->arch.irqs_pending_mask[0];
+ if (mask) {
+ vcpu->arch.irqs_pending_mask[0] = 0;
+ val = vcpu->arch.irqs_pending[0] & mask;
csr->hvip &= ~mask;
csr->hvip |= val;
@@ -352,11 +361,14 @@ void kvm_riscv_vcpu_flush_interrupts(struct kvm_vcpu *vcpu)
/* Flush AIA high interrupts */
kvm_riscv_vcpu_aia_flush_interrupts(vcpu);
+
+ raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
}
void kvm_riscv_vcpu_sync_interrupts(struct kvm_vcpu *vcpu)
{
unsigned long hvip;
+ unsigned long flags;
struct kvm_vcpu_arch *v = &vcpu->arch;
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
@@ -365,34 +377,41 @@ void kvm_riscv_vcpu_sync_interrupts(struct kvm_vcpu *vcpu)
/* Sync-up HVIP.VSSIP bit changes does by Guest */
hvip = csr_read(CSR_HVIP);
+
+ raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
+
if ((csr->hvip ^ hvip) & (1UL << IRQ_VS_SOFT)) {
if (hvip & (1UL << IRQ_VS_SOFT)) {
- if (!test_and_set_bit(IRQ_VS_SOFT,
- v->irqs_pending_mask))
- set_bit(IRQ_VS_SOFT, v->irqs_pending);
+ if (!__test_and_set_bit(IRQ_VS_SOFT,
+ v->irqs_pending_mask))
+ __set_bit(IRQ_VS_SOFT, v->irqs_pending);
} else {
- if (!test_and_set_bit(IRQ_VS_SOFT,
- v->irqs_pending_mask))
- clear_bit(IRQ_VS_SOFT, v->irqs_pending);
+ if (!__test_and_set_bit(IRQ_VS_SOFT,
+ v->irqs_pending_mask))
+ __clear_bit(IRQ_VS_SOFT, v->irqs_pending);
}
}
/* Sync up the HVIP.LCOFIP bit changes (only clear) by the guest */
if ((csr->hvip ^ hvip) & (1UL << IRQ_PMU_OVF)) {
if (!(hvip & (1UL << IRQ_PMU_OVF)) &&
- !test_and_set_bit(IRQ_PMU_OVF, v->irqs_pending_mask))
- clear_bit(IRQ_PMU_OVF, v->irqs_pending);
+ !__test_and_set_bit(IRQ_PMU_OVF, v->irqs_pending_mask))
+ __clear_bit(IRQ_PMU_OVF, v->irqs_pending);
}
/* Sync-up AIA high interrupts */
kvm_riscv_vcpu_aia_sync_interrupts(vcpu);
+ raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
+
/* Sync-up timer CSRs */
kvm_riscv_vcpu_timer_sync(vcpu);
}
int kvm_riscv_vcpu_set_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
{
+ unsigned long flags;
+
/*
* We only allow VS-mode software, timer, and external
* interrupts when irq is one of the local interrupts
@@ -405,9 +424,10 @@ int kvm_riscv_vcpu_set_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
irq != IRQ_PMU_OVF)
return -EINVAL;
- set_bit(irq, vcpu->arch.irqs_pending);
- smp_mb__before_atomic();
- set_bit(irq, vcpu->arch.irqs_pending_mask);
+ raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
+ __set_bit(irq, vcpu->arch.irqs_pending);
+ __set_bit(irq, vcpu->arch.irqs_pending_mask);
+ raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
kvm_vcpu_kick(vcpu);
@@ -416,6 +436,8 @@ int kvm_riscv_vcpu_set_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
int kvm_riscv_vcpu_unset_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
{
+ unsigned long flags;
+
/*
* We only allow VS-mode software, timer, counter overflow and external
* interrupts when irq is one of the local interrupts
@@ -428,26 +450,33 @@ int kvm_riscv_vcpu_unset_interrupt(struct kvm_vcpu *vcpu, unsigned int irq)
irq != IRQ_PMU_OVF)
return -EINVAL;
- clear_bit(irq, vcpu->arch.irqs_pending);
- smp_mb__before_atomic();
- set_bit(irq, vcpu->arch.irqs_pending_mask);
+ raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
+ __clear_bit(irq, vcpu->arch.irqs_pending);
+ __set_bit(irq, vcpu->arch.irqs_pending_mask);
+ raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
return 0;
}
bool kvm_riscv_vcpu_has_interrupts(struct kvm_vcpu *vcpu, u64 mask)
{
+ unsigned long flags;
unsigned long ie;
+ bool ret;
+ raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
ie = ((vcpu->arch.guest_csr.vsie & VSIP_VALID_MASK)
<< VSIP_TO_HVIP_SHIFT) & (unsigned long)mask;
ie |= vcpu->arch.guest_csr.vsie & ~IRQ_LOCAL_MASK &
(unsigned long)mask;
- if (READ_ONCE(vcpu->arch.irqs_pending[0]) & ie)
- return true;
+ ret = vcpu->arch.irqs_pending[0] & ie;
+ raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
/* Check AIA high interrupts */
- return kvm_riscv_vcpu_aia_has_interrupts(vcpu, mask);
+ if (!ret)
+ ret = kvm_riscv_vcpu_aia_has_interrupts(vcpu, mask);
+
+ return ret;
}
void __kvm_riscv_vcpu_power_off(struct kvm_vcpu *vcpu)
diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c
index b319c4c13c54ce..6223806fcbc2ba 100644
--- a/arch/riscv/kvm/vcpu_onereg.c
+++ b/arch/riscv/kvm/vcpu_onereg.c
@@ -445,6 +445,7 @@ static int kvm_riscv_vcpu_general_set_csr(struct kvm_vcpu *vcpu,
unsigned long reg_val)
{
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
+ unsigned long flags;
if (reg_num >= sizeof(struct kvm_riscv_csr) / sizeof(unsigned long))
return -ENOENT;
@@ -456,8 +457,11 @@ static int kvm_riscv_vcpu_general_set_csr(struct kvm_vcpu *vcpu,
((unsigned long *)csr)[reg_num] = reg_val;
- if (reg_num == KVM_REG_RISCV_CSR_REG(sip))
- WRITE_ONCE(vcpu->arch.irqs_pending_mask[0], 0);
+ if (reg_num == KVM_REG_RISCV_CSR_REG(sip)) {
+ raw_spin_lock_irqsave(&vcpu->arch.irqs_pending_lock, flags);
+ vcpu->arch.irqs_pending_mask[0] = 0;
+ raw_spin_unlock_irqrestore(&vcpu->arch.irqs_pending_lock, flags);
+ }
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 133/602] usb: xhci-pci: Limit VIA VL805 DMA addressing to 36 bits
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (131 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 132/602] RISC-V: KVM: Serialize virtual interrupt pending state updates Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 134/602] wifi: ath9k: hif_usb: dont dereference hif_dev after re-arming firmware request Greg Kroah-Hartman
` (472 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, stable, Xincheng Zhang, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xincheng Zhang <zhangxincheng@ultrarisc.com>
commit 1fc50f1ecde39feb4fccdaf4bc71aa6c0eb25c49 upstream.
The VIA VL805/806 xHCI controller advertises AC64, but fails to handle
DMA addresses at or above 0x1000000000. On systems with large amounts of
RAM, this can cause USB device failures when the controller is given DMA
addresses beyond its usable address width.
Do not use XHCI_NO_64BIT_SUPPORT for this controller. That quirk clears
the cached AC64 capability and limits DMA to 32 bits, causing unnecessary
bouncing for addresses between 4GiB and 64GiB and hiding the controller's
real AC64 capability from code that may need to distinguish register
access width from usable DMA address width.
Track the usable DMA address width separately from the AC64 capability.
Initialize the generic xhci->dma_mask_bits field to 64 and let PCI quirks
reduce it for controllers with narrower DMA support. Set VIA VL805/806 to
36 bits so the DMA API only hands it addresses in the range it can handle
while keeping HCCPARAMS1.AC64 visible.
Cc: stable@kernel.org
Signed-off-by: Xincheng Zhang <zhangxincheng@ultrarisc.com>
Link: https://patch.msgid.link/20260630-xhci-via-dma-fix-v3-1-690dcb8cf75a@ultrarisc.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/usb/host/xhci-pci.c | 1 +
drivers/usb/host/xhci.c | 15 ++++++++++-----
drivers/usb/host/xhci.h | 1 +
3 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 5f60528453e917..bd33cf6769cf6d 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -454,6 +454,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == PCI_DEVICE_ID_VIA_VL805) {
xhci->quirks |= XHCI_LPM_SUPPORT;
xhci->quirks |= XHCI_TRB_OVERFETCH;
+ xhci->dma_mask_bits = 36;
}
if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index aae3f1d1f11950..a50e813dda13a0 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -5259,6 +5259,7 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
if (xhci->hci_version > 0x100)
xhci->hcc_params2 = readl(&xhci->cap_regs->hcc_params2);
+ xhci->dma_mask_bits = 64;
/* xhci-plat or xhci-pci might have set max_interrupters already */
if ((!xhci->max_interrupters) ||
xhci->max_interrupters > HCS_MAX_INTRS(xhci->hcs_params1))
@@ -5300,12 +5301,16 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
if (xhci->quirks & XHCI_NO_64BIT_SUPPORT)
xhci->hcc_params &= ~BIT(0);
- /* Set dma_mask and coherent_dma_mask to 64-bits,
- * if xHC supports 64-bit addressing */
+ /*
+ * Set dma_mask and coherent_dma_mask to 64-bits if xHC supports
+ * 64-bit addressing, unless a controller-specific quirk callback
+ * limits the usable address width.
+ */
if (HCC_64BIT_ADDR(xhci->hcc_params) &&
- !dma_set_mask(dev, DMA_BIT_MASK(64))) {
- xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");
- dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
+ !dma_set_mask(dev, DMA_BIT_MASK(xhci->dma_mask_bits))) {
+ xhci_dbg(xhci, "Enabling %u-bit DMA addresses.\n",
+ xhci->dma_mask_bits);
+ dma_set_coherent_mask(dev, DMA_BIT_MASK(xhci->dma_mask_bits));
} else {
/*
* This is to avoid error in cases where a 32-bit USB
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index b4fa8e7e437639..1a3f2dfd5a711d 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1510,6 +1510,7 @@ struct xhci_hcd {
/* imod_interval in ns (I * 250ns) */
u32 imod_interval;
u32 page_size;
+ unsigned int dma_mask_bits;
/* MSI-X/MSI vectors */
int nvecs;
/* optional clocks */
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 134/602] wifi: ath9k: hif_usb: dont dereference hif_dev after re-arming firmware request
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (132 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 133/602] usb: xhci-pci: Limit VIA VL805 DMA addressing to 36 bits Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 135/602] wifi: ath11k: fix NULL pointer dereference in ath11k_hal_srng_access_begin Greg Kroah-Hartman
` (471 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, syzbot+50122cbc2874b1eb25b0,
Cheng Yongkang, Toke Høiland-Jørgensen, Jeff Johnson,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cheng Yongkang <teel4res@gmail.com>
[ Upstream commit dad9f96945d77ecd4708f730c06ef54dcd8cc057 ]
ath9k_hif_request_firmware() re-arms an asynchronous firmware load via
request_firmware_nowait(), passing hif_dev as the completion context, and
then still dereferences hif_dev:
dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n",
hif_dev->fw_name);
The re-armed callback ath9k_hif_usb_firmware_cb() runs on the "events"
workqueue and, when the firmware is missing, walks the retry chain into
ath9k_hif_usb_firmware_fail() -> complete_all(&hif_dev->fw_done). That
releases the wait_for_completion(&hif_dev->fw_done) in a concurrent
ath9k_hif_usb_disconnect(), which then kfree()s hif_dev. The trailing
dev_info() in the frame that re-armed the request can therefore read freed
memory (hif_dev->udev, the first field of struct hif_device_usb):
BUG: KASAN: slab-use-after-free in ath9k_hif_request_firmware
Read of size 8 ... by task kworker/...
ath9k_hif_request_firmware
ath9k_hif_usb_firmware_cb drivers/net/wireless/ath/ath9k/hif_usb.c:1247
request_firmware_work_func
Allocated by ...:
ath9k_hif_usb_probe drivers/net/wireless/ath/ath9k/hif_usb.c
Freed by ...:
ath9k_hif_usb_disconnect -> kfree drivers/net/wireless/ath/ath9k/hif_usb.c
The fw_done barrier only makes disconnect wait for the firmware chain to
*terminate*; it does not protect the outer ath9k_hif_request_firmware()
frame that re-armed the request and keeps touching hif_dev afterwards.
Drop the post-request dev_info(): it is the only use of hif_dev after the
async request is armed, and it is purely informational (the dev_err() on the
failure path runs only when request_firmware_nowait() did not arm a callback,
so hif_dev is still alive there).
This was first reported by syzbot as a single, non-reproduced crash that was
later auto-obsoleted, and was independently rediscovered by the reFuzz fuzzer,
which produced a C reproducer (USB-gadget connect/disconnect of an ath9k_htc
device whose firmware download fails). The vulnerable code is unchanged and
still present in v7.1-rc6, where the slab-use-after-free reproduces under KASAN
once the (sub-microsecond) race window is widened.
Fixes: e904cf6fe230 ("ath9k_htc: introduce support for different fw versions")
Reported-by: syzbot+50122cbc2874b1eb25b0@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=50122cbc2874b1eb25b0
Signed-off-by: Cheng Yongkang <teel4res@gmail.com>
Acked-by: Toke Høiland-Jørgensen <toke@toke.dk>
Link: https://patch.msgid.link/20260605153210.20471-1-1020691186@qq.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/ath/ath9k/hif_usb.c | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 7265766cddbdeb..dbf94333664ec5 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -1225,15 +1225,10 @@ static int ath9k_hif_request_firmware(struct hif_device_usb *hif_dev,
ret = request_firmware_nowait(THIS_MODULE, true, hif_dev->fw_name,
&hif_dev->udev->dev, GFP_KERNEL,
hif_dev, ath9k_hif_usb_firmware_cb);
- if (ret) {
+ if (ret)
dev_err(&hif_dev->udev->dev,
"ath9k_htc: Async request for firmware %s failed\n",
hif_dev->fw_name);
- return ret;
- }
-
- dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n",
- hif_dev->fw_name);
return ret;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 135/602] wifi: ath11k: fix NULL pointer dereference in ath11k_hal_srng_access_begin
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (133 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 134/602] wifi: ath9k: hif_usb: dont dereference hif_dev after re-arming firmware request Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 136/602] hwmon: (corsair-psu) Stop device IO before calling hid_hw_stop Greg Kroah-Hartman
` (470 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Gaole Zhang, Baochen Qiang,
Rameshkumar Sundaram, Jeff Johnson, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gaole Zhang <gaole.zhang@oss.qualcomm.com>
[ Upstream commit e8d85672dd7e2523f774caafba8f858384e18df7 ]
In ATH11K_QMI_EVENT_FW_READY, ATH11K_FLAG_REGISTERED is set
unconditionally even when ath11k_core_qmi_firmware_ready() fails.
This leaves the driver in an inconsistent state where
initialization is considered complete although the firmware ready
handling did not finish successfully. During the subsequent SSR,
the driver enters the restart path based on this incorrect state
and dereferences uninitialized srng members, resulting in a NULL
pointer dereference.
Call trace:
ath11k_hal_srng_access_begin+0xc/0x60 [ath11k] (P)
ath11k_ce_cleanup_pipes+0x17c/0x180 [ath11k]
ath11k_core_restart+0x40/0x168 [ath11k]
Fix this by:
- skipping firmware_ready if ATH11K_FLAG_REGISTERED is already set
- setting ATH11K_FLAG_REGISTERED only when firmware_ready succeeds
- setting ATH11K_FLAG_QMI_FAIL and aborting the FW_READY handling
on error
Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.2.0.c2-00204-QCAMSLSWPLZ-1
Fixes: 6fe62a8cec51c ("wifi: ath11k: Add cold boot calibration support on WCN6750")
Signed-off-by: Gaole Zhang <gaole.zhang@oss.qualcomm.com>
Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
Reviewed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com>
Link: https://patch.msgid.link/20260609090609.4041009-1-gaole.zhang@oss.qualcomm.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/ath/ath11k/qmi.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c
index 3ffb7723b67318..0c2527d85532fa 100644
--- a/drivers/net/wireless/ath/ath11k/qmi.c
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
@@ -3295,9 +3295,14 @@ static void ath11k_qmi_driver_event_work(struct work_struct *work)
clear_bit(ATH11K_FLAG_CRASH_FLUSH,
&ab->dev_flags);
clear_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags);
- ath11k_core_qmi_firmware_ready(ab);
- set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags);
-
+ if (!test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags)) {
+ ret = ath11k_core_qmi_firmware_ready(ab);
+ if (ret) {
+ set_bit(ATH11K_FLAG_QMI_FAIL, &ab->dev_flags);
+ break;
+ }
+ set_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags);
+ }
break;
case ATH11K_QMI_EVENT_COLD_BOOT_CAL_DONE:
break;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 136/602] hwmon: (corsair-psu) Stop device IO before calling hid_hw_stop
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (134 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 135/602] wifi: ath11k: fix NULL pointer dereference in ath11k_hal_srng_access_begin Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 137/602] hwmon: (corsair-cpro) " Greg Kroah-Hartman
` (469 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, syzbot+9eebf5f6544c5e873858,
Edward Adam Davis, Guenter Roeck, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Edward Adam Davis <eadavis@qq.com>
[ Upstream commit 9ab8656548cd737b98d0b19c4253aff8d68e97f4 ]
hid_hw_stop() does not stop the device IO.
This results in a race condition between hid_input_report() and the point
immediately following the execution of hid_device_io_start() within
corsairpsu_probe(). If the probe operation fails after "io start" has
been initiated, this race condition will result in a uaf vulnerability
[1].
CPU0 CPU1
==== ====
corsairpsu_probe()
hid_device_io_start()
... unlock driver_input_lock
hid_hw_stop()
kfree(hidraw) __hid_input_report()
... acquire driver_input_lock
hid_report_raw_event()
hidraw_report_event()
... access hidraw's list_lock // trigger uaf
Consequently, when corsairpsu_probe() fails and hid_hw_stop() needs to
be executed, the io_started flag is first cleared while holding the
driver_input_lock to prevent potential race conditions involving input
reports.
[1]
BUG: KASAN: slab-use-after-free in rt_spin_lock+0x83/0x400 kernel/locking/spinlock_rt.c:56
Call Trace:
hidraw_report_event+0x5d/0x3a0 drivers/hid/hidraw.c:577
hid_report_raw_event+0x311/0x1730 drivers/hid/hid-core.c:2076
__hid_input_report drivers/hid/hid-core.c:2152 [inline]
hid_input_report+0x44e/0x580 drivers/hid/hid-core.c:2174
hid_irq_in+0x47e/0x6d0 drivers/hid/usbhid/hid-core.c:286
__usb_hcd_giveback_urb+0x3b3/0x5e0 drivers/usb/core/hcd.c:1657
dummy_timer+0x8a9/0x47d0 drivers/usb/gadget/udc/dummy_hcd.c:2005
Allocated by task 10:
hidraw_connect+0x57/0x430 drivers/hid/hidraw.c:606
hid_connect+0x5bf/0x19d0 drivers/hid/hid-core.c:2277
hid_hw_start+0xa8/0x120 drivers/hid/hid-core.c:2387
corsairpsu_probe+0xd9/0x3c0 drivers/hwmon/corsair-psu.c:782
Freed by task 10:
hidraw_disconnect+0x4f/0x60 drivers/hid/hidraw.c:662
hid_disconnect drivers/hid/hid-core.c:2362 [inline]
hid_hw_stop+0x101/0x1e0 drivers/hid/hid-core.c:2407
corsairpsu_probe+0x327/0x3c0 drivers/hwmon/corsair-psu.c:826
Fix the problem by calling hid_device_io_stop() before calling
hid_hw_stop().
Fixes: d115b51e0e56 ("hwmon: add Corsair PSU HID controller driver")
Reported-by: syzbot+9eebf5f6544c5e873858@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=9eebf5f6544c5e873858
Tested-by: syzbot+9eebf5f6544c5e873858@syzkaller.appspotmail.com
Signed-off-by: Edward Adam Davis <eadavis@qq.com>
Link: https://lore.kernel.org/r/tencent_BB7C33EB9EA41B7B4B5F1B8B25C0BA13BB08@qq.com
[groeck: Updated subject and description;
call hid_device_io_stop() only if IO has been started]
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/hwmon/corsair-psu.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/hwmon/corsair-psu.c b/drivers/hwmon/corsair-psu.c
index 93937e1bce196b..4ab73bcef1d125 100644
--- a/drivers/hwmon/corsair-psu.c
+++ b/drivers/hwmon/corsair-psu.c
@@ -831,6 +831,7 @@ static int corsairpsu_probe(struct hid_device *hdev, const struct hid_device_id
fail_and_close:
hid_hw_close(hdev);
+ hid_device_io_stop(hdev);
fail_and_stop:
hid_hw_stop(hdev);
return ret;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 137/602] hwmon: (corsair-cpro) Stop device IO before calling hid_hw_stop
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (135 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 136/602] hwmon: (corsair-psu) Stop device IO before calling hid_hw_stop Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 138/602] hwmon: (gigabyte_waterforce) " Greg Kroah-Hartman
` (468 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Sashiko, Guenter Roeck, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guenter Roeck <linux@roeck-us.net>
[ Upstream commit 94c87871b051d7ad758828a805215a2ec194512a ]
Calling hid_hw_stop() does not stop the device IO.
This results in a race condition between hid_input_report() and the point
immediately following the execution of hid_device_io_start() within
the driver probe function. If the probe operation fails after "io start"
has been initiated, this race condition will result in a UAF vulnerability.
Fix the problem by calling hid_device_io_stop() before calling
hid_hw_stop().
Reported-by: Sashiko <sashiko-bot@kernel.org>
Fixes: 40c3a44542257 ("hwmon: add Corsair Commander Pro driver")
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/hwmon/corsair-cpro.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/hwmon/corsair-cpro.c b/drivers/hwmon/corsair-cpro.c
index b7b911f8359c7f..71e48b3bba60f0 100644
--- a/drivers/hwmon/corsair-cpro.c
+++ b/drivers/hwmon/corsair-cpro.c
@@ -645,6 +645,7 @@ static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id)
out_hw_close:
hid_hw_close(hdev);
+ hid_device_io_stop(hdev);
out_hw_stop:
hid_hw_stop(hdev);
return ret;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 138/602] hwmon: (gigabyte_waterforce) Stop device IO before calling hid_hw_stop
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (136 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 137/602] hwmon: (corsair-cpro) " Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 139/602] hwmon: (nzxt-smart2) " Greg Kroah-Hartman
` (467 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Sashiko, Guenter Roeck, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guenter Roeck <linux@roeck-us.net>
[ Upstream commit ff0c5c53d08274e200b48a4d53aa078265e873cb ]
Calling hid_hw_stop() does not stop the device IO.
This results in a race condition between hid_input_report() and the point
immediately following the execution of hid_device_io_start() within
the driver probe function. If the probe operation fails after "io start"
has been initiated, this race condition will result in a UAF vulnerability.
Fix the problem by calling hid_device_io_stop() before calling
hid_hw_stop().
Reported-by: Sashiko <sashiko-bot@kernel.org>
Fixes: 42ac68e3d4ba0 ("hwmon: Add driver for Gigabyte AORUS Waterforce AIO coolers")
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/hwmon/gigabyte_waterforce.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/hwmon/gigabyte_waterforce.c b/drivers/hwmon/gigabyte_waterforce.c
index 27487e215bddff..4eea05f8b569c2 100644
--- a/drivers/hwmon/gigabyte_waterforce.c
+++ b/drivers/hwmon/gigabyte_waterforce.c
@@ -371,13 +371,15 @@ static int waterforce_probe(struct hid_device *hdev, const struct hid_device_id
if (IS_ERR(priv->hwmon_dev)) {
ret = PTR_ERR(priv->hwmon_dev);
hid_err(hdev, "hwmon registration failed with %d\n", ret);
- goto fail_and_close;
+ goto fail_and_io_stop;
}
waterforce_debugfs_init(priv);
return 0;
+fail_and_io_stop:
+ hid_device_io_stop(hdev);
fail_and_close:
hid_hw_close(hdev);
fail_and_stop:
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 139/602] hwmon: (nzxt-smart2) Stop device IO before calling hid_hw_stop
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (137 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 138/602] hwmon: (gigabyte_waterforce) " Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 140/602] hwmon: (nzxt-kraken3) " Greg Kroah-Hartman
` (466 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Sashiko, Guenter Roeck, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guenter Roeck <linux@roeck-us.net>
[ Upstream commit 59d104b54b0b42e30fd2a68d24ee5c49dcc54d1e ]
Calling hid_hw_stop() does not stop the device IO.
This results in a race condition between hid_input_report() and the point
immediately following the execution of hid_device_io_start() within
the driver probe function. If the probe operation fails after "io start"
has been initiated, this race condition will result in a UAF vulnerability.
Fix the problem by calling hid_device_io_stop() before calling
hid_hw_stop().
Reported-by: Sashiko <sashiko-bot@kernel.org>
Fixes: 53e68c20aeb1e ("hwmon: add driver for NZXT RGB&Fan Controller/Smart Device v2")
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/hwmon/nzxt-smart2.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/hwmon/nzxt-smart2.c b/drivers/hwmon/nzxt-smart2.c
index c2d1173f42fefb..6f8febda4277c9 100644
--- a/drivers/hwmon/nzxt-smart2.c
+++ b/drivers/hwmon/nzxt-smart2.c
@@ -774,7 +774,7 @@ static int nzxt_smart2_hid_probe(struct hid_device *hdev,
out_hw_close:
hid_hw_close(hdev);
-
+ hid_device_io_stop(hdev);
out_hw_stop:
hid_hw_stop(hdev);
return ret;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 140/602] hwmon: (nzxt-kraken3) Stop device IO before calling hid_hw_stop
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (138 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 139/602] hwmon: (nzxt-smart2) " Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 141/602] watchdog: pretimeout: Fix UAF in watchdog_unregister_governor() Greg Kroah-Hartman
` (465 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Sashiko, Guenter Roeck, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guenter Roeck <linux@roeck-us.net>
[ Upstream commit f151d0143ac4e086f92f52328ebdbdc50933d8ef ]
Calling hid_hw_stop() does not stop the device IO.
This results in a race condition between hid_input_report() and the point
immediately following the execution of hid_device_io_start() within
the driver probe function. If the probe operation fails after "io start"
has been initiated, this race condition will result in a UAF vulnerability.
Fix the problem by calling hid_device_io_stop() before calling
hid_hw_stop().
Reported-by: Sashiko <sashiko-bot@kernel.org>
Fixes: f3b4b146eb107 ("hwmon: Add driver for NZXT Kraken X and Z series AIO CPU coolers")
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/hwmon/nzxt-kraken3.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/hwmon/nzxt-kraken3.c b/drivers/hwmon/nzxt-kraken3.c
index d00409bcab93ad..05525406c5fbb5 100644
--- a/drivers/hwmon/nzxt-kraken3.c
+++ b/drivers/hwmon/nzxt-kraken3.c
@@ -948,7 +948,7 @@ static int kraken3_probe(struct hid_device *hdev, const struct hid_device_id *id
ret = kraken3_init_device(hdev);
if (ret < 0) {
hid_err(hdev, "device init failed with %d\n", ret);
- goto fail_and_close;
+ goto fail_and_stop_io;
}
ret = kraken3_get_fw_ver(hdev);
@@ -960,13 +960,15 @@ static int kraken3_probe(struct hid_device *hdev, const struct hid_device_id *id
if (IS_ERR(priv->hwmon_dev)) {
ret = PTR_ERR(priv->hwmon_dev);
hid_err(hdev, "hwmon registration failed with %d\n", ret);
- goto fail_and_close;
+ goto fail_and_stop_io;
}
kraken3_debugfs_init(priv, device_name);
return 0;
+fail_and_stop_io:
+ hid_device_io_stop(hdev);
fail_and_close:
hid_hw_close(hdev);
fail_and_stop:
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 141/602] watchdog: pretimeout: Fix UAF in watchdog_unregister_governor()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (139 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 140/602] hwmon: (nzxt-kraken3) " Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 142/602] wifi: ath11k: fix potential buffer underflow in ath11k_hal_rx_msdu_list_get() Greg Kroah-Hartman
` (464 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Tzung-Bi Shih, Guenter Roeck,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tzung-Bi Shih <tzungbi@kernel.org>
[ Upstream commit 7362ba0f9c96ac3ad6a2ca3995bd9fc9a28a8661 ]
When a watchdog governor is unregistered, it updates existing watchdog
devices that were using this governor by falling back to `default_gov`.
If the governor being unregistered is currently set as `default_gov`,
the `default_gov` is never cleared. This leads to 2 use-after-free
issues:
1. New watchdog devices registered after this point will inherit the
dangling `default_gov`.
2. Existing watchdog devices using the unregistered governor will have
their `wdd->gov` reassigned to the dangling `default_gov`.
Fix the UAF by clearing `default_gov` if it matches the governor being
unregistered.
Fixes: da0d12ff2b82 ("watchdog: pretimeout: add panic pretimeout governor")
Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
Link: https://lore.kernel.org/r/20260707101803.3598173-1-tzungbi@kernel.org
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/watchdog/watchdog_pretimeout.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/watchdog/watchdog_pretimeout.c b/drivers/watchdog/watchdog_pretimeout.c
index e5295c990fa1b8..787b6227b8ccc3 100644
--- a/drivers/watchdog/watchdog_pretimeout.c
+++ b/drivers/watchdog/watchdog_pretimeout.c
@@ -165,6 +165,8 @@ void watchdog_unregister_governor(struct watchdog_governor *gov)
}
spin_lock_irq(&pretimeout_lock);
+ if (default_gov == gov)
+ default_gov = NULL;
list_for_each_entry(p, &pretimeout_list, entry)
if (p->wdd->gov == gov)
p->wdd->gov = default_gov;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 142/602] wifi: ath11k: fix potential buffer underflow in ath11k_hal_rx_msdu_list_get()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (140 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 141/602] watchdog: pretimeout: Fix UAF in watchdog_unregister_governor() Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 143/602] wifi: ath11k: Flush the posted write after writing to PCIE_SOC_GLOBAL_RESET Greg Kroah-Hartman
` (463 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Dmitry Morgun, Rameshkumar Sundaram,
Baochen Qiang, Jeff Johnson, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Morgun <d.morgun@ispras.ru>
[ Upstream commit 7f11e70629650ff6ea140984e5ce188b775b2683 ]
When the first entry in msdu_details has a zero buffer address,
the code accesses msdu_details[i - 1] with i == 0, causing a
buffer underflow.
Fix similarly to ath12k_wifi7_hal_rx_msdu_list_get() by adding
a separate check for i == 0 before the main condition to prevent
the out-of-bounds access.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices")
Signed-off-by: Dmitry Morgun <d.morgun@ispras.ru>
Reviewed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com>
Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
Link: https://patch.msgid.link/20260530114252.42615-1-d.morgun@ispras.ru
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/ath/ath11k/dp_rx.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index 78b0fa8d4f3391..6cc252d00ef130 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -4614,6 +4614,9 @@ static void ath11k_hal_rx_msdu_list_get(struct ath11k *ar,
msdu_details = &msdu_link->msdu_link[0];
for (i = 0; i < HAL_RX_NUM_MSDU_DESC; i++) {
+ if (!i && FIELD_GET(BUFFER_ADDR_INFO0_ADDR,
+ msdu_details[i].buf_addr_info.info0) == 0)
+ break;
if (FIELD_GET(BUFFER_ADDR_INFO0_ADDR,
msdu_details[i].buf_addr_info.info0) == 0) {
msdu_desc_info = &msdu_details[i - 1].rx_msdu_info;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 143/602] wifi: ath11k: Flush the posted write after writing to PCIE_SOC_GLOBAL_RESET
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (141 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 142/602] wifi: ath11k: fix potential buffer underflow in ath11k_hal_rx_msdu_list_get() Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 144/602] wifi: ath12k: " Greg Kroah-Hartman
` (462 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Alex Williamson,
Manivannan Sadhasivam, Baochen Qiang, Raj Kumar Bhagat,
Jeff Johnson, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
[ Upstream commit 0fe8010fc5b147607fc19ba010ba469afc95f35f ]
ath11k_pci_soc_global_reset() tries to reset the device by writing to the
PCIE_SOC_GLOBAL_RESET register. But it doesn't do a read-back to ensure
that the write gets flushed to the device before the delay.
This may lead to the delay on the host to be insufficient, if the posted
write doesn't reach the device before the delay.
So add a read-back after writing to the PCIE_SOC_GLOBAL_RESET register and
before the delay.
Compile tested only.
Fixes: f3c603d412b3 ("ath11k: reset MHI during power down and power up")
Reported-by: Alex Williamson <alex@shazbot.org>
Closes: https://lore.kernel.org/linux-pci/20260622160822.09350246@shazbot.org
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
Reviewed-by: Raj Kumar Bhagat <raj.bhagat@oss.qualcomm.com>
Link: https://patch.msgid.link/20260623141649.41087-1-manivannan.sadhasivam@oss.qualcomm.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/ath/ath11k/pci.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
index eee83eb6b2c3c0..6b0e52a6fb89b6 100644
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -197,6 +197,8 @@ static void ath11k_pci_soc_global_reset(struct ath11k_base *ab)
val |= PCIE_SOC_GLOBAL_RESET_V;
ath11k_pcic_write32(ab, PCIE_SOC_GLOBAL_RESET, val);
+ /* Flush the posted write to the device */
+ ath11k_pcic_read32(ab, PCIE_SOC_GLOBAL_RESET);
/* TODO: exact time to sleep is uncertain */
delay = 10;
@@ -206,6 +208,8 @@ static void ath11k_pci_soc_global_reset(struct ath11k_base *ab)
val &= ~PCIE_SOC_GLOBAL_RESET_V;
ath11k_pcic_write32(ab, PCIE_SOC_GLOBAL_RESET, val);
+ /* Flush the posted write to the device */
+ ath11k_pcic_read32(ab, PCIE_SOC_GLOBAL_RESET);
mdelay(delay);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 144/602] wifi: ath12k: Flush the posted write after writing to PCIE_SOC_GLOBAL_RESET
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (142 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 143/602] wifi: ath11k: Flush the posted write after writing to PCIE_SOC_GLOBAL_RESET Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 145/602] firewire: net: Fix fragmented datagram reassembly Greg Kroah-Hartman
` (461 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Alex Williamson,
Manivannan Sadhasivam, Baochen Qiang, Raj Kumar Bhagat,
Jeff Johnson, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
[ Upstream commit 55f3aa06951cac78b0206bde961c8cf11929a27a ]
ath12k_pci_soc_global_reset() tries to reset the device by writing to the
PCIE_SOC_GLOBAL_RESET register. But it doesn't do a read-back to ensure
that the write gets flushed to the device before the delay.
This may lead to the delay on the host to be insufficient, if the posted
write doesn't reach the device before the delay.
So add a read-back after writing to the PCIE_SOC_GLOBAL_RESET register and
before the delay.
Compile tested only.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.6-01243-QCAHKSWPL_SILICONZ-1
Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
Reported-by: Alex Williamson <alex@shazbot.org>
Closes: https://lore.kernel.org/linux-pci/20260622160822.09350246@shazbot.org
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com>
Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
Reviewed-by: Raj Kumar Bhagat <raj.bhagat@oss.qualcomm.com>
Tested-by: Raj Kumar Bhagat <raj.bhagat@oss.qualcomm.com>
Link: https://patch.msgid.link/20260623141649.41087-2-manivannan.sadhasivam@oss.qualcomm.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/ath/ath12k/pci.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c
index 0ac92a606cea0c..4ba0c1bb32341b 100644
--- a/drivers/net/wireless/ath/ath12k/pci.c
+++ b/drivers/net/wireless/ath/ath12k/pci.c
@@ -225,6 +225,8 @@ static void ath12k_pci_soc_global_reset(struct ath12k_base *ab)
val |= PCIE_SOC_GLOBAL_RESET_V;
ath12k_pci_write32(ab, PCIE_SOC_GLOBAL_RESET, val);
+ /* Flush the posted write to the device */
+ ath12k_pci_read32(ab, PCIE_SOC_GLOBAL_RESET);
/* TODO: exact time to sleep is uncertain */
delay = 10;
@@ -234,6 +236,8 @@ static void ath12k_pci_soc_global_reset(struct ath12k_base *ab)
val &= ~PCIE_SOC_GLOBAL_RESET_V;
ath12k_pci_write32(ab, PCIE_SOC_GLOBAL_RESET, val);
+ /* Flush the posted write to the device */
+ ath12k_pci_read32(ab, PCIE_SOC_GLOBAL_RESET);
mdelay(delay);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 145/602] firewire: net: Fix fragmented datagram reassembly
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (143 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 144/602] wifi: ath12k: " Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 146/602] wifi: ath6kl: fix OOB read from firmware num_msg in TX complete handler Greg Kroah-Hartman
` (460 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Ruoyu Wang, Takashi Sakamoto,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <ruoyuw560@gmail.com>
[ Upstream commit d52a13adbb8ccbab99cd3bad36804e87d8b5c052 ]
fwnet_frag_new() keeps a sorted list of received fragments for a partial
datagram. When a new fragment is adjacent to an existing fragment, the
code checks whether the new fragment also closes the gap to the next or
previous list entry.
Those neighbor lookups currently assume that the current fragment always
has a real next or previous fragment. At a list edge, the next or
previous entry is the list head, not a struct fwnet_fragment_info.
The gap checks also compare against the old edge of the current fragment
instead of the edge after adding the new fragment. As a result, a
fragment that bridges two existing ranges may leave two adjacent ranges
unmerged, so fwnet_pd_is_complete() can miss a complete datagram.
Check for the list head before looking up the neighboring fragment, and
compare the neighbor against the new fragment's far edge when deciding
whether to merge all three ranges.
This issue was found by a static analysis checker and confirmed by
manual source review.
Fixes: c76acec6d551 ("firewire: add IPv4 support")
Signed-off-by: Ruoyu Wang <ruoyuw560@gmail.com>
Link: https://lore.kernel.org/r/20260707150454.2265951-1-ruoyuw560@gmail.com
Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/firewire/net.c | 39 +++++++++++++++++++++------------------
1 file changed, 21 insertions(+), 18 deletions(-)
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index 423ead5fa9c135..a601a0130414ff 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -298,31 +298,34 @@ static struct fwnet_fragment_info *fwnet_frag_new(
if (fi->offset + fi->len == offset) {
/* The new fragment can be tacked on to the end */
/* Did the new fragment plug a hole? */
- fi2 = list_entry(fi->fi_link.next,
- struct fwnet_fragment_info, fi_link);
- if (fi->offset + fi->len == fi2->offset) {
- /* glue fragments together */
- fi->len += len + fi2->len;
- list_del(&fi2->fi_link);
- kfree(fi2);
- } else {
- fi->len += len;
+ if (!list_is_last(&fi->fi_link, &pd->fi_list)) {
+ fi2 = list_next_entry(fi, fi_link);
+ if (offset + len == fi2->offset) {
+ /* glue fragments together */
+ fi->len += len + fi2->len;
+ list_del(&fi2->fi_link);
+ kfree(fi2);
+
+ return fi;
+ }
}
+ fi->len += len;
return fi;
}
if (offset + len == fi->offset) {
/* The new fragment can be tacked on to the beginning */
/* Did the new fragment plug a hole? */
- fi2 = list_entry(fi->fi_link.prev,
- struct fwnet_fragment_info, fi_link);
- if (fi2->offset + fi2->len == fi->offset) {
- /* glue fragments together */
- fi2->len += fi->len + len;
- list_del(&fi->fi_link);
- kfree(fi);
-
- return fi2;
+ if (!list_is_first(&fi->fi_link, &pd->fi_list)) {
+ fi2 = list_prev_entry(fi, fi_link);
+ if (fi2->offset + fi2->len == offset) {
+ /* glue fragments together */
+ fi2->len += fi->len + len;
+ list_del(&fi->fi_link);
+ kfree(fi);
+
+ return fi2;
+ }
}
fi->offset = offset;
fi->len += len;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 146/602] wifi: ath6kl: fix OOB read from firmware num_msg in TX complete handler
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (144 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 145/602] firewire: net: Fix fragmented datagram reassembly Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 147/602] wifi: ath6kl: fix OOB read from firmware IE lengths in connect event Greg Kroah-Hartman
` (459 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Tristan Madani, Jeff Johnson,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <tristan@talencesecurity.com>
[ Upstream commit 3a21c89215cc18f1a97c5e5bfd1da6d4f3d44495 ]
The firmware-controlled num_msg field (u8, 0-255) drives the loop in
ath6kl_wmi_tx_complete_event_rx() without validation against the buffer
length. This allows out-of-bounds reads of up to 1020 bytes past the
WMI event buffer when the firmware sends an inflated num_msg.
Add a check that the buffer is large enough to hold the fixed struct
and the num_msg variable-length entries.
Fixes: bdcd81707973 ("Add ath6kl cleaned up driver")
Signed-off-by: Tristan Madani <tristan@talencesecurity.com>
Link: https://patch.msgid.link/20260625232907.3620746-1-tristmd@gmail.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/ath/ath6kl/wmi.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index 3787b9fb007559..a572952dd4b903 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -484,6 +484,18 @@ static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len)
evt = (struct wmi_tx_complete_event *) datap;
+ if (len < sizeof(*evt)) {
+ ath6kl_dbg(ATH6KL_DBG_WMI, "tx complete: invalid len %d\n",
+ len);
+ return -EINVAL;
+ }
+
+ if (len < sizeof(*evt) + evt->num_msg * sizeof(struct tx_complete_msg_v1)) {
+ ath6kl_dbg(ATH6KL_DBG_WMI, "tx complete: invalid len %d for %u msgs\n",
+ len, evt->num_msg);
+ return -EINVAL;
+ }
+
ath6kl_dbg(ATH6KL_DBG_WMI, "comp: %d %d %d\n",
evt->num_msg, evt->msg_len, evt->msg_type);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 147/602] wifi: ath6kl: fix OOB read from firmware IE lengths in connect event
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (145 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 146/602] wifi: ath6kl: fix OOB read from firmware num_msg in TX complete handler Greg Kroah-Hartman
@ 2026-07-30 14:08 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 148/602] wifi: carl9170: bound memcpy length in cmd callback to prevent OOB read Greg Kroah-Hartman
` (458 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:08 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Tristan Madani,
Vasanthakumar Thiagarajan, Jeff Johnson, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <tristan@talencesecurity.com>
[ Upstream commit 6b47b29730de3232b919d8362749f6814c5f2a33 ]
The firmware-controlled beacon_ie_len, assoc_req_len, and assoc_resp_len
fields in ath6kl_wmi_connect_event_rx() are not validated against the
buffer length. Their sum (up to 765) can exceed the actual WMI event
data, causing out-of-bounds reads during IE parsing and state corruption
of wmi->is_wmm_enabled.
Add a check that the total IE length fits within the buffer.
Fixes: bdcd81707973 ("Add ath6kl cleaned up driver")
Signed-off-by: Tristan Madani <tristan@talencesecurity.com>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
Link: https://patch.msgid.link/20260421135009.348084-3-tristmd@gmail.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/ath/ath6kl/wmi.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index a572952dd4b903..447896b871c3e2 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -874,6 +874,14 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len,
ev = (struct wmi_connect_event *) datap;
+ if (len < sizeof(*ev) + ev->beacon_ie_len +
+ ev->assoc_req_len + ev->assoc_resp_len) {
+ ath6kl_dbg(ATH6KL_DBG_WMI,
+ "connect event: IE lengths %u+%u+%u exceed buffer %d\n",
+ ev->beacon_ie_len, ev->assoc_req_len,
+ ev->assoc_resp_len, len);
+ return -EINVAL;
+ }
if (vif->nw_type == AP_NETWORK) {
/* AP mode start/STA connected event */
struct net_device *dev = vif->ndev;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 148/602] wifi: carl9170: bound memcpy length in cmd callback to prevent OOB read
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (146 preceding siblings ...)
2026-07-30 14:08 ` [PATCH 6.12 147/602] wifi: ath6kl: fix OOB read from firmware IE lengths in connect event Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 149/602] wifi: carl9170: fix OOB read from off-by-two in TX status handler Greg Kroah-Hartman
` (457 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Tristan Madani, Christian Lamparter,
Jeff Johnson, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <tristan@talencesecurity.com>
[ Upstream commit 4cde55b2feff9504d1f993ab80e84e7ccb62791c ]
When the firmware sends a command response with a length mismatch,
carl9170_cmd_callback() logs the mismatch and calls carl9170_restart()
but then falls through to memcpy(ar->readbuf, buffer + 4, len - 4).
Since len comes from the firmware and can exceed ar->readlen, this
copies more data than the readbuf was allocated for.
Bound the memcpy to min(len - 4, ar->readlen) so that the response
is still completed -- avoiding repeated restarts from queued garbage --
while preventing an overread past the response buffer.
Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend")
Signed-off-by: Tristan Madani <tristan@talencesecurity.com>
Acked-by: Christian Lamparter <chunkeey@gmail.com>
Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac
Link: https://patch.msgid.link/20260421134929.325662-2-tristmd@gmail.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/ath/carl9170/rx.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c
index 908c4c8b7f8256..9a25c2a540b95f 100644
--- a/drivers/net/wireless/ath/carl9170/rx.c
+++ b/drivers/net/wireless/ath/carl9170/rx.c
@@ -150,7 +150,8 @@ static void carl9170_cmd_callback(struct ar9170 *ar, u32 len, void *buffer)
spin_lock(&ar->cmd_lock);
if (ar->readbuf) {
if (len >= 4)
- memcpy(ar->readbuf, buffer + 4, len - 4);
+ memcpy(ar->readbuf, buffer + 4,
+ min_t(u32, len - 4, ar->readlen));
ar->readbuf = NULL;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 149/602] wifi: carl9170: fix OOB read from off-by-two in TX status handler
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (147 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 148/602] wifi: carl9170: bound memcpy length in cmd callback to prevent OOB read Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 150/602] wifi: carl9170: fix buffer overflow in rx_stream failover path Greg Kroah-Hartman
` (456 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Tristan Madani, Christian Lamparter,
Jeff Johnson, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <tristan@talencesecurity.com>
[ Upstream commit a3f42f1049ad80c65560d2b078ad426c3134f78d ]
The bounds check in carl9170_tx_process_status() uses
`i > ((cmd->hdr.len / 2) + 1)` which is off by two, allowing
2 extra iterations past valid _tx_status entries when the firmware-
controlled hdr.ext exceeds hdr.len/2. Fix by using the correct
comparison `i >= (cmd->hdr.len / 2)`.
Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend")
Signed-off-by: Tristan Madani <tristan@talencesecurity.com>
Acked-by: Christian Lamparter <chunkeey@gmail.com>
Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac
Link: https://patch.msgid.link/20260421134929.325662-3-tristmd@gmail.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/ath/carl9170/tx.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c
index 0226c31a6cae26..8280d264d5e2e8 100644
--- a/drivers/net/wireless/ath/carl9170/tx.c
+++ b/drivers/net/wireless/ath/carl9170/tx.c
@@ -693,7 +693,7 @@ void carl9170_tx_process_status(struct ar9170 *ar,
unsigned int i;
for (i = 0; i < cmd->hdr.ext; i++) {
- if (WARN_ON(i > ((cmd->hdr.len / 2) + 1))) {
+ if (WARN_ON(i >= (cmd->hdr.len / 2))) {
print_hex_dump_bytes("UU:", DUMP_PREFIX_NONE,
(void *) cmd, cmd->hdr.len + 4);
break;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 150/602] wifi: carl9170: fix buffer overflow in rx_stream failover path
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (148 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 149/602] wifi: carl9170: fix OOB read from off-by-two in TX status handler Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 151/602] btrfs: declare btrfs_ioctl_search_args_v2::buf as __u8 Greg Kroah-Hartman
` (455 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Tristan Madani, Christian Lamparter,
Jeff Johnson, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <tristan@talencesecurity.com>
[ Upstream commit a1a21995c2e1cc2ca6b2226cfe4f5f018370182a ]
The failover continuation in carl9170_rx_stream() copies the full tlen
from the second USB transfer instead of capping at rx_failover_missing
bytes. When both transfers are near maximum size, the total exceeds the
65535-byte failover SKB, triggering skb_over_panic.
Limit the copy size to the missing byte count.
Fixes: a84fab3cbfdc ("carl9170: 802.11 rx/tx processing and usb backend")
Signed-off-by: Tristan Madani <tristan@talencesecurity.com>
Acked-by: Christian Lamparter <chunkeey@gmail.com>
Closes: https://syzkaller.appspot.com/bug?extid=5c1ca6ccaa1215781cac
Link: https://patch.msgid.link/20260421134929.325662-4-tristmd@gmail.com
[Fix checkpatch CHECK:PARENTHESIS_ALIGNMENT]
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/ath/carl9170/rx.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c
index 9a25c2a540b95f..bda30b1f940459 100644
--- a/drivers/net/wireless/ath/carl9170/rx.c
+++ b/drivers/net/wireless/ath/carl9170/rx.c
@@ -918,7 +918,9 @@ static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len)
}
}
- skb_put_data(ar->rx_failover, tbuf, tlen);
+ skb_put_data(ar->rx_failover, tbuf,
+ min_t(unsigned int, tlen,
+ ar->rx_failover_missing));
ar->rx_failover_missing -= tlen;
if (ar->rx_failover_missing <= 0) {
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 151/602] btrfs: declare btrfs_ioctl_search_args_v2::buf as __u8
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (149 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 150/602] wifi: carl9170: fix buffer overflow in rx_stream failover path Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 152/602] btrfs: dont propagate EXTENT_FLAG_LOGGING to split extent maps Greg Kroah-Hartman
` (454 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Qu Wenruo, You-Kai Zheng,
David Sterba, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: You-Kai Zheng <ykzheng@synology.com>
[ Upstream commit b95181f3929ff98949fa9460ca93eccebbf2d7fc ]
The variable-sized buffer buf in struct btrfs_ioctl_search_args_v2 is
declared as __u64[], but it holds a packed byte stream of search results,
where all offsets into the buffer are in bytes.
Declaring buf as __u64[] makes it easy for user space to write incorrect
pointer arithmetic: adding a byte offset directly to a __u64 pointer
scales the offset by 8, landing at byte position offset*8 instead of
offset.
This recently caused an infinite loop in btrfs-progs: the accessor read
all-zero data from misaddressed items, which fed zeroed search keys back
into the ioctl loop and spun forever. The issue was worked around at the
time by disabling TREE_SEARCH_V2 entirely in btrfs-progs (d73e69824854:
"btrfs-progs: temporarily disable usage of v2 of search tree ioctl").
The kernel side already treats buf as a byte buffer, so change the
declaration to __u8[] to match the actual semantics and prevent similar
misuse in user space. The change is ABI compatible: both the structure size
and alignment are unchanged.
Fixes: cc68a8a5a433 ("btrfs: new ioctl TREE_SEARCH_V2")
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: You-Kai Zheng <ykzheng@synology.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
include/uapi/linux/btrfs.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h
index cdf6ad872149cd..8c5490c6ff99db 100644
--- a/include/uapi/linux/btrfs.h
+++ b/include/uapi/linux/btrfs.h
@@ -597,7 +597,7 @@ struct btrfs_ioctl_search_args_v2 {
__u64 buf_size; /* in - size of buffer
* out - on EOVERFLOW: needed size
* to store item */
- __u64 buf[]; /* out - found items */
+ __u8 buf[]; /* out - found items */
};
/* With a @src_length of zero, the range from @src_offset->EOF is cloned! */
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 152/602] btrfs: dont propagate EXTENT_FLAG_LOGGING to split extent maps
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (150 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 151/602] btrfs: declare btrfs_ioctl_search_args_v2::buf as __u8 Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 153/602] btrfs: free mapping node on duplicate reloc root insert Greg Kroah-Hartman
` (453 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jeff Layton, Filipe Manana,
Leo Martins, David Sterba, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leo Martins <loemra.dev@gmail.com>
[ Upstream commit 5eff4d5b17fa1950e80bfd1ba43dc0699e61a644 ]
When btrfs_drop_extent_map_range() splits an extent map, the new split
maps inherit the original map's flags through a local 'flags' variable.
Commit f86f7a75e2fb ("btrfs: use the flags of an extent map to identify
the compression type") changed the EXTENT_FLAG_LOGGING clearing to
operate on em->flags instead of that local 'flags' copy, so a split of
an extent map that is currently being logged wrongly inherits
EXTENT_FLAG_LOGGING.
The flag is then never cleared on the split, and when it is freed while
still on the inode's modified_extents list (for example by the extent
map shrinker) it trips the WARN_ON(!list_empty(&em->list)) in
btrfs_free_extent_map() and leads to a use-after-free.
Clear EXTENT_FLAG_LOGGING from the local 'flags' copy used for the
splits and only clear EXTENT_FLAG_PINNED from em->flags, restoring the
behaviour prior to f86f7a75e2fb.
CC: Jeff Layton <jlayton@kernel.org>
Link: https://lore.kernel.org/all/20260629-btrfs-skip-logging-v1-1-4e3a28c1acaf@kernel.org/
Fixes: f86f7a75e2fb ("btrfs: use the flags of an extent map to identify the compression type")
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Leo Martins <loemra.dev@gmail.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/btrfs/extent_map.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
index 36af9aa9aab13f..044970109c7b58 100644
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -859,13 +859,13 @@ void btrfs_drop_extent_map_range(struct btrfs_inode *inode, u64 start, u64 end,
goto next;
}
- flags = em->flags;
/*
* In case we split the extent map, we want to preserve the
* EXTENT_FLAG_LOGGING flag on our extent map, but we don't want
* it on the new extent maps.
*/
- em->flags &= ~(EXTENT_FLAG_PINNED | EXTENT_FLAG_LOGGING);
+ flags = em->flags & ~EXTENT_FLAG_LOGGING;
+ em->flags &= ~EXTENT_FLAG_PINNED;
modified = !list_empty(&em->list);
/*
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 153/602] btrfs: free mapping node on duplicate reloc root insert
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (151 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 152/602] btrfs: dont propagate EXTENT_FLAG_LOGGING to split extent maps Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 154/602] ASoC: tas2781: bound firmware description string parsing Greg Kroah-Hartman
` (452 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Qu Wenruo, Guanghui Yang,
David Sterba, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guanghui Yang <3497809730@qq.com>
[ Upstream commit 6a8269b6459ed870a8156c106a0f597383907872 ]
__add_reloc_root() allocates a mapping_node before inserting it into
rc->reloc_root_tree. If rb_simple_insert() finds an existing entry, it
returns the existing rb_node and leaves the newly allocated node unlinked.
The error path then returns -EEXIST without freeing the new node. Since
the node was never inserted into reloc_root_tree, the later cleanup in
put_reloc_control() cannot find it either.
Free the newly allocated node before returning -EEXIST.
The callers currently assert that -EEXIST should not happen, so this is a
defensive cleanup for an unexpected duplicate insert path. If the path is
ever reached, the local allocation should still be released.
Fixes: 57a304cfd43b ("btrfs: do not panic in __add_reloc_root")
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Guanghui Yang <3497809730@qq.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/btrfs/relocation.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index d2a1323e8b1034..8130bfd1abbf2b 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -580,6 +580,7 @@ static int __add_reloc_root(struct btrfs_root *root)
btrfs_err(fs_info,
"Duplicate root found for start=%llu while inserting into relocation tree",
node->bytenr);
+ kfree(node);
return -EEXIST;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 154/602] ASoC: tas2781: bound firmware description string parsing
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (152 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 153/602] btrfs: free mapping node on duplicate reloc root insert Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 155/602] ALSA: hda: cs35l41: Fix NULL pointer dereference in cs35l41_get_acpi_mute_state() Greg Kroah-Hartman
` (451 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Pengpeng Hou, Mark Brown,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <pengpeng@iscas.ac.cn>
[ Upstream commit bc889dfcea9294a1eae7f8e2f3573a90764ae4d0 ]
The TAS2781 firmware parser reads several variable-length description
strings with strlen() before checking that the string terminator is
present inside the firmware blob. A malformed firmware image without a
NUL terminator can therefore make the parser walk past the end of the
firmware buffer before the later size checks run.
Add a small bounded string-length helper and use it for all description
fields that are parsed from the firmware buffer. Keep the existing size
checks for the fixed bytes that follow each string.
Fixes: 915f5eadebd2 ("ASoC: tas2781: firmware lib")
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Link: https://patch.msgid.link/20260706144540.93929-1-pengpeng@iscas.ac.cn
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
sound/soc/codecs/tas2781-fmwlib.c | 63 ++++++++++++++++++++++++++++---
1 file changed, 57 insertions(+), 6 deletions(-)
diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c
index 0aeb88abbf52f1..a2c4602eb57440 100644
--- a/sound/soc/codecs/tas2781-fmwlib.c
+++ b/sound/soc/codecs/tas2781-fmwlib.c
@@ -11,6 +11,7 @@
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/limits.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
@@ -891,13 +892,42 @@ static int tasdevice_load_block_kernel(
return 0;
}
+static int tasdevice_fw_strnlen(const struct firmware *fmw, int offset)
+{
+ const u8 *start;
+ const u8 *nul;
+ size_t remaining;
+ size_t len;
+
+ if (offset < 0 || offset >= fmw->size)
+ return -EINVAL;
+
+ start = fmw->data + offset;
+ remaining = fmw->size - offset;
+ nul = memchr(start, '\0', remaining);
+ if (!nul)
+ return -EINVAL;
+
+ len = nul - start;
+ if (len > INT_MAX)
+ return -EOVERFLOW;
+
+ return len;
+}
+
static int fw_parse_variable_hdr(struct tasdevice_priv
*tas_priv, struct tasdevice_dspfw_hdr *fw_hdr,
const struct firmware *fmw, int offset)
{
const unsigned char *buf = fmw->data;
- int len = strlen((char *)&buf[offset]);
+ int len;
+ len = tasdevice_fw_strnlen(fmw, offset);
+ if (len < 0) {
+ dev_err(tas_priv->dev, "%s: Description error\n", __func__);
+ offset = len;
+ goto out;
+ }
len++;
if (offset + len + 8 > fmw->size) {
@@ -1029,7 +1059,12 @@ static int fw_parse_data(struct tasdevice_fw *tas_fmw,
memcpy(img_data->name, &data[offset], 64);
offset += 64;
- n = strlen((char *)&data[offset]);
+ n = tasdevice_fw_strnlen(fmw, offset);
+ if (n < 0) {
+ dev_err(tas_fmw->dev, "%s: Description error\n", __func__);
+ offset = n;
+ goto out;
+ }
n++;
if (offset + n + 2 > fmw->size) {
dev_err(tas_fmw->dev, "%s: Description error\n", __func__);
@@ -1102,7 +1137,12 @@ static int fw_parse_program_data(struct tasdevice_priv *tas_priv,
}
offset += 64;
- n = strlen((char *)&buf[offset]);
+ n = tasdevice_fw_strnlen(fmw, offset);
+ if (n < 0) {
+ dev_err(tas_priv->dev, "Description err\n");
+ offset = n;
+ goto out;
+ }
/* skip '\0' and 5 unused bytes */
n += 6;
if (offset + n > fmw->size) {
@@ -1165,7 +1205,12 @@ static int fw_parse_configuration_data(
memcpy(config->name, &data[offset], 64);
offset += 64;
- n = strlen((char *)&data[offset]);
+ n = tasdevice_fw_strnlen(fmw, offset);
+ if (n < 0) {
+ dev_err(tas_priv->dev, "Description err\n");
+ offset = n;
+ goto out;
+ }
n += 15;
if (offset + n > fmw->size) {
dev_err(tas_priv->dev, "Description err\n");
@@ -1819,7 +1864,8 @@ static int fw_parse_calibration_data(struct tasdevice_priv *tas_priv,
{
struct tasdevice_calibration *calibration;
unsigned char *data = (unsigned char *)fmw->data;
- unsigned int i, n;
+ unsigned int i;
+ int n;
if (offset + 2 > fmw->size) {
dev_err(tas_priv->dev, "%s: Calibrations error\n", __func__);
@@ -1851,7 +1897,12 @@ static int fw_parse_calibration_data(struct tasdevice_priv *tas_priv,
calibration = &(tas_fmw->calibrations[i]);
offset += 64;
- n = strlen((char *)&data[offset]);
+ n = tasdevice_fw_strnlen(fmw, offset);
+ if (n < 0) {
+ dev_err(tas_priv->dev, "Description err\n");
+ offset = n;
+ goto out;
+ }
/* skip '\0' and 2 unused bytes */
n += 3;
if (offset + n > fmw->size) {
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 155/602] ALSA: hda: cs35l41: Fix NULL pointer dereference in cs35l41_get_acpi_mute_state()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (153 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 154/602] ASoC: tas2781: bound firmware description string parsing Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 156/602] ALSA: hda: cs35l41: validate and free ACPI mute object Greg Kroah-Hartman
` (450 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Denis Arefev, Takashi Iwai,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Denis Arefev <arefev@swemel.ru>
[ Upstream commit 8527bbb33936340525a3504a00932b2f8fd75754 ]
Return value of a function acpi_evaluate_dsm() is dereferenced without
checking for NULL, but it is usually checked for this function.
acpi_evaluate_dsm() may return NULL, when acpi_evaluate_object() returns
acpi_status other than ACPI_SUCCESS, so add a check to prevent the crach.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
Fixes: 447106e92a0c ("ALSA: hda: cs35l41: Support mute notifications for CS35L41 HDA")
Cc: stable@vger.kernel.org
Signed-off-by: Denis Arefev <arefev@swemel.ru>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Stable-dep-of: 3b597d24dc04 ("ALSA: hda: cs35l41: validate and free ACPI mute object")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
sound/pci/hda/cs35l41_hda.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c
index 099b8e9582b841..bc84415416aae5 100644
--- a/sound/pci/hda/cs35l41_hda.c
+++ b/sound/pci/hda/cs35l41_hda.c
@@ -1403,6 +1403,8 @@ static int cs35l41_get_acpi_mute_state(struct cs35l41_hda *cs35l41, acpi_handle
if (cs35l41_dsm_supported(handle, CS35L41_DSM_GET_MUTE)) {
ret = acpi_evaluate_dsm(handle, &guid, 0, CS35L41_DSM_GET_MUTE, NULL);
+ if (!ret)
+ return -EINVAL;
mute = *ret->buffer.pointer;
dev_dbg(cs35l41->dev, "CS35L41_DSM_GET_MUTE: %d\n", mute);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 156/602] ALSA: hda: cs35l41: validate and free ACPI mute object
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (154 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 155/602] ALSA: hda: cs35l41: Fix NULL pointer dereference in cs35l41_get_acpi_mute_state() Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 157/602] ASoC: bt-sco: fix duplicate DAPM widget names for wideband DAI Greg Kroah-Hartman
` (449 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Guangshuo Li, Takashi Iwai,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <lgs201920130244@gmail.com>
[ Upstream commit 3b597d24dc0455ae926f1053f97c2725038fc3cd ]
cs35l41_get_acpi_mute_state() evaluates a _DSM method to get the ACPI
mute state and reads the first byte from the returned object.
However, the returned ACPI object is owned by the caller and is never
freed after use, so each successful query leaks the _DSM result object.
The code also assumes that the returned object is a buffer with at least
one byte. A malformed firmware response can return a different object
type or an empty buffer, and the direct ret->buffer.pointer dereference
can then access an invalid pointer.
Use the typed _DSM helper, validate that the returned buffer contains at
least one byte, and free the ACPI object after reading it.
Fixes: 447106e92a0c ("ALSA: hda: cs35l41: Support mute notifications for CS35L41 HDA")
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
Link: https://patch.msgid.link/20260708113625.752913-1-lgs201920130244@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
sound/pci/hda/cs35l41_hda.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c
index bc84415416aae5..031978a62cb996 100644
--- a/sound/pci/hda/cs35l41_hda.c
+++ b/sound/pci/hda/cs35l41_hda.c
@@ -1402,10 +1402,19 @@ static int cs35l41_get_acpi_mute_state(struct cs35l41_hda *cs35l41, acpi_handle
guid_parse(CS35L41_UUID, &guid);
if (cs35l41_dsm_supported(handle, CS35L41_DSM_GET_MUTE)) {
- ret = acpi_evaluate_dsm(handle, &guid, 0, CS35L41_DSM_GET_MUTE, NULL);
+ ret = acpi_evaluate_dsm_typed(handle, &guid, 0,
+ CS35L41_DSM_GET_MUTE, NULL,
+ ACPI_TYPE_BUFFER);
+
if (!ret)
return -EINVAL;
+ if (!ret->buffer.length || !ret->buffer.pointer) {
+ ACPI_FREE(ret);
+ return -EINVAL;
+ }
+
mute = *ret->buffer.pointer;
+ ACPI_FREE(ret);
dev_dbg(cs35l41->dev, "CS35L41_DSM_GET_MUTE: %d\n", mute);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 157/602] ASoC: bt-sco: fix duplicate DAPM widget names for wideband DAI
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (155 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 156/602] ALSA: hda: cs35l41: validate and free ACPI mute object Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 158/602] ASoC: cs35l56: Dont use devres to unregister component Greg Kroah-Hartman
` (448 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Shengjiu Wang, Mark Brown,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shengjiu Wang <shengjiu.wang@nxp.com>
[ Upstream commit 0b604e886ece11b71c4daaeccc512c784b89b014 ]
The bt-sco-pcm-wb DAI uses the same stream_name strings as bt-sco-pcm
("Playback" and "Capture"). This causes duplicate DAPM AIF widget
names within the same component, leading to debugfs warnings:
debugfs: 'Playback' already exists in 'dapm'
debugfs: 'Capture' already exists in 'dapm'
Give the wideband DAI distinct stream names ("WB Playback" and
"WB Capture") and add corresponding DAPM AIF widgets and routes for
them.
Fixes: 5947e1b4992e ("ASoC: bt-sco: extend rate and add a general compatible string")
Assisted-by: VeroCoder:claude-sonnet-4-5
Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
Link: https://patch.msgid.link/20260715100620.1387159-1-shengjiu.wang@oss.nxp.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
sound/soc/codecs/bt-sco.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/sound/soc/codecs/bt-sco.c b/sound/soc/codecs/bt-sco.c
index 3afcef2dfa3529..c0bf45b76cb8c5 100644
--- a/sound/soc/codecs/bt-sco.c
+++ b/sound/soc/codecs/bt-sco.c
@@ -17,11 +17,17 @@ static const struct snd_soc_dapm_widget bt_sco_widgets[] = {
SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_OUT("BT_SCO_TX", "Capture", 0,
SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("BT_SCO_RX_WB", "WB Playback", 0,
+ SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("BT_SCO_TX_WB", "WB Capture", 0,
+ SND_SOC_NOPM, 0, 0),
};
static const struct snd_soc_dapm_route bt_sco_routes[] = {
{ "BT_SCO_TX", NULL, "RX" },
{ "TX", NULL, "BT_SCO_RX" },
+ { "BT_SCO_TX_WB", NULL, "RX" },
+ { "TX", NULL, "BT_SCO_RX_WB" },
};
static struct snd_soc_dai_driver bt_sco_dai[] = {
@@ -45,14 +51,14 @@ static struct snd_soc_dai_driver bt_sco_dai[] = {
{
.name = "bt-sco-pcm-wb",
.playback = {
- .stream_name = "Playback",
+ .stream_name = "WB Playback",
.channels_min = 1,
.channels_max = 1,
.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
},
.capture = {
- .stream_name = "Capture",
+ .stream_name = "WB Capture",
.channels_min = 1,
.channels_max = 1,
.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 158/602] ASoC: cs35l56: Dont use devres to unregister component
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (156 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 157/602] ASoC: bt-sco: fix duplicate DAPM widget names for wideband DAI Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 159/602] ASoC: cs35l56: Fix potential probe() deadlock Greg Kroah-Hartman
` (447 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Richard Fitzgerald, Mark Brown,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Richard Fitzgerald <rf@opensource.cirrus.com>
[ Upstream commit bee87cf0f1248c0f20710d7a79df41fe892d9f88 ]
Manually call snd_soc_unregister_component() from cs35l56_remove()
instead of using devres cleanup. This ensures that the component is
destroyed before cs35l56_remove() starts cleanup of anything the
component code could be using.
Devres cleanup happens after the driver remove() callback, so if
snd_soc_register_component() is used, it will not be destroyed until
after cs35l56_remove() has returned. But there is some cleanup that
must be done in cs35l56_remove(), or wrapped in a custom devres
cleanup handler to ensure correct ordering. The simplest option is
to call snd_soc_unregister_component() at the start of cs35l56_remove().
Fixes: e49611252900 ("ASoC: cs35l56: Add driver for Cirrus Logic CS35L56")
Closes: https://sashiko.dev/#/patchset/20260501103002.2843735-1-rf%40opensource.cirrus.com
Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Link: https://patch.msgid.link/20260505161124.3621000-2-rf@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Stable-dep-of: 93c2a8ea2454 ("ASoC: cs35l56: Fix potential probe() deadlock")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
sound/soc/codecs/cs35l56.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c
index c78f7f95f127d0..ee5357ac0ceab5 100644
--- a/sound/soc/codecs/cs35l56.c
+++ b/sound/soc/codecs/cs35l56.c
@@ -1330,9 +1330,9 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56)
goto err;
}
- ret = devm_snd_soc_register_component(cs35l56->base.dev,
- &soc_component_dev_cs35l56,
- cs35l56_dai, ARRAY_SIZE(cs35l56_dai));
+ ret = snd_soc_register_component(cs35l56->base.dev,
+ &soc_component_dev_cs35l56,
+ cs35l56_dai, ARRAY_SIZE(cs35l56_dai));
if (ret < 0) {
dev_err_probe(cs35l56->base.dev, ret, "Register codec failed\n");
goto err_remove_wm_adsp;
@@ -1434,6 +1434,8 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_init, SND_SOC_CS35L56_CORE);
void cs35l56_remove(struct cs35l56_private *cs35l56)
{
+ snd_soc_unregister_component(cs35l56->base.dev);
+
cs35l56->base.init_done = false;
/*
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 159/602] ASoC: cs35l56: Fix potential probe() deadlock
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (157 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 158/602] ASoC: cs35l56: Dont use devres to unregister component Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 160/602] ASoC: cs35l56: Use complete_all() to signal init_completion Greg Kroah-Hartman
` (446 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Salman S. Tahir, Richard Fitzgerald,
Mark Brown, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Richard Fitzgerald <rf@opensource.cirrus.com>
[ Upstream commit 93c2a8ea2454b7b14eb378a58cad8a83c0ffc903 ]
On I2C/SPI call cs35l56_init() before calling
snd_soc_register_component() to prevent the potential for a deadlock
on init_completion.
For most buses all the hardware would be ready when probe() returns,
but on SoundWire, probe() must return before the SoundWire bus driver
will enumerate the device. All access to the registers must be deferred
until the driver receives an ATTACHED notification. But anything that
could return -EPROBE_DEFER must be called during probe, and that includes
snd_soc_register_component(). Because of that, on SoundWire the ASoC
component can be created before the registers are accssible, so
cs35l56_component_probe() waits for init_completion to signal that the
registers are accessible.
On I2C/SPI this 2-stage startup isn't required so their probe()
functions simply called cs35l56_common_probe() and then cs35l56_init().
The problem with this was that snd_soc_register_component() was still
called early. If this triggered ASoC to create the card, ASoC would call
cs35l56_component_probe() which waits on init_completion - but this would
be running inside the cs35l56 driver probe() so blocking it from reaching
the code that signals init_completion, causing a deadlock.
Fixes: e496112529006 ("ASoC: cs35l56: Add driver for Cirrus Logic CS35L56")
Reported-by: Salman S. Tahir <salman.abusaad@gmail.com>
Closes: https://lore.kernel.org/linux-sound/95c21574-97d5-4311-9263-9e174d22d22c@opensource.cirrus.com/T/#u
Tested-by: Salman S. Tahir <salman.abusaad@gmail.com>
Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Link: https://patch.msgid.link/20260716132045.1469156-2-rf@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
sound/soc/codecs/cs35l56-i2c.c | 4 +---
sound/soc/codecs/cs35l56-spi.c | 4 +---
sound/soc/codecs/cs35l56.c | 15 +++++++++++++++
3 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/sound/soc/codecs/cs35l56-i2c.c b/sound/soc/codecs/cs35l56-i2c.c
index 2bd2ff75cd5047..93ee9e60ba79c9 100644
--- a/sound/soc/codecs/cs35l56-i2c.c
+++ b/sound/soc/codecs/cs35l56-i2c.c
@@ -40,9 +40,7 @@ static int cs35l56_i2c_probe(struct i2c_client *client)
if (ret != 0)
return ret;
- ret = cs35l56_init(cs35l56);
- if (ret == 0)
- ret = cs35l56_irq_request(&cs35l56->base, client->irq);
+ ret = cs35l56_irq_request(&cs35l56->base, client->irq);
if (ret < 0)
cs35l56_remove(cs35l56);
diff --git a/sound/soc/codecs/cs35l56-spi.c b/sound/soc/codecs/cs35l56-spi.c
index 568f554a8638bf..a5bae05d6433e9 100644
--- a/sound/soc/codecs/cs35l56-spi.c
+++ b/sound/soc/codecs/cs35l56-spi.c
@@ -41,9 +41,7 @@ static int cs35l56_spi_probe(struct spi_device *spi)
if (ret != 0)
return ret;
- ret = cs35l56_init(cs35l56);
- if (ret == 0)
- ret = cs35l56_irq_request(&cs35l56->base, spi->irq);
+ ret = cs35l56_irq_request(&cs35l56->base, spi->irq);
if (ret < 0)
cs35l56_remove(cs35l56);
diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c
index ee5357ac0ceab5..b657a0df1ed166 100644
--- a/sound/soc/codecs/cs35l56.c
+++ b/sound/soc/codecs/cs35l56.c
@@ -1330,6 +1330,16 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56)
goto err;
}
+ /*
+ * On SoundWire the cs35l56_init() cannot be run until after the
+ * device has been enumerated by the SoundWire core.
+ */
+ if (!cs35l56->sdw_peripheral) {
+ ret = cs35l56_init(cs35l56);
+ if (ret)
+ goto err_remove_wm_adsp;
+ }
+
ret = snd_soc_register_component(cs35l56->base.dev,
&soc_component_dev_cs35l56,
cs35l56_dai, ARRAY_SIZE(cs35l56_dai));
@@ -1344,6 +1354,11 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56)
wm_adsp2_remove(&cs35l56->dsp);
err:
+ if (pm_runtime_enabled(cs35l56->base.dev)) {
+ pm_runtime_dont_use_autosuspend(cs35l56->base.dev);
+ pm_runtime_disable(cs35l56->base.dev);
+ }
+
gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 160/602] ASoC: cs35l56: Use complete_all() to signal init_completion
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (158 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 159/602] ASoC: cs35l56: Fix potential probe() deadlock Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 161/602] wifi: iwlwifi: mvm: validate SAR GEO response payload size Greg Kroah-Hartman
` (445 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Richard Fitzgerald, Mark Brown,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Richard Fitzgerald <rf@opensource.cirrus.com>
[ Upstream commit e0bffb63a2eda0af82ed7e6357ac67c2db990c21 ]
In cs35l56_init() use complete_all() to signal init_completion instead
of complete().
cs35l56_init() was signaling init_completion using the complete() function.
This only releases ONE waiter.
If cs35l56_component_probe() was called multiple times the first time
would consume that one signal, then future calls would timeout waiting for
the completion. This could happen if:
- The component is probed, removed, then probed again without the cs35l56
module being removed.
- A call to component_probe() returns an error and ASoC calls it again
later.
It should use complete_all() so that after it has been signaled it will
allow any code that waits on it to continue immediately.
The one case where the driver must wait for initialization to run again is
when waiting for a reboot after firmware download, and here the code
correctly calls reinit_completion() first.
Fixes: e496112529006 ("ASoC: cs35l56: Add driver for Cirrus Logic CS35L56")
Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Link: https://patch.msgid.link/20260716132045.1469156-3-rf@opensource.cirrus.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
sound/soc/codecs/cs35l56.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c
index b657a0df1ed166..2eff866713aefd 100644
--- a/sound/soc/codecs/cs35l56.c
+++ b/sound/soc/codecs/cs35l56.c
@@ -1441,7 +1441,7 @@ int cs35l56_init(struct cs35l56_private *cs35l56)
return dev_err_probe(cs35l56->base.dev, ret, "Failed to write ASP1_CONTROL3\n");
cs35l56->base.init_done = true;
- complete(&cs35l56->init_completion);
+ complete_all(&cs35l56->init_completion);
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 161/602] wifi: iwlwifi: mvm: validate SAR GEO response payload size
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (159 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 160/602] ASoC: cs35l56: Use complete_all() to signal init_completion Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 162/602] wifi: iwlwifi: mvm: fix read in wake packet notification handler Greg Kroah-Hartman
` (444 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Pagadala Yesu Anjaneyulu,
Miri Korenblit, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pagadala Yesu Anjaneyulu <pagadala.yesu.anjaneyulu@intel.com>
[ Upstream commit 408d7da38272ce48e2db79b8a9895999f94d7655 ]
The SAR GEO command response is cast to
iwl_geo_tx_power_profiles_resp without verifying the payload length.
A malformed or unexpected firmware response can lead to reading an
invalid structure layout.
Add an explicit size check before accessing the response data and
return -EIO when the payload size is wrong.
Fixes: f604324eefec ("iwlwifi: remove iwl_validate_sar_geo_profile() export")
Signed-off-by: Pagadala Yesu Anjaneyulu <pagadala.yesu.anjaneyulu@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20260715215523.7e749b7d374a.I4ef54548bff6c6e7c7a57bee771ac12508aad677@changeid
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
index 2b9a684cf61d57..4bad012472e1e9 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c
@@ -976,12 +976,22 @@ int iwl_mvm_get_sar_geo_profile(struct iwl_mvm *mvm)
return ret;
}
+ if (IWL_FW_CHECK(mvm,
+ iwl_rx_packet_payload_len(cmd.resp_pkt) !=
+ sizeof(*resp),
+ "Wrong size for iwl_geo_tx_power_profiles_resp: %d\n",
+ iwl_rx_packet_payload_len(cmd.resp_pkt))) {
+ ret = -EIO;
+ goto out;
+ }
+
resp = (void *)cmd.resp_pkt->data;
ret = le32_to_cpu(resp->profile_idx);
if (WARN_ON(ret > BIOS_GEO_MAX_PROFILE_NUM))
ret = -EIO;
+out:
iwl_free_resp(&cmd);
return ret;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 162/602] wifi: iwlwifi: mvm: fix read in wake packet notification handler
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (160 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 161/602] wifi: iwlwifi: mvm: validate SAR GEO response payload size Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 163/602] usb: atm: ueagle-atm: reject descriptors that confuse probe and disconnect Greg Kroah-Hartman
` (443 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Shahar Tzarfati, Miri Korenblit,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shahar Tzarfati <shahar.tzarfati@intel.com>
[ Upstream commit 9d7657aae8c1579584c67b0b66114a6a98db8b2f ]
In iwl_mvm_wowlan_store_wake_pkt(), packet_len was initialized from
notif->wake_packet_length before the explicit check that len >=
sizeof(*notif).
Move the assignment of packet_len to after the size check so that
notif->wake_packet_length is only accessed once the payload length
has been validated.
Fixes: 219ed58feda9 ("wifi: iwlwifi: mvm: Add support for wowlan wake packet notification")
Signed-off-by: Shahar Tzarfati <shahar.tzarfati@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20260715215523.99d5cf85a528.Ic4aa736011d4fe88e0cd19723d1d48bb24642198@changeid
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/intel/iwlwifi/mvm/d3.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index 817ddc7103af27..dd31b9b2cd39bf 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -3144,7 +3144,7 @@ static int iwl_mvm_wowlan_store_wake_pkt(struct iwl_mvm *mvm,
struct iwl_wowlan_status_data *status,
u32 len)
{
- u32 data_size, packet_len = le32_to_cpu(notif->wake_packet_length);
+ u32 data_size, packet_len;
if (len < sizeof(*notif)) {
IWL_ERR(mvm, "Invalid WoWLAN wake packet notification!\n");
@@ -3163,6 +3163,7 @@ static int iwl_mvm_wowlan_store_wake_pkt(struct iwl_mvm *mvm,
return -EIO;
}
+ packet_len = le32_to_cpu(notif->wake_packet_length);
data_size = len - offsetof(struct iwl_wowlan_wake_pkt_notif, wake_packet);
/* data_size got the padding from the notification, remove it. */
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 163/602] usb: atm: ueagle-atm: reject descriptors that confuse probe and disconnect
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (161 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 162/602] wifi: iwlwifi: mvm: fix read in wake packet notification handler Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 164/602] drivers/virt: pkvm: Fix end calculation in mmio_guard_ioremap_hook() Greg Kroah-Hartman
` (442 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, syzbot+e62a973f8322b3bbe3ac,
Diego Fernando Mancera Gomez, Stanislaw Gruszka, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Diego Fernando Mancera Gomez <diegomancera.dev@gmail.com>
[ Upstream commit 71132cedd1ecbc4032d76e9928c18a10f7e39b80 ]
uea_probe() distinguishes a pre-firmware device from a post-firmware one
using the USB id (UEA_IS_PREFIRM()), and stores a different object as the
interface data in each case: a 'struct completion' for a pre-firmware
device (to be waited on in .disconnect()), or a 'struct usbatm_data' for a
post-firmware one.
uea_disconnect() instead tells the two apart by the number of interfaces
of the active configuration (a pre-firmware device exposes a single
interface, ADI930 has 2 and eagle has 3), and casts the interface data
accordingly.
Because the two handlers use different criteria, a crafted device that
advertises a pre-firmware id together with a multi-interface descriptor
(or a post-firmware id with a single interface) makes them disagree: the
small 'struct completion' stored by uea_probe() is then passed to
usbatm_usb_disconnect(), which casts it to 'struct usbatm_data' and takes
instance->serialize, reading past the end of the allocation:
BUG: KASAN: slab-out-of-bounds in __mutex_lock+0x152a/0x1b80
Read of size 8 at addr ffff8880470e2c60 by task kworker/1:2/982
...
__mutex_lock+0x152a/0x1b80
usbatm_usb_disconnect+0x70/0x820
uea_disconnect+0x133/0x2c0
usb_unbind_interface+0x1dd/0x9e0
...
which belongs to the cache kmalloc-96 of size 96
The buggy address is located 0 bytes to the right of
allocated 96-byte region [ffff8880470e2c00, ffff8880470e2c60)
Reject such inconsistent descriptors in uea_probe() so that both handlers
always make the same pre/post-firmware decision.
Reported-by: syzbot+e62a973f8322b3bbe3ac@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=e62a973f8322b3bbe3ac
Fixes: e2674dfbed8a ("usb: atm: ueagle-atm: wait for pre-firmware load in .disconnect()")
Signed-off-by: Diego Fernando Mancera Gomez <diegomancera.dev@gmail.com>
Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
Link: https://patch.msgid.link/20260717080704.1264-1-diegomancera.dev@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/usb/atm/ueagle-atm.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index cd53d36aa30748..dad42820814022 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -2590,6 +2590,7 @@ static struct usbatm_driver uea_usbatm_driver = {
static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
struct usb_device *usb = interface_to_usbdev(intf);
+ bool single_iface = usb->config->desc.bNumInterfaces == 1;
int ret;
uea_enters(usb);
@@ -2599,6 +2600,22 @@ static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id)
le16_to_cpu(usb->descriptor.bcdDevice),
chip_name[UEA_CHIP_VERSION(id)]);
+ /*
+ * uea_probe() decides between the pre-firmware and post-firmware case
+ * from the USB id and stores a different object as interface data in
+ * each case: a struct completion for a pre-firmware device, a struct
+ * usbatm_data for a post-firmware one. uea_disconnect() instead tells
+ * the two apart by the number of interfaces (a pre-firmware device
+ * exposes a single interface, ADI930 has 2 and eagle has 3). A crafted
+ * device advertising a pre-firmware id together with a multi-interface
+ * descriptor (or the other way around) makes the two disagree, so that
+ * usbatm_usb_disconnect() treats the small completion object as a
+ * struct usbatm_data and reads out of bounds. Reject such inconsistent
+ * descriptors so both paths make the same decision.
+ */
+ if (UEA_IS_PREFIRM(id) != single_iface)
+ return -ENODEV;
+
usb_reset_device(usb);
if (UEA_IS_PREFIRM(id)) {
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 164/602] drivers/virt: pkvm: Fix end calculation in mmio_guard_ioremap_hook()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (162 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 163/602] usb: atm: ueagle-atm: reject descriptors that confuse probe and disconnect Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 165/602] hwmon: (asus-ec-sensors) fix looping over banks while reading from EC Greg Kroah-Hartman
` (441 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Mostafa Saleh, Catalin Marinas,
Aneesh Kumar K.V (Arm), Will Deacon, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mostafa Saleh <smostafa@google.com>
[ Upstream commit 62c740f823a8e47ffe56e45a7472c27cf988e2f6 ]
Sashiko (locally) reports a logical issues in mmio_guard_ioremap_hook()
mmio_guard_ioremap_hook() attempts to handle unaligned addresses and
sizes. However, aligning the start address before adding the size, might
shift the end to the page before.
Fixes: 0f1269495800 ("drivers/virt: pkvm: Intercept ioremap using pKVM MMIO_GUARD hypercall")
Signed-off-by: Mostafa Saleh <smostafa@google.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Tested-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c b/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c
index 4230b817a80bd8..d66291def0f408 100644
--- a/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c
+++ b/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c
@@ -82,8 +82,8 @@ static int mmio_guard_ioremap_hook(phys_addr_t phys, size_t size,
if (protval != PROT_DEVICE_nGnRE && protval != PROT_DEVICE_nGnRnE)
return 0;
+ end = PAGE_ALIGN(phys + size);
phys = PAGE_ALIGN_DOWN(phys);
- end = phys + PAGE_ALIGN(size);
while (phys < end) {
const int func_id = ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_FUNC_ID;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 165/602] hwmon: (asus-ec-sensors) fix looping over banks while reading from EC
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (163 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 164/602] drivers/virt: pkvm: Fix end calculation in mmio_guard_ioremap_hook() Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 166/602] hwmon: (asus-ec-sensors) fix EC read intervals Greg Kroah-Hartman
` (440 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Eugene Shalygin, Guenter Roeck,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eugene Shalygin <eugene.shalygin@gmail.com>
[ Upstream commit e741d13cc2abfc6fccebe2008057aa52e285223e ]
Do not assume there are only bank 0 and bank 1 available, just use '!='
for bank comparison.
Fixes: d0ddfd241e57 ("hwmon: (asus-ec-sensors) add driver for ASUS EC")
Signed-off-by: Eugene Shalygin <eugene.shalygin@gmail.com>
Link: https://lore.kernel.org/r/20260711074217.554656-1-eugene.shalygin@gmail.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/hwmon/asus-ec-sensors.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c
index 483dfb806cc510..909720fbf2685f 100644
--- a/drivers/hwmon/asus-ec-sensors.c
+++ b/drivers/hwmon/asus-ec-sensors.c
@@ -776,7 +776,7 @@ static int asus_ec_block_read(const struct device *dev,
}
for (ireg = 0; ireg < ec->nr_registers; ireg++) {
reg_bank = register_bank(ec->registers[ireg]);
- if (reg_bank < bank) {
+ if (reg_bank != bank) {
continue;
}
ec_read(register_index(ec->registers[ireg]),
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 166/602] hwmon: (asus-ec-sensors) fix EC read intervals
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (164 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 165/602] hwmon: (asus-ec-sensors) fix looping over banks while reading from EC Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 167/602] hwmon: (asus-ec-sensors) add missed handle for ENOMEM Greg Kroah-Hartman
` (439 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Eugene Shalygin, Guenter Roeck,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eugene Shalygin <eugene.shalygin@gmail.com>
[ Upstream commit 60710b2af13b81da71b429d3f8b19dd70310729d ]
Take INITIAL_JIFFIES into account when setting up next update time.
Fixes: d0ddfd241e57 ("hwmon: (asus-ec-sensors) add driver for ASUS EC")
Signed-off-by: Eugene Shalygin <eugene.shalygin@gmail.com>
Link: https://lore.kernel.org/r/20260712110650.1240071-2-eugene.shalygin@gmail.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/hwmon/asus-ec-sensors.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c
index 909720fbf2685f..d08abd1adc0812 100644
--- a/drivers/hwmon/asus-ec-sensors.c
+++ b/drivers/hwmon/asus-ec-sensors.c
@@ -596,7 +596,7 @@ struct ec_sensors_data {
/* sorted list of unique register banks */
u8 banks[ASUS_EC_MAX_BANK + 1];
/* in jiffies */
- unsigned long last_updated;
+ u64 next_update;
struct lock_data lock_data;
/* number of board EC sensors */
u8 nr_sensors;
@@ -865,13 +865,12 @@ static int get_cached_value_or_update(const struct device *dev,
int sensor_index,
struct ec_sensors_data *state, s32 *value)
{
- if (time_after(jiffies, state->last_updated + HZ)) {
+ if (time_after64(get_jiffies_64(), state->next_update)) {
if (update_ec_sensors(dev, state)) {
dev_err(dev, "update_ec_sensors() failure\n");
return -EIO;
}
-
- state->last_updated = jiffies;
+ state->next_update = get_jiffies_64() + HZ;
}
*value = state->sensors[sensor_index].cached_value;
@@ -989,6 +988,7 @@ static int asus_ec_probe(struct platform_device *pdev)
if (!ec_data)
return -ENOMEM;
+ ec_data->next_update = INITIAL_JIFFIES;
dev_set_drvdata(dev, ec_data);
ec_data->board_info = pboard_info;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 167/602] hwmon: (asus-ec-sensors) add missed handle for ENOMEM
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (165 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 166/602] hwmon: (asus-ec-sensors) fix EC read intervals Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 168/602] smb: client: validate DFS referral PathConsumed Greg Kroah-Hartman
` (438 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Eugene Shalygin, Guenter Roeck,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eugene Shalygin <eugene.shalygin@gmail.com>
[ Upstream commit 9813c1f49efeadbcb17e4a41972350ac783f9cac ]
Add missing return value check in the setup function.
Fixes: d0ddfd241e57 ("hwmon: (asus-ec-sensors) add driver for ASUS EC")
Signed-off-by: Eugene Shalygin <eugene.shalygin@gmail.com>
Link: https://lore.kernel.org/r/20260712130602.1256700-2-eugene.shalygin@gmail.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/hwmon/asus-ec-sensors.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/hwmon/asus-ec-sensors.c b/drivers/hwmon/asus-ec-sensors.c
index d08abd1adc0812..ad1a2ff618a38a 100644
--- a/drivers/hwmon/asus-ec-sensors.c
+++ b/drivers/hwmon/asus-ec-sensors.c
@@ -1064,9 +1064,11 @@ static int asus_ec_probe(struct platform_device *pdev)
if (!nr_count[type])
continue;
- asus_ec_hwmon_add_chan_info(asus_ec_hwmon_chan, dev,
- nr_count[type], type,
- hwmon_attributes[type]);
+ status = asus_ec_hwmon_add_chan_info(asus_ec_hwmon_chan, dev,
+ nr_count[type], type,
+ hwmon_attributes[type]);
+ if (status)
+ return status;
*ptr_asus_ec_ci++ = asus_ec_hwmon_chan++;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 168/602] smb: client: validate DFS referral PathConsumed
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (166 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 167/602] hwmon: (asus-ec-sensors) add missed handle for ENOMEM Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 169/602] hwmon: occ: validate poll response sensor blocks Greg Kroah-Hartman
` (437 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Paulo Alcantara (Red Hat),
Yichong Chen, Steve French, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yichong Chen <chenyichong@uniontech.com>
[ Upstream commit f6f5ee2aa33b350c671721b965251c42cebb962e ]
parse_dfs_referrals() validates that the response contains the fixed
referral entry array and, on for-next, the per-referral string offsets.
However, the response also contains a PathConsumed value that is later
used for DFS path parsing.
If a malformed response provides a PathConsumed value larger than the
search name, later DFS parsing can advance beyond the end of the path.
Validate PathConsumed against the search name length before storing it in
the parsed referral.
Fixes: 4ecce920e13a ("CIFS: move DFS response parsing out of SMB1 code")
Reviewed-by: Paulo Alcantara (Red Hat) <pc@manguebit.org>
Signed-off-by: Yichong Chen <chenyichong@uniontech.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/smb/client/misc.c | 34 +++++++++++++++++++++++++---------
1 file changed, 25 insertions(+), 9 deletions(-)
diff --git a/fs/smb/client/misc.c b/fs/smb/client/misc.c
index 713b95a2361145..ce8f3fdffc3bda 100644
--- a/fs/smb/client/misc.c
+++ b/fs/smb/client/misc.c
@@ -954,6 +954,8 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size,
int i, rc = 0;
char *data_end;
struct dfs_referral_level_3 *ref;
+ unsigned int path_consumed;
+ size_t search_name_len;
if (rsp_size < sizeof(*rsp)) {
cifs_dbg(VFS | ONCE,
@@ -1001,6 +1003,7 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size,
rc = -ENOMEM;
goto parse_DFS_referrals_exit;
}
+ search_name_len = strlen(searchName);
/* collect necessary data from referrals */
for (i = 0; i < *num_of_nodes; i++) {
@@ -1009,21 +1012,34 @@ parse_dfs_referrals(struct get_dfs_referral_rsp *rsp, u32 rsp_size,
struct dfs_info3_param *node = (*target_nodes)+i;
node->flags = le32_to_cpu(rsp->DFSFlags);
+ path_consumed = le16_to_cpu(rsp->PathConsumed);
if (is_unicode) {
- __le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
- GFP_KERNEL);
- if (tmp == NULL) {
+ size_t search_name_utf16_len = search_name_len * 2 + 2;
+ __le16 *tmp;
+
+ if (path_consumed > search_name_utf16_len) {
+ rc = -EINVAL;
+ goto parse_DFS_referrals_exit;
+ }
+
+ tmp = kmalloc(search_name_utf16_len, GFP_KERNEL);
+ if (!tmp) {
rc = -ENOMEM;
goto parse_DFS_referrals_exit;
}
- cifsConvertToUTF16((__le16 *) tmp, searchName,
+ cifsConvertToUTF16((__le16 *)tmp, searchName,
PATH_MAX, nls_codepage, remap);
- node->path_consumed = cifs_utf16_bytes(tmp,
- le16_to_cpu(rsp->PathConsumed),
- nls_codepage);
+ node->path_consumed = cifs_utf16_bytes(tmp, path_consumed,
+ nls_codepage);
kfree(tmp);
- } else
- node->path_consumed = le16_to_cpu(rsp->PathConsumed);
+ } else {
+ if (path_consumed > search_name_len) {
+ rc = -EINVAL;
+ goto parse_DFS_referrals_exit;
+ }
+
+ node->path_consumed = path_consumed;
+ }
node->server_type = le16_to_cpu(ref->ServerType);
node->ref_flag = le16_to_cpu(ref->ReferralEntryFlags);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 169/602] hwmon: occ: validate poll response sensor blocks
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (167 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 168/602] smb: client: validate DFS referral PathConsumed Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 170/602] regulator: mt6358: use regmap helper to read fixed LDO calibration Greg Kroah-Hartman
` (436 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Pengpeng Hou, Guenter Roeck,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <pengpeng@iscas.ac.cn>
[ Upstream commit 70e76e700fc6c46afb4e17aec099a1ea089b4a22 ]
The OCC poll response parser walks a counted list of sensor data blocks.
It used the static backing-array capacity as the parse boundary, but a
transport response makes only data_length bytes current and valid. A
truncated response can therefore make the parser consume a block header or
block extent outside the current response.
Use data_length as the parent boundary, prove the fixed poll header and
each current block header before reading them, and prove the complete block
before advancing. Keep parsed sensor metadata local until the complete
response has passed validation, then publish it. Propagate
malformed-response errors before publishing the OCC as active.
Fixes: aa195fe49b03 ("hwmon (occ): Parse OCC poll response")
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Link: https://lore.kernel.org/r/20260720115826.14813-1-pengpeng@iscas.ac.cn
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/hwmon/occ/common.c | 38 ++++++++++++++++++++++++++++++--------
1 file changed, 30 insertions(+), 8 deletions(-)
diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c
index e18e80e832fd3f..175208d712b06e 100644
--- a/drivers/hwmon/occ/common.c
+++ b/drivers/hwmon/occ/common.c
@@ -1052,32 +1052,49 @@ static int occ_setup_sensor_attrs(struct occ *occ)
}
/* only need to do this once at startup, as OCC won't change sensors on us */
-static void occ_parse_poll_response(struct occ *occ)
+static int occ_parse_poll_response(struct occ *occ)
{
unsigned int i, old_offset, offset = 0, size = 0;
+ u16 data_length;
struct occ_sensor *sensor;
- struct occ_sensors *sensors = &occ->sensors;
+ struct occ_sensors parsed = {};
+ struct occ_sensors *sensors = &parsed;
struct occ_response *resp = &occ->resp;
struct occ_poll_response *poll =
(struct occ_poll_response *)&resp->data[0];
struct occ_poll_response_header *header = &poll->header;
struct occ_sensor_data_block *block = &poll->block;
+ data_length = get_unaligned_be16(&resp->data_length);
+ if (data_length < sizeof(*header) || data_length > OCC_RESP_DATA_BYTES) {
+ dev_err(occ->bus_dev, "invalid OCC poll response length %u\n",
+ data_length);
+ return -EMSGSIZE;
+ }
+
dev_info(occ->bus_dev, "OCC found, code level: %.16s\n",
header->occ_code_level);
for (i = 0; i < header->num_sensor_data_blocks; ++i) {
block = (struct occ_sensor_data_block *)((u8 *)block + offset);
+ if (size + sizeof(*header) + sizeof(block->header) >
+ data_length) {
+ dev_err(occ->bus_dev,
+ "truncated OCC sensor block header\n");
+ return -EMSGSIZE;
+ }
+
old_offset = offset;
offset = (block->header.num_sensors *
block->header.sensor_length) + sizeof(block->header);
- size += offset;
/* validate all the length/size fields */
- if ((size + sizeof(*header)) >= OCC_RESP_DATA_BYTES) {
- dev_warn(occ->bus_dev, "exceeded response buffer\n");
- return;
+ if (size + sizeof(*header) + offset > data_length) {
+ dev_err(occ->bus_dev,
+ "exceeded OCC poll response length\n");
+ return -EMSGSIZE;
}
+ size += offset;
dev_dbg(occ->bus_dev, " %04x..%04x: %.4s (%d sensors)\n",
old_offset, offset - 1, block->header.eye_catcher,
@@ -1107,6 +1124,9 @@ static void occ_parse_poll_response(struct occ *occ)
dev_dbg(occ->bus_dev, "Max resp size: %u+%zd=%zd\n", size,
sizeof(*header), size + sizeof(*header));
+ occ->sensors = parsed;
+
+ return 0;
}
int occ_active(struct occ *occ, bool active)
@@ -1138,10 +1158,12 @@ int occ_active(struct occ *occ, bool active)
goto unlock;
}
- occ->active = true;
occ->next_update = jiffies + OCC_UPDATE_FREQUENCY;
- occ_parse_poll_response(occ);
+ rc = occ_parse_poll_response(occ);
+ if (rc)
+ goto unlock;
+ occ->active = true;
rc = occ_setup_sensor_attrs(occ);
if (rc) {
dev_err(occ->bus_dev,
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 170/602] regulator: mt6358: use regmap helper to read fixed LDO calibration
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (168 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 169/602] hwmon: occ: validate poll response sensor blocks Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 171/602] Bluetooth: btusb: validate Realtek vendor event length Greg Kroah-Hartman
` (435 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Daniel Golle, Chen-Yu Tsai,
Mark Brown, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Golle <daniel@makrotopia.org>
[ Upstream commit 1d26f125501f3fbe6c259ab75bf6516299a0bf0e ]
The "fixed" LDOs with output voltage calibration use
mt6358_get_buck_voltage_sel as their get_voltage_sel op, but the
MT6358_REG_FIXED and MT6366_REG_FIXED entries do not populate
da_vsel_reg/da_vsel_mask. The op therefore reads register 0x0 with a
zero mask and shifts the result by ffs(0) - 1 = -1, which is undefined
behaviour and gets flagged by UBSAN on every boot on MT6366 boards:
UBSAN: shift-out-of-bounds in drivers/regulator/mt6358-regulator.c:384:38
shift exponent -1 is negative
Call trace:
mt6358_get_buck_voltage_sel+0xc8/0x120
regulator_get_voltage_rdev+0x70/0x170
set_machine_constraints+0x504/0xc38
regulator_register+0x324/0xc68
Besides the undefined shift, the returned selector is always 0, so the
actual calibration offset programmed in <reg>_ANA_CON0 is never
reported.
The descriptor already carries the correct vsel_reg/vsel_mask (the
ANA_CON0 calibration field), matching the regulator_set_voltage_sel_regmap
op already in use. Read the selector back through
regulator_get_voltage_sel_regmap instead.
Fixes: cf08fa74c716 ("regulator: mt6358: Add output voltage fine tuning to fixed regulators")
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Chen-Yu Tsai <wens@kernel.org>
Tested-by: Chen-Yu Tsai <wens@kernel.org>
Link: https://patch.msgid.link/dcd98d81dede338c9bbb9700a9613c848b702e49.1784336005.git.daniel@makrotopia.org
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/regulator/mt6358-regulator.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/regulator/mt6358-regulator.c b/drivers/regulator/mt6358-regulator.c
index e4745f616cea3b..44bef0bdfdbe35 100644
--- a/drivers/regulator/mt6358-regulator.c
+++ b/drivers/regulator/mt6358-regulator.c
@@ -492,7 +492,7 @@ static const struct regulator_ops mt6358_volt_fixed_ops = {
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
- .get_voltage_sel = mt6358_get_buck_voltage_sel,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 171/602] Bluetooth: btusb: validate Realtek vendor event length
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (169 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 170/602] regulator: mt6358: use regmap helper to read fixed LDO calibration Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 172/602] netlink: specs: rt-link: convert bridge port flag attributes to u8 Greg Kroah-Hartman
` (434 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Pengpeng Hou, Luiz Augusto von Dentz,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <pengpeng@iscas.ac.cn>
[ Upstream commit df541cd485ff80a5ddc579d99687bc7506df9851 ]
btusb_recv_event_realtek() reads the event code at data[0] and the Realtek
subevent code at data[2] before deciding whether to consume a vendor event
as a coredump.
For example, the two-byte event ff 00 contains a complete vendor-event
header declaring zero parameters. The old classifier still reads a
nonexistent third byte and can misclassify the event as a coredump if the
adjacent byte is 0x34.
Require the HCI event header and first parameter to be present before
inspecting the Realtek subevent code. Short events continue through the
normal HCI receive path, which owns their protocol validation.
Fixes: 044014ce85a1 ("Bluetooth: btrtl: Add Realtek devcoredump support")
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/bluetooth/btusb.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 903d43380d038f..aadbda2fd5a20a 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -2707,7 +2707,9 @@ static int btusb_setup_realtek(struct hci_dev *hdev)
static int btusb_recv_event_realtek(struct hci_dev *hdev, struct sk_buff *skb)
{
- if (skb->data[0] == HCI_VENDOR_PKT && skb->data[2] == RTK_SUB_EVENT_CODE_COREDUMP) {
+ if (skb->len >= HCI_EVENT_HDR_SIZE + 1 &&
+ skb->data[0] == HCI_VENDOR_PKT &&
+ skb->data[2] == RTK_SUB_EVENT_CODE_COREDUMP) {
struct rtk_dev_coredump_hdr hdr = {
.code = RTK_DEVCOREDUMP_CODE_MEMDUMP,
};
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 172/602] netlink: specs: rt-link: convert bridge port flag attributes to u8
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (170 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 171/602] Bluetooth: btusb: validate Realtek vendor event length Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 173/602] net/packet: avoid fanout hook re-registration after unregister Greg Kroah-Hartman
` (433 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Petr Machata, Nikolay Aleksandrov,
Ido Schimmel, Danielle Ratson, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Danielle Ratson <danieller@nvidia.com>
[ Upstream commit f6e3b21608e974c4aaa4cfd73a239dacf1d8a9a3 ]
A number of IFLA_BRPORT_* attributes are documented in the rt-link spec
as having the "flag" type, i.e. a payload-less NLA_FLAG attribute whose
meaning is presence-only. This does not match the kernel, which emits
these attributes with nla_put_u8() and validates them as NLA_U8 in
br_port_policy[]. The values are not mere presence flags but carry a u8
payload (0/1).
Convert these bridge port attributes from "flag" to "u8" so the spec
reflects the actual wire format.
Fixes: 077b6022d24b ("doc/netlink/specs: Add sub-message type to rt_link family")
Reviewed-by: Petr Machata <petrm@nvidia.com>
Acked-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Danielle Ratson <danieller@nvidia.com>
Link: https://patch.msgid.link/a57cdfcfc4a6dcb92106c25b4dde5059fde2bd44.1783236731.git.danieller@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
Documentation/netlink/specs/rt_link.yaml | 40 ++++++++++++------------
1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/Documentation/netlink/specs/rt_link.yaml b/Documentation/netlink/specs/rt_link.yaml
index a048fc30389d68..5fb757dcb53c2e 100644
--- a/Documentation/netlink/specs/rt_link.yaml
+++ b/Documentation/netlink/specs/rt_link.yaml
@@ -1619,31 +1619,31 @@ attribute-sets:
type: u32
-
name: mode
- type: flag
+ type: u8
-
name: guard
- type: flag
+ type: u8
-
name: protect
- type: flag
+ type: u8
-
name: fast-leave
- type: flag
+ type: u8
-
name: learning
- type: flag
+ type: u8
-
name: unicast-flood
- type: flag
+ type: u8
-
name: proxyarp
- type: flag
+ type: u8
-
name: learning-sync
- type: flag
+ type: u8
-
name: proxyarp-wifi
- type: flag
+ type: u8
-
name: root-id
type: binary
@@ -1690,34 +1690,34 @@ attribute-sets:
type: pad
-
name: mcast-flood
- type: flag
+ type: u8
-
name: mcast-to-ucast
- type: flag
+ type: u8
-
name: vlan-tunnel
- type: flag
+ type: u8
-
name: bcast-flood
- type: flag
+ type: u8
-
name: group-fwd-mask
type: u16
-
name: neigh-suppress
- type: flag
+ type: u8
-
name: isolated
- type: flag
+ type: u8
-
name: backup-port
type: u32
-
name: mrp-ring-open
- type: flag
+ type: u8
-
name: mrp-in-open
- type: flag
+ type: u8
-
name: mcast-eht-hosts-limit
type: u32
@@ -1726,10 +1726,10 @@ attribute-sets:
type: u32
-
name: locked
- type: flag
+ type: u8
-
name: mab
- type: flag
+ type: u8
-
name: mcast-n-groups
type: u32
@@ -1738,7 +1738,7 @@ attribute-sets:
type: u32
-
name: neigh-vlan-suppress
- type: flag
+ type: u8
-
name: backup-nhid
type: u32
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 173/602] net/packet: avoid fanout hook re-registration after unregister
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (171 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 172/602] netlink: specs: rt-link: convert bridge port flag attributes to u8 Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 174/602] bonding: fix devconf_all NULL dereference when IPv6 is disabled Greg Kroah-Hartman
` (432 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Lee, Willem de Bruijn,
Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Lee <david.lee@trailofbits.com>
[ Upstream commit 50aff80475abd3533eef4320477037e6fcc6b56e ]
packet_set_ring() temporarily detaches a socket from packet delivery while
reconfiguring its ring. It records the previous running state, clears
po->num, unregisters the protocol hook when needed, drops po->bind_lock,
and later restores po->num and re-registers the hook from the saved
was_running value.
That unlocked window can race with NETDEV_UNREGISTER. The notifier can
observe the socket as not running, skip __unregister_prot_hook(), and
invalidate the per-socket binding by setting po->ifindex to -1 and clearing
po->prot_hook.dev. A one-member fanout group can still retain its shared
fanout hook device pointer. When packet_set_ring() resumes, re-registering
solely from the stale was_running state can re-add the fanout hook after
the device has been unregistered.
Treat po->ifindex == -1 as an invalidated binding after reacquiring
po->bind_lock. This is distinct from ifindex 0, the normal
unbound/wildcard state: ifindex -1 marks an existing device binding that
was invalidated when the device was unregistered. Restore po->num as
before, but do not re-register the hook if device unregister already
detached the socket.
Fixes: dc99f600698d ("packet: Add fanout support.")
Link: https://lore.kernel.org/netdev/20260701113947.23180-1-david.lee@trailofbits.com/
Signed-off-by: David Lee <david.lee@trailofbits.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20260707104440.833129-1-david.lee@trailofbits.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/packet/af_packet.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 562c860cca577a..c5900752522652 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -4604,7 +4604,11 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
spin_lock(&po->bind_lock);
WRITE_ONCE(po->num, num);
- if (was_running)
+ /*
+ * NETDEV_UNREGISTER may have invalidated the binding while bind_lock
+ * was dropped above. Do not re-add a fanout hook to a dead device.
+ */
+ if (was_running && READ_ONCE(po->ifindex) != -1)
register_prot_hook(sk);
spin_unlock(&po->bind_lock);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 174/602] bonding: fix devconf_all NULL dereference when IPv6 is disabled
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (172 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 173/602] net/packet: avoid fanout hook re-registration after unregister Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 175/602] rds: drop incoming messages that cross network namespace boundaries Greg Kroah-Hartman
` (431 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Qianheng Peng, Zhaolong Zhang,
Hangbin Liu, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhaolong Zhang <zhangzl68@chinatelecom.cn>
[ Upstream commit 1c975de3343cdef506f2eecc833cc1f14b0401c4 ]
When booting with the 'ipv6.disable=1' parameter, the devconf_all is
never initialized because inet6_init() exits before addrconf_init() is
called which initializes it. bond_send_validate(), however, will still
call bond_ns_send_all() even ipv6 is indeed disabled. It will lead to
NULL derefence of net->ipv6.devconf_all in ip6_pol_route().
BUG: kernel NULL pointer dereference, address: 000000000000000c
[...]
Workqueue: bond0 bond_arp_monitor [bonding]
RIP: 0010:ip6_pol_route+0x69/0x480
[...]
Call Trace:
<TASK>
? srso_return_thunk+0x5/0x5f
? __pfx_ip6_pol_route_output+0x10/0x10
fib6_rule_lookup+0xfe/0x260
? wakeup_preempt+0x8a/0x90
? srso_return_thunk+0x5/0x5f
? srso_return_thunk+0x5/0x5f
? sched_balance_rq+0x369/0x810
ip6_route_output_flags+0xd7/0x170
bond_ns_send_all+0xde/0x280 [bonding]
bond_ab_arp_probe+0x296/0x320 [bonding]
? srso_return_thunk+0x5/0x5f
bond_activebackup_arp_mon+0xb4/0x2c0 [bonding]
process_one_work+0x196/0x370
worker_thread+0x1af/0x320
? srso_return_thunk+0x5/0x5f
? __pfx_worker_thread+0x10/0x10
kthread+0xe3/0x120
? __pfx_kthread+0x10/0x10
ret_from_fork+0x199/0x260
? __pfx_kthread+0x10/0x10
ret_from_fork_asm+0x1a/0x30
</TASK>
Fix this by adding ipv6_mod_enabled() condition check in the caller.
Fixes: 4e24be018eb9 ("bonding: add new parameter ns_targets")
Signed-off-by: Qianheng Peng <pengqh1@chinatelecom.cn>
Signed-off-by: Zhaolong Zhang <zhangzl68@chinatelecom.cn>
Reviewed-by: Hangbin Liu <liuhangbin@gmail.com>
Link: https://patch.msgid.link/20260707010622.487333-1-zhangzl2013@126.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/bonding/bond_main.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 7d71cfc2c93741..2919329a8c2006 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3512,7 +3512,8 @@ static void bond_send_validate(struct bonding *bond, struct slave *slave)
{
bond_arp_send_all(bond, slave);
#if IS_ENABLED(CONFIG_IPV6)
- bond_ns_send_all(bond, slave);
+ if (likely(ipv6_mod_enabled()))
+ bond_ns_send_all(bond, slave);
#endif
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 175/602] rds: drop incoming messages that cross network namespace boundaries
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (173 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 174/602] bonding: fix devconf_all NULL dereference when IPv6 is disabled Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 176/602] gtp: parse extension headers before reading inner protocol Greg Kroah-Hartman
` (430 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Aldo Ariel Panzardo,
Allison Henderson, Paolo Abeni, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aldo Ariel Panzardo <qwe.aldo@gmail.com>
[ Upstream commit 5521ae71e32a8069ed4ca6e792179dc57bc43ab2 ]
rds_find_bound() looks up the destination socket using a global
rhashtable keyed solely on (addr, port, scope_id). Network namespaces
are not part of the key, so a sender in netns A can deliver an incoming
message (inc) to a socket that lives in a different netns B.
When this happens, inc->i_conn points to an rds_connection whose c_net
is netns A, but the receiving rs lives in netns B. Once the child
process that created netns A exits, cleanup_net() calls
rds_loop_exit_net() -> rds_loop_kill_conns() -> rds_conn_destroy(),
freeing that connection. If the survivor socket in netns B still holds
the inc, any subsequent dereference of inc->i_conn is a use-after-free.
There are two dangerous sites in rds_clear_recv_queue():
1. inc->i_conn->c_lcong (offset 88 of freed rds_connection, size 200)
read via rds_recv_rcvbuf_delta() -- confirmed by KASAN.
2. inc->i_conn->c_trans->inc_free(inc) (function pointer at offset 80)
called via rds_inc_put() when the inc refcount reaches zero -- same
race window, potential call-through-freed-object primitive.
The bug is reachable from unprivileged user namespaces
(CLONE_NEWUSER + CLONE_NEWNET), available since Linux 3.8.
Fix this by rejecting the delivery in rds_recv_incoming() when the
socket returned by rds_find_bound() belongs to a different network
namespace than the connection that carried the message. Use the
existing rds_conn_net() / sock_net() helpers and net_eq() for the
comparison.
Fixes: c809195f5523 ("rds: clean up loopback rds_connections on netns deletion")
Signed-off-by: Aldo Ariel Panzardo <qwe.aldo@gmail.com>
Reviewed-by: Allison Henderson <achender@kernel.org>
Tested-by: Allison Henderson <achender@kernel.org>
Signed-off-by: Allison Henderson <achender@kernel.org>
Link: https://patch.msgid.link/20260708024314.601139-1-achender@kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/rds/recv.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/net/rds/recv.c b/net/rds/recv.c
index 5627f80013f8b1..bd9d00326e94fd 100644
--- a/net/rds/recv.c
+++ b/net/rds/recv.c
@@ -366,6 +366,21 @@ void rds_recv_incoming(struct rds_connection *conn, struct in6_addr *saddr,
goto out;
}
+ /*
+ * rds_find_bound() uses a global (netns-agnostic) hash table.
+ * An RDS connection created in netns A can match a socket bound
+ * in the init netns, delivering inc cross-netns with inc->i_conn
+ * pointing into netns A. When cleanup_net() then frees that conn,
+ * any subsequent dereference of inc->i_conn is a use-after-free.
+ * Drop the inc if the receiving socket lives in a different netns.
+ */
+ if (!net_eq(sock_net(rds_rs_to_sk(rs)), rds_conn_net(conn))) {
+ rds_stats_inc(s_recv_drop_no_sock);
+ rds_sock_put(rs);
+ rs = NULL;
+ goto out;
+ }
+
/* Process extension headers */
rds_recv_incoming_exthdrs(inc, rs);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 176/602] gtp: parse extension headers before reading inner protocol
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (174 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 175/602] rds: drop incoming messages that cross network namespace boundaries Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 177/602] dpaa2-switch: put MAC endpoint device on disconnect Greg Kroah-Hartman
` (429 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Zhixing Chen, Paolo Abeni,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhixing Chen <running910@gmail.com>
[ Upstream commit 96e37e2f618e931aa97af95e707dcdfb1ec41264 ]
GTPv1-U packets may carry a chain of extension headers before the inner
IP packet. The receive path already parses and skips these extension
headers, but it currently reads the inner protocol before doing so.
As a result, the first extension header byte is interpreted as the inner
IP version. Packets with extension headers are then dropped before PDP
lookup.
Parse the extension header chain before calling gtp_inner_proto(), so the
inner protocol is read from the actual inner IP header.
Fixes: c75fc0b9e5be ("gtp: identify tunnel via GTP device + GTP version + TEID + family")
Signed-off-by: Zhixing Chen <running910@gmail.com>
Link: https://patch.msgid.link/20260708042244.120898-1-running910@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/gtp.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index d7f644dfaa8d9e..dc4770e79990f0 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -821,13 +821,17 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb)
if (!pskb_may_pull(skb, hdrlen))
return -1;
+ gtp1 = (struct gtp1_header *)(skb->data + sizeof(struct udphdr));
+
+ if (gtp1->flags & GTP1_F_EXTHDR &&
+ gtp_parse_exthdrs(skb, &hdrlen) < 0)
+ return -1;
+
if (gtp_inner_proto(skb, hdrlen, &inner_proto) < 0) {
netdev_dbg(gtp->dev, "GTP packet does not encapsulate an IP packet\n");
return -1;
}
- gtp1 = (struct gtp1_header *)(skb->data + sizeof(struct udphdr));
-
pctx = gtp1_pdp_find(gtp, ntohl(gtp1->tid),
gtp_proto_to_family(inner_proto));
if (!pctx) {
@@ -835,10 +839,6 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb)
return 1;
}
- if (gtp1->flags & GTP1_F_EXTHDR &&
- gtp_parse_exthdrs(skb, &hdrlen) < 0)
- return -1;
-
return gtp_rx(pctx, skb, hdrlen, gtp->role, inner_proto);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 177/602] dpaa2-switch: put MAC endpoint device on disconnect
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (175 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 176/602] gtp: parse extension headers before reading inner protocol Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 178/602] dpaa2-eth: " Greg Kroah-Hartman
` (428 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Guangshuo Li, Simon Horman,
Paolo Abeni, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <lgs201920130244@gmail.com>
[ Upstream commit 4c1eabbef7a1707635652e956e39db1269c3af2b ]
fsl_mc_get_endpoint() returns the MAC endpoint device with a reference
taken through device_find_child(). The switch port connect path stores
that device in mac->mc_dev and keeps it for the lifetime of the connected
MAC object.
However, the disconnect path only closes the MAC and frees the dpaa2_mac
object. It does not drop the endpoint device reference stored in
mac->mc_dev, so every successful connect leaks that device reference when
the MAC is later disconnected.
Drop the endpoint device reference before freeing the dpaa2_mac object.
Fixes: 84cba72956fd ("dpaa2-switch: integrate the MAC endpoint support")
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260708111025.749311-1-lgs201920130244@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
index 4520c2788b1c56..8469ca27086994 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
@@ -1510,6 +1510,7 @@ static void dpaa2_switch_port_disconnect_mac(struct ethsw_port_priv *port_priv)
dpaa2_mac_disconnect(mac);
dpaa2_mac_close(mac);
+ put_device(&mac->mc_dev->dev);
kfree(mac);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 178/602] dpaa2-eth: put MAC endpoint device on disconnect
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (176 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 177/602] dpaa2-switch: put MAC endpoint device on disconnect Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 179/602] iommu/amd: Wait for completion instead of returning early in iommu_completion_wait() Greg Kroah-Hartman
` (427 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Guangshuo Li, Ioana Ciornei,
Paolo Abeni, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <lgs201920130244@gmail.com>
[ Upstream commit b4b201cc93ff70150853aba03e14d314d1980ca0 ]
fsl_mc_get_endpoint() returns the MAC endpoint device with a reference
taken through device_find_child(). The Ethernet connect path stores that
device in mac->mc_dev and keeps it for the lifetime of the connected MAC
object.
However, the disconnect path only disconnects and closes the MAC before
freeing the dpaa2_mac object. It does not drop the endpoint device
reference stored in mac->mc_dev, so every successful connect leaks that
device reference when the MAC is later disconnected.
Drop the endpoint device reference after closing the MAC and before
freeing the dpaa2_mac object.
Fixes: 719479230893 ("dpaa2-eth: add MAC/PHY support through phylink")
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
Reviewed-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Reviewed-by: Ioana Ciornei <ioana.ciornei@nxp.com>
Link: https://patch.msgid.link/20260708111738.750391-1-lgs201920130244@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
index f56a14e09d4a3f..047a09e9e6da2d 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
@@ -4721,6 +4721,7 @@ static void dpaa2_eth_disconnect_mac(struct dpaa2_eth_priv *priv)
dpaa2_mac_disconnect(mac);
dpaa2_mac_close(mac);
+ put_device(&mac->mc_dev->dev);
kfree(mac);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 179/602] iommu/amd: Wait for completion instead of returning early in iommu_completion_wait()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (177 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 178/602] dpaa2-eth: " Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 180/602] wifi: mac80211: tear down new links on vif update error path Greg Kroah-Hartman
` (426 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Guanghui Feng, Vasant Hegde,
Will Deacon, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guanghui Feng <guanghuifeng@linux.alibaba.com>
[ Upstream commit 1e75a8255f11c81fb07e81e5029cfd75804350a0 ]
need_sync is a per-IOMMU flag shared by all domains and devices behind
that IOMMU. It is set whenever a command is queued with sync == true and
cleared when a completion-wait (CWAIT) command is queued. However, a
cleared need_sync only means that a covering CWAIT has been queued, not
that all previously queued commands have actually completed in hardware.
iommu_completion_wait() read need_sync locklessly and returned early
when it was false. This breaks the "block until all previously queued
commands have completed" contract in a multi-CPU scenario:
CPU2: queue inv-B => need_sync = true
CPU1: queue CWAIT(N); need_sync = false; then wait_on_sem(N)
CPU2: read need_sync == false => return 0 (no wait!)
CPU2 returns without waiting for any sequence number even though its
inv-B may not have completed yet (CWAIT(N), queued after inv-B, has not
been signaled). CPU2 then proceeds to, for example, free page-table
pages while the IOMMU can still walk stale translations, opening a
use-after-free window. This is a logical race in the meaning of the
flag, not a memory-visibility issue, so barriers alone do not help.
Fix it without losing the optimization of avoiding redundant CWAIT
commands: take iommu->lock before testing need_sync, and when it is
false do not return early but wait for the last allocated sequence
number (cmd_sem_val). Since need_sync == false implies no sync command
was queued after the last CWAIT, that CWAIT is FIFO-ordered after every
not-yet-completed command, so waiting for its sequence number guarantees
all prior commands (possibly queued by another CPU) have completed. The
common path with pending work is unchanged and no extra hardware command
is issued.
Signed-off-by: Guanghui Feng <guanghuifeng@linux.alibaba.com>
Fixes: 815b33fdc279 ("x86/amd-iommu: Cleanup completion-wait handling")
Reviewed-by: Vasant Hegde <vasant.hegde@amd.com>
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/iommu/amd/iommu.c | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index b4052fa9cc76bc..3f109a99a9e401 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -1424,11 +1424,23 @@ static int iommu_completion_wait(struct amd_iommu *iommu)
int ret;
u64 data;
- if (!iommu->need_sync)
- return 0;
-
raw_spin_lock_irqsave(&iommu->lock, flags);
+ if (!iommu->need_sync) {
+ /*
+ * No command has been queued since the last completion-wait.
+ * A concurrent CPU may have already queued that CWAIT and
+ * cleared need_sync; need_sync == false only means a covering
+ * CWAIT is queued, not that all prior commands have completed.
+ * Wait for the last allocated sequence number so that any
+ * command queued before this call (possibly on another CPU)
+ * is guaranteed to have completed before returning.
+ */
+ data = iommu->cmd_sem_val;
+ raw_spin_unlock_irqrestore(&iommu->lock, flags);
+ return wait_on_sem(iommu, data);
+ }
+
data = get_cmdsem_val(iommu);
build_completion_wait(&cmd, iommu, data);
@@ -1438,9 +1450,7 @@ static int iommu_completion_wait(struct amd_iommu *iommu)
if (ret)
return ret;
- ret = wait_on_sem(iommu, data);
-
- return ret;
+ return wait_on_sem(iommu, data);
}
static void domain_flush_complete(struct protection_domain *domain)
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 180/602] wifi: mac80211: tear down new links on vif update error path
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (178 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 179/602] iommu/amd: Wait for completion instead of returning early in iommu_completion_wait() Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 181/602] nfp: Check resource mutex allocation Greg Kroah-Hartman
` (425 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Weiming Shi, Xiang Mei,
Johannes Berg, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei <xmei5@asu.edu>
[ Upstream commit 952c02b33f56207a160421bcd61e7ac53c9c59ae ]
When ieee80211_vif_update_links() adds new links it allocates a link
container for each and calls ieee80211_link_init() (which registers the
per-link debugfs files with file->private_data pointing into the container)
and ieee80211_link_setup(). If the subsequent drv_change_vif_links() fails,
the error path restores the old pointers and jumps to 'free', which frees
the new containers but never removes their debugfs entries or stops the
links. The debugfs files survive with file->private_data dangling at the
freed container, so a later open()+read() (e.g. link-1/txpower)
dereferences freed memory in ieee80211_if_read_link(), a use-after-free.
The removal path already dismantles links correctly via
ieee80211_tear_down_links(), which removes each link's keys and debugfs
entries and calls ieee80211_link_stop(); the add path on the error branch
does not. Commit be1ba9ed221f ("wifi: mac80211: avoid weird state in error
path") hardened this same error path for the link-removal case
(new_links == 0) but left the newly-added links' teardown unaddressed.
drv_change_vif_links() can fail at runtime on MLO drivers (internal
allocation / queue / firmware command failures).
Remove the new links' debugfs entries and stop them before freeing.
BUG: KASAN: slab-use-after-free in ieee80211_if_read_link (net/mac80211/debugfs_netdev.c:127)
Read of size 8 at addr ffff888011290000 by task exploit/145
Call Trace:
...
ieee80211_if_read_link (net/mac80211/debugfs_netdev.c:127)
short_proxy_read (fs/debugfs/file.c:373)
vfs_read (fs/read_write.c:572)
ksys_read (fs/read_write.c:716)
do_syscall_64 (arch/x86/entry/syscall_64.c:94)
entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
...
Oops: general protection fault, probably for non-canonical address 0xdffffc000000000a
RIP: 0010:ieee80211_if_read_link (net/mac80211/debugfs_netdev.c:127)
Kernel panic - not syncing: Fatal exception
Fixes: 170cd6a66d9a ("wifi: mac80211: add netdev per-link debugfs data and driver hook")
Reported-by: Weiming Shi <bestswngs@gmail.com>
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Xiang Mei <xmei5@asu.edu>
Link: https://patch.msgid.link/20260711210302.2098404-1-xmei5@asu.edu
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/mac80211/link.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/net/mac80211/link.c b/net/mac80211/link.c
index df303496914ca6..29813394bbff1c 100644
--- a/net/mac80211/link.c
+++ b/net/mac80211/link.c
@@ -379,6 +379,10 @@ static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata,
memcpy(sdata->link, old_data, sizeof(old_data));
memcpy(sdata->vif.link_conf, old, sizeof(old));
ieee80211_set_vif_links_bitmaps(sdata, old_links, dormant_links);
+ for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) {
+ ieee80211_link_debugfs_remove(&links[link_id]->data);
+ ieee80211_link_stop(&links[link_id]->data);
+ }
/* and free (only) the newly allocated links */
memset(to_free, 0, sizeof(links));
goto free;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 181/602] nfp: Check resource mutex allocation
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (179 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 180/602] wifi: mac80211: tear down new links on vif update error path Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 182/602] wan: wanxl: Only reset hardware after BAR mapping Greg Kroah-Hartman
` (424 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Ruoyu Wang, Simon Horman,
Paolo Abeni, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <ruoyuw560@gmail.com>
[ Upstream commit a61b4db34a753bdf5c9e77a7f3d3dddd41dcfacc ]
nfp_cpp_resource_find() allocates a CPP mutex handle for the matching
resource-table entry and then reports success. nfp_resource_try_acquire()
immediately passes that handle to nfp_cpp_mutex_trylock().
However, nfp_cpp_mutex_alloc() returns NULL on failure. If that happens
for a matching table entry, the resource lookup still returns success and
the following trylock dereferences a NULL mutex pointer while opening the
resource.
nfp_resource_acquire() already treats failure to allocate the table mutex
as -ENOMEM. Do the same for the resource mutex and fail the lookup before
publishing the rest of the resource handle.
This issue was found by a static analysis checker and confirmed by
manual source review.
Fixes: f01a2161577d ("nfp: add support for resources")
Signed-off-by: Ruoyu Wang <ruoyuw560@gmail.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260708143408.3168425-1-ruoyuw560@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c
index 279ea0b5695577..55525f45e447b7 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c
@@ -96,6 +96,9 @@ static int nfp_cpp_resource_find(struct nfp_cpp *cpp, struct nfp_resource *res)
res->mutex =
nfp_cpp_mutex_alloc(cpp,
NFP_RESOURCE_TBL_TARGET, addr, key);
+ if (!res->mutex)
+ return -ENOMEM;
+
res->cpp_id = NFP_CPP_ID(entry.region.cpp_target,
entry.region.cpp_action,
entry.region.cpp_token);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 182/602] wan: wanxl: Only reset hardware after BAR mapping
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (180 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 181/602] nfp: Check resource mutex allocation Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 183/602] wifi: mwifiex: bound uAP association event IEs to the event buffer Greg Kroah-Hartman
` (423 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Ruoyu Wang, Paolo Abeni, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <ruoyuw560@gmail.com>
[ Upstream commit 91957b89da995607cb654b1f9a3c126ddbaee10f ]
wanxl_pci_init_one() stores the freshly allocated card in driver data
before the PLX BAR is mapped. Several early probe failures then unwind
through wanxl_pci_remove_one(), including failure to allocate the coherent
status area or to restore the DMA mask.
wanxl_pci_remove_one() unconditionally calls wanxl_reset(), and
wanxl_reset() dereferences card->plx. On those early failures card->plx
is still NULL, so the error path can dereference a NULL MMIO pointer.
Only issue the hardware reset once the BAR mapping exists. The remaining
cleanup in wanxl_pci_remove_one() already checks whether later resources
were allocated.
This issue was found by a static analysis checker and confirmed by
manual source review.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Ruoyu Wang <ruoyuw560@gmail.com>
Link: https://patch.msgid.link/20260708143415.3169358-1-ruoyuw560@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wan/wanxl.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
index 5a9e262188efe1..c38dd741401e13 100644
--- a/drivers/net/wan/wanxl.c
+++ b/drivers/net/wan/wanxl.c
@@ -514,7 +514,8 @@ static void wanxl_pci_remove_one(struct pci_dev *pdev)
if (card->irq)
free_irq(card->irq, card);
- wanxl_reset(card);
+ if (card->plx)
+ wanxl_reset(card);
for (i = 0; i < RX_QUEUE_LENGTH; i++)
if (card->rx_skbs[i]) {
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 183/602] wifi: mwifiex: bound uAP association event IEs to the event buffer
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (181 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 182/602] wan: wanxl: Only reset hardware after BAR mapping Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 184/602] iommu/amd: Bound the early ACPI HID map Greg Kroah-Hartman
` (422 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, HE WEI , Francesco Dolcini,
Johannes Berg, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: HE WEI (ギカク) <skyexpoc@gmail.com>
[ Upstream commit f0858bfc7d3cab411a447b88e3ef970e575032c9 ]
mwifiex_process_uap_event() handles EVENT_UAP_STA_ASSOC by exposing the
(re)association request IEs that the firmware copies into the event:
sinfo->assoc_req_ies = &event->data[len];
len = (u8 *)sinfo->assoc_req_ies - (u8 *)&event->frame_control;
sinfo->assoc_req_ies_len = le16_to_cpu(event->len) - (u16)len;
event->len is supplied by the device firmware and is never validated,
and the subtraction is unchecked. assoc_req_ies points into
adapter->event_body[MAX_EVENT_SIZE], a fixed-size array embedded in the
kmalloc()'d struct mwifiex_adapter.
On the ap_11n_enabled path mwifiex_set_sta_ht_cap() walks these IEs with
cfg80211_find_ie(), whose for_each_element() loop dereferences each
element header. A firmware-reported event->len larger than the bytes
actually received makes assoc_req_ies_len describe IEs that extend past
event_body, so the walk reads out of the adapter slab object, a
slab-out-of-bounds read (KASAN: slab-out-of-bounds in cfg80211_find_ie).
An event->len smaller than the header instead makes the int subtraction
negative, which wraps to a huge size_t when stored in assoc_req_ies_len.
The same length is handed to cfg80211_new_sta(), so a more modest
over-claim can also copy stale event_body bytes into the
NL80211_CMD_NEW_STATION notification.
A malicious or malfunctioning mwifiex device (USB/SDIO/PCIe) can deliver
such an event while the interface is in AP/uAP mode.
Validate event->len before use: reject a length that underflows the
header or that would place the IEs outside the event_body[] buffer the
event was copied into. event->len here is struct mwifiex_assoc_event.len,
a payload field internal to this event, not the transport frame length,
so it is validated in this handler rather than at the generic
MWIFIEX_TYPE_EVENT receive path, which only sees the event cause and the
transport frame length. The bound is against event_body[MAX_EVENT_SIZE]
rather than the actually-received length because the transports store the
event differently (USB and SDIO leave the 4-byte event header in
event_skb, PCIe strips it via skb_pull), whereas event_body is the single
fixed buffer all of them copy the event into. This is the event-path
analogue of the receive-path bounds checks added in commit 119585281617
("wifi: mwifiex: Fix OOB and integer underflow when rx packets").
Fixes: e568634ae7ac ("mwifiex: add AP event handling framework")
Signed-off-by: HE WEI (ギカク) <skyexpoc@gmail.com>
Reviewed-by: Francesco Dolcini <francesco.dolcini@toradex.com>
Link: https://patch.msgid.link/20260715135711.34688-1-skyexpoc@gmail.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
.../net/wireless/marvell/mwifiex/uap_event.c | 24 +++++++++++++++++--
1 file changed, 22 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/marvell/mwifiex/uap_event.c b/drivers/net/wireless/marvell/mwifiex/uap_event.c
index 58ef5020a46a73..c7383abf064f50 100644
--- a/drivers/net/wireless/marvell/mwifiex/uap_event.c
+++ b/drivers/net/wireless/marvell/mwifiex/uap_event.c
@@ -123,11 +123,31 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
len = ETH_ALEN;
if (len != -1) {
+ u16 evt_len = le16_to_cpu(event->len);
+
sinfo->assoc_req_ies = &event->data[len];
len = (u8 *)sinfo->assoc_req_ies -
(u8 *)&event->frame_control;
- sinfo->assoc_req_ies_len =
- le16_to_cpu(event->len) - (u16)len;
+
+ /*
+ * event->len is reported by the device firmware
+ * and is not otherwise validated. Reject a
+ * length that underflows the header, or that
+ * would place the association request IEs
+ * outside the fixed-size event_body[] buffer the
+ * event was copied into; otherwise the IE walk
+ * in mwifiex_set_sta_ht_cap() reads past
+ * event_body and out of the adapter slab object.
+ */
+ if (evt_len < len ||
+ (u8 *)&event->frame_control + evt_len >
+ adapter->event_body + MAX_EVENT_SIZE) {
+ mwifiex_dbg(adapter, ERROR,
+ "invalid STA assoc event length\n");
+ kfree(sinfo);
+ return -1;
+ }
+ sinfo->assoc_req_ies_len = evt_len - (u16)len;
}
}
cfg80211_new_sta(priv->netdev, event->sta_addr, sinfo,
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 184/602] iommu/amd: Bound the early ACPI HID map
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (182 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 183/602] wifi: mwifiex: bound uAP association event IEs to the event buffer Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 185/602] iommu/intel: Fix out-of-bounds memset in dmar_latency_disable() Greg Kroah-Hartman
` (421 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Pengpeng Hou, Ankit Soni,
Will Deacon, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <pengpeng@iscas.ac.cn>
[ Upstream commit fb80117fddb5b477218dc99bb53911b72c3847f8 ]
The ivrs_acpihid command-line parser appends entries to a fixed
four-element early_acpihid_map array. Unlike the sibling IOAPIC and HPET
parsers, it does not reject a fifth entry before incrementing the map size.
Check the capacity at the common found label before parsing the HID and
UID or writing the entry.
Fixes: ca3bf5d47cec ("iommu/amd: Introduces ivrs_acpihid kernel parameter")
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Reviewed-by: Ankit Soni <Ankit.Soni@amd.com>
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/iommu/amd/init.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 7fa340281b9fb2..36a814b6c4de56 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -3696,6 +3696,12 @@ static int __init parse_ivrs_acpihid(char *str)
return 1;
found:
+ if (early_acpihid_map_size == EARLY_MAP_SIZE) {
+ pr_err("Early ACPI HID map overflow - ignoring ivrs_acpihid%s\n",
+ str);
+ return 1;
+ }
+
p = acpiid;
hid = strsep(&p, ":");
uid = p;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 185/602] iommu/intel: Fix out-of-bounds memset in dmar_latency_disable()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (183 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 184/602] iommu/amd: Bound the early ACPI HID map Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 186/602] wifi: mac80211: recalculate TIM when a station enters power save Greg Kroah-Hartman
` (420 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Li RongQing, Will Deacon,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li RongQing <lirongqing@baidu.com>
[ Upstream commit 754f8efe45f87e3a9c6871b645b2f9d46d1b407b ]
dmar_latency_disable() intends to zero out only the single
latency_statistic entry for the given type, but the memset size was
computed as sizeof(*lstat) * DMAR_LATENCY_NUM, which clears the entire
array starting from &lstat[type].
When type > 0, this writes beyond the end of the allocated array,
corrupting adjacent memory.
Fix by using sizeof(*lstat) to clear only the target entry.
Fixes: 55ee5e67a59a ("iommu/vt-d: Add common code for dmar latency performance monitors")
Signed-off-by: Li RongQing <lirongqing@baidu.com>
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/iommu/intel/perf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/iommu/intel/perf.c b/drivers/iommu/intel/perf.c
index dceeadc3ee7cdd..6afb55073e9f10 100644
--- a/drivers/iommu/intel/perf.c
+++ b/drivers/iommu/intel/perf.c
@@ -63,7 +63,7 @@ void dmar_latency_disable(struct intel_iommu *iommu, enum latency_type type)
return;
spin_lock_irqsave(&latency_lock, flags);
- memset(&lstat[type], 0, sizeof(*lstat) * DMAR_LATENCY_NUM);
+ memset(&lstat[type], 0, sizeof(*lstat));
spin_unlock_irqrestore(&latency_lock, flags);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 186/602] wifi: mac80211: recalculate TIM when a station enters power save
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (184 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 185/602] iommu/intel: Fix out-of-bounds memset in dmar_latency_disable() Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 187/602] pds_core: reject component parameter in legacy firmware update Greg Kroah-Hartman
` (419 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Andrew Pope, Johannes Berg,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrew Pope <andrew.pope@morsemicro.com>
[ Upstream commit a007a384c9eb17610f53a53e2f59944c31f1565a ]
When an AP buffers frames for a station on its per-station TXQs and the
station subsequently enters power save, sta_ps_start() records the
buffered TIDs in txq_buffered_tids but does not update the TIM. The
station's TIM bit is only ever set when a further frame is buffered
while the station is already asleep
(ieee80211_tx_h_unicast_ps_buf() -> sta_info_recalc_tim()).
If no further downlink frame arrives for that station the beacon
TIM never advertises the buffered traffic. A station relying on the
TIM then remains in doze indefinitely on top of a non-empty queue. Its
TXQs were removed from the scheduler's active list at PS entry, nothing
pages it, and the flow deadlocks until an unrelated event wakes the
station.
Recalculate the TIM at the end of sta_ps_start(), so traffic
already buffered at PS entry is advertised immediately.
sta_info_recalc_tim() already consults txq_buffered_tids, which is
updated above, and is safe in this context (it is already called
from equivalent paths such as the tx handlers and
ieee80211_handle_filtered_frame()).
Fixes: ba8c3d6f16a1 ("mac80211: add an intermediate software queue implementation")
Signed-off-by: Andrew Pope <andrew.pope@morsemicro.com>
Link: https://patch.msgid.link/20260717011751.79524-1-andrew.pope@morsemicro.com
[add wifi: subject prefix]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/mac80211/rx.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 59070283839277..7e3bcd709c579b 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1595,6 +1595,8 @@ static void sta_ps_start(struct sta_info *sta)
else
clear_bit(tid, &sta->txq_buffered_tids);
}
+
+ sta_info_recalc_tim(sta);
}
static void sta_ps_end(struct sta_info *sta)
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 187/602] pds_core: reject component parameter in legacy firmware update
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (185 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 186/602] wifi: mac80211: recalculate TIM when a station enters power save Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 188/602] amd-xgbe: fix MAC_AUTO_SW handling in CL37 AN Greg Kroah-Hartman
` (418 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Nikhil P. Rao, Simon Horman,
Paolo Abeni, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikhil P. Rao <nikhil.rao@amd.com>
[ Upstream commit 7be2552e601c247a328a5aba6fc06ac844b94a16 ]
The legacy firmware update path does not support per-component updates.
If a user specifies a component parameter with devlink flash, reject
the request with -EOPNOTSUPP rather than silently ignoring the component
parameter and flashing the entire firmware image.
Fixes: 49ce92fbee0b ("pds_core: add FW update feature to devlink")
Signed-off-by: Nikhil P. Rao <nikhil.rao@amd.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260708163649.128620-1-nikhil.rao@amd.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/amd/pds_core/devlink.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/ethernet/amd/pds_core/devlink.c b/drivers/net/ethernet/amd/pds_core/devlink.c
index 621791a3c543be..e35572f099c884 100644
--- a/drivers/net/ethernet/amd/pds_core/devlink.c
+++ b/drivers/net/ethernet/amd/pds_core/devlink.c
@@ -89,6 +89,12 @@ int pdsc_dl_flash_update(struct devlink *dl,
{
struct pdsc *pdsc = devlink_priv(dl);
+ if (params->component) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Component update not supported by this device");
+ return -EOPNOTSUPP;
+ }
+
return pdsc_firmware_update(pdsc, params->fw, extack);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 188/602] amd-xgbe: fix MAC_AUTO_SW handling in CL37 AN
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (186 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 187/602] pds_core: reject component parameter in legacy firmware update Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 189/602] net: txgbe: fix FDIR filter leak on remove Greg Kroah-Hartman
` (417 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Patrick Oppenlander,
Prashanth Kumar KR, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Prashanth Kumar KR <PrashanthKumar.K.R@amd.com>
[ Upstream commit 4bf22afe53a1de4b44b04cf677fd5199089cbdff ]
MAC_AUTO_SW (VR_MII_DIG_CTRL1 bit 9) enables automatic XPCS speed
mode switching after CL37 auto-negotiation and is only meaningful in
SGMII MAC mode. The original code unconditionally set this bit on
every call to xgbe_an37_set(), including when called from
xgbe_an37_disable() with enable=false. This left MAC_AUTO_SW=1 after
AN was disabled, causing the XPCS to autonomously switch speed from
stale AN state during subsequent mode changes, breaking SGMII speed
negotiation on 1G copper SFP modules.
Patrick: This was breaking negotiation for all 1G SFP modules,
not just copper modules.
Fixes: 42fd432fe6d3 ("amd-xgbe: align CL37 AN sequence as per databook")
Reported-by: Patrick Oppenlander <patrick.oppenlander@gmail.com>
Link: https://lore.kernel.org/netdev/CAEg67GmFS0Q4oSZkz8zWdOzckSth9_vBPiOy6a7-d697C2w2Xg@mail.gmail.com
Signed-off-by: Prashanth Kumar KR <PrashanthKumar.K.R@amd.com>
Tested-by: Patrick Oppenlander <patrick.oppenlander@gmail.com>
Link: https://patch.msgid.link/20260709095006.3683940-1-prashanthkumar.k.r@amd.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
index 75e9cb3fc7aa66..804945ea602790 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
@@ -376,9 +376,14 @@ static void xgbe_an37_set(struct xgbe_prv_data *pdata, bool enable,
XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_CTRL1, reg);
- reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL);
- reg |= XGBE_VEND2_MAC_AUTO_SW;
- XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL, reg);
+ if (pdata->an_mode == XGBE_AN_MODE_CL37_SGMII) {
+ reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL);
+ if (enable)
+ reg |= XGBE_VEND2_MAC_AUTO_SW;
+ else
+ reg &= ~XGBE_VEND2_MAC_AUTO_SW;
+ XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL, reg);
+ }
}
static void xgbe_an37_restart(struct xgbe_prv_data *pdata)
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 189/602] net: txgbe: fix FDIR filter leak on remove
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (187 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 188/602] amd-xgbe: fix MAC_AUTO_SW handling in CL37 AN Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 190/602] sctp: fix auth_chunk_list capacity check in sctp_auth_ep_add_chunkid Greg Kroah-Hartman
` (416 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Chenguang Zhao, Jacob Keller,
Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chenguang Zhao <zhaochenguang@kylinos.cn>
[ Upstream commit ecaa37826340520664a4e5522f803ff48fc3f564 ]
Perfect FDIR filters can be added while the interface is down and are
kept on the software list for later restore. unregister_netdev() only
calls ndo_stop when the device is up, so txgbe_fdir_filter_exit() in
txgbe_close() is skipped in that case and the filters are leaked on
driver remove. Free the filter list from txgbe_remove() as well.
Fixes: 4bdb441105dc ("net: txgbe: support Flow Director perfect filters")
Signed-off-by: Chenguang Zhao <zhaochenguang@kylinos.cn>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Link: https://patch.msgid.link/20260713091911.1614795-1-chenguang.zhao@linux.dev
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/wangxun/txgbe/txgbe_main.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
index 32fc1bec2728ff..113b2dfa2e4b03 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
@@ -744,6 +744,7 @@ static void txgbe_remove(struct pci_dev *pdev)
netdev = wx->netdev;
unregister_netdev(netdev);
+ txgbe_fdir_filter_exit(wx);
txgbe_remove_phy(txgbe);
wx_free_isb_resources(wx);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 190/602] sctp: fix auth_chunk_list capacity check in sctp_auth_ep_add_chunkid
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (188 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 189/602] net: txgbe: fix FDIR filter leak on remove Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 191/602] pds_core: fix deadlock between reset thread and remove Greg Kroah-Hartman
` (415 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, HanQuan, Xin Long, Jakub Kicinski,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: HanQuan <eilaimemedsnaimel@gmail.com>
[ Upstream commit ff04b26794a16a8a879eb4fd2c02c2d6b03850e9 ]
sctp_auth_ep_add_chunkid() uses SCTP_NUM_CHUNK_TYPES (20) as the
capacity limit for ep->auth_chunk_list, allowing it to hold up to
20 chunk entries (param_hdr.length up to 24). However, the copy
destination asoc->c.auth_chunks in struct sctp_cookie is only
SCTP_AUTH_MAX_CHUNKS (16) entries (20 bytes). When more than 16
chunks are added, sctp_association_init() memcpy overflows the
destination by up to 4 bytes.
Fix by using SCTP_AUTH_MAX_CHUNKS as the capacity limit, matching
the destination capacity.
Fixes: 1f485649f529 ("[SCTP]: Implement SCTP-AUTH internals")
Signed-off-by: HanQuan <eilaimemedsnaimel@gmail.com>
Acked-by: Xin Long <lucien.xin@gmail.com>
Link: https://patch.msgid.link/20260713032021.3491702-1-zhoujian.zja@antgroup.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/sctp/auth.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/sctp/auth.c b/net/sctp/auth.c
index c58fffc86a0c2d..8320764b16b928 100644
--- a/net/sctp/auth.c
+++ b/net/sctp/auth.c
@@ -766,7 +766,7 @@ int sctp_auth_ep_add_chunkid(struct sctp_endpoint *ep, __u8 chunk_id)
/* Check if we can add this chunk to the array */
param_len = ntohs(p->param_hdr.length);
nchunks = param_len - sizeof(struct sctp_paramhdr);
- if (nchunks == SCTP_NUM_CHUNK_TYPES)
+ if (nchunks == SCTP_AUTH_MAX_CHUNKS)
return -EINVAL;
p->chunks[nchunks] = chunk_id;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 191/602] pds_core: fix deadlock between reset thread and remove
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (189 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 190/602] sctp: fix auth_chunk_list capacity check in sctp_auth_ep_add_chunkid Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 192/602] pds_core: fix use-after-free on workqueue during remove Greg Kroah-Hartman
` (414 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, sashiko-bot, Nikhil P. Rao,
Harshitha Ramamurthy, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikhil P. Rao <nikhil.rao@amd.com>
[ Upstream commit ab0eec0ff0a421737a37f510ceab5c6ea59cd05a ]
pci_reset_function() acquires device_lock before performing the reset.
pdsc_remove() is called by the PCI core with device_lock already held.
If pdsc_pci_reset_thread() is running when pdsc_remove() is called,
destroy_workqueue() will block waiting for the work to complete, while
the work is blocked waiting for device_lock - deadlock.
Use pci_try_reset_function() which uses pci_dev_trylock() internally.
This acquires both the device lock and the PCI config access lock
without blocking - if either lock is contended, it returns -EAGAIN
immediately. This avoids the deadlock while also ensuring proper
config space access serialization during the reset.
The pci_dev_get/put calls are also removed as they were unnecessary -
the driver-owned workqueue is destroyed in pdsc_remove(), guaranteeing
the work completes before remove returns. The PCI core holds its
reference to pci_dev throughout the entire unbind sequence.
Fixes: 81665adf25d2 ("pds_core: Fix pdsc_check_pci_health function to use work thread")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Closes: https://patchwork.kernel.org/comment/27002369/
Signed-off-by: Nikhil P. Rao <nikhil.rao@amd.com>
Reviewed-by: Harshitha Ramamurthy <hramamurthy@google.com>
Link: https://patch.msgid.link/20260714180223.1642792-2-nikhil.rao@amd.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/amd/pds_core/core.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c
index 3c60d4cf9d0e17..c99cbb038f5d98 100644
--- a/drivers/net/ethernet/amd/pds_core/core.c
+++ b/drivers/net/ethernet/amd/pds_core/core.c
@@ -597,9 +597,10 @@ void pdsc_pci_reset_thread(struct work_struct *work)
struct pdsc *pdsc = container_of(work, struct pdsc, pci_reset_work);
struct pci_dev *pdev = pdsc->pdev;
- pci_dev_get(pdev);
- pci_reset_function(pdev);
- pci_dev_put(pdev);
+ /* Use try variant to avoid deadlock with pdsc_remove().
+ * If lock is contended, the watchdog timer will retry.
+ */
+ pci_try_reset_function(pdev);
}
static void pdsc_check_pci_health(struct pdsc *pdsc)
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 192/602] pds_core: fix use-after-free on workqueue during remove
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (190 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 191/602] pds_core: fix deadlock between reset thread and remove Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 193/602] pds_core: yield the CPU while waiting for the adminq to drain Greg Kroah-Hartman
` (413 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, sashiko-bot, Nikhil P. Rao,
Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikhil P. Rao <nikhil.rao@amd.com>
[ Upstream commit 0ad134881508c36b65c1a8864f8bec53adbd3327 ]
In pdsc_remove(), the workqueue is destroyed before pdsc_teardown()
is called. This ordering allows two paths to queue work on the
destroyed workqueue:
1. If pdsc_teardown() -> pdsc_devcmd_reset() times out, the error
path in pdsc_devcmd_locked() queues health_work.
2. A NotifyQ event can trigger the ISR and queue work before free_irq()
is called in pdsc_teardown().
Fix by moving destroy_workqueue() after pdsc_teardown() so the
workqueue outlives every queuer; destroy_workqueue() then flushes any
work still pending.
Draining the queued work also requires ordering the teardown so the
resources that work touches are freed last:
- In pdsc_qcq_free(), after freeing the interrupt, cancel_work_sync()
the queue's work and only then clear qcq->intx, so
pdsc_process_adminq()'s read of qcq->intx for interrupt-credit
return cannot race with the clear.
- Free adminqcq before notifyqcq: the shared adminq ISR is released
when adminqcq is freed, and the adminq work accesses notifyqcq, so
both must be stopped before notifyqcq is freed.
Fixes: 01ba61b55b20 ("pds_core: Add adminq processing and commands")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Closes: https://patchwork.kernel.org/comment/27002369/
Signed-off-by: Nikhil P. Rao <nikhil.rao@amd.com>
Link: https://patch.msgid.link/20260714180223.1642792-3-nikhil.rao@amd.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/amd/pds_core/core.c | 14 ++++++++++----
drivers/net/ethernet/amd/pds_core/main.c | 5 +++--
2 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c
index c99cbb038f5d98..985ef535e41583 100644
--- a/drivers/net/ethernet/amd/pds_core/core.c
+++ b/drivers/net/ethernet/amd/pds_core/core.c
@@ -110,7 +110,6 @@ static void pdsc_qcq_intr_free(struct pdsc *pdsc, struct pdsc_qcq *qcq)
return;
pdsc_intr_free(pdsc, qcq->intx);
- qcq->intx = PDS_CORE_INTR_INDEX_NOT_ASSIGNED;
}
static int pdsc_qcq_intr_alloc(struct pdsc *pdsc, struct pdsc_qcq *qcq)
@@ -145,6 +144,12 @@ void pdsc_qcq_free(struct pdsc *pdsc, struct pdsc_qcq *qcq)
pdsc_qcq_intr_free(pdsc, qcq);
+ /* Drain any work queued by ISR before it was freed above */
+ if (qcq->work.func)
+ cancel_work_sync(&qcq->work);
+
+ qcq->intx = PDS_CORE_INTR_INDEX_NOT_ASSIGNED;
+
if (qcq->q_base)
dma_free_coherent(dev, qcq->q_size,
qcq->q_base, qcq->q_base_pa);
@@ -304,8 +309,11 @@ int pdsc_qcq_alloc(struct pdsc *pdsc, unsigned int type, unsigned int index,
static void pdsc_core_uninit(struct pdsc *pdsc)
{
- pdsc_qcq_free(pdsc, &pdsc->notifyqcq);
+ /* Free adminqcq first: its work accesses notifyqcq, so we must
+ * disable its IRQ and drain its work before freeing notifyqcq.
+ */
pdsc_qcq_free(pdsc, &pdsc->adminqcq);
+ pdsc_qcq_free(pdsc, &pdsc->notifyqcq);
if (pdsc->kern_dbpage) {
iounmap(pdsc->kern_dbpage);
@@ -472,8 +480,6 @@ void pdsc_teardown(struct pdsc *pdsc, bool removing)
{
if (!pdsc->pdev->is_virtfn)
pdsc_devcmd_reset(pdsc);
- if (pdsc->adminqcq.work.func)
- cancel_work_sync(&pdsc->adminqcq.work);
pdsc_core_uninit(pdsc);
diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c
index a3a68889137b63..8a4ca474813888 100644
--- a/drivers/net/ethernet/amd/pds_core/main.c
+++ b/drivers/net/ethernet/amd/pds_core/main.c
@@ -429,8 +429,6 @@ static void pdsc_remove(struct pci_dev *pdev)
pdsc_sriov_configure(pdev, 0);
timer_shutdown_sync(&pdsc->wdtimer);
- if (pdsc->wq)
- destroy_workqueue(pdsc->wq);
mutex_lock(&pdsc->config_lock);
set_bit(PDSC_S_STOPPING_DRIVER, &pdsc->state);
@@ -438,6 +436,9 @@ static void pdsc_remove(struct pci_dev *pdev)
pdsc_stop(pdsc);
pdsc_teardown(pdsc, PDSC_TEARDOWN_REMOVING);
mutex_unlock(&pdsc->config_lock);
+
+ if (pdsc->wq)
+ destroy_workqueue(pdsc->wq);
mutex_destroy(&pdsc->config_lock);
mutex_destroy(&pdsc->devcmd_lock);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 193/602] pds_core: yield the CPU while waiting for the adminq to drain
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (191 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 192/602] pds_core: fix use-after-free on workqueue during remove Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 194/602] pds_core: order completion reads after the ownership check Greg Kroah-Hartman
` (412 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, sashiko-bot, Nikhil P. Rao,
Eric Joyner, Pavan Chebbi, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikhil P. Rao <nikhil.rao@amd.com>
[ Upstream commit a11f0b8a204296fe7db9eaec53441012222cb004 ]
pdsc_adminq_wait_and_dec_once_unused() busy-waits for adminq_refcnt to
drop to one:
while (!refcount_dec_if_one(&pdsc->adminq_refcnt))
cpu_relax();
The refcount is held by pdsc_adminq_post() for the duration of an
in-flight command, which can wait up to devcmd_timeout seconds
(PDS_CORE_DEVCMD_TIMEOUT is 5) for the hardware to complete. cpu_relax()
is not a reschedule point, so on a non-preemptible kernel this loop can
spin on the CPU for several seconds, starving other tasks on that core.
Add cond_resched() to the loop so the waiter yields to other runnable
tasks while it polls, keeping cpu_relax() as the busy-wait hint between
checks.
Fixes: 7e82a8745b95 ("pds_core: Prevent race issues involving the adminq")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260629200358.2626129-1-nikhil.rao%40amd.com?part=2
Signed-off-by: Nikhil P. Rao <nikhil.rao@amd.com>
Reviewed-by: Eric Joyner <eric.joyner@amd.com>
Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
Link: https://patch.msgid.link/20260714201456.1776153-1-nikhil.rao@amd.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/amd/pds_core/core.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/amd/pds_core/core.c b/drivers/net/ethernet/amd/pds_core/core.c
index 985ef535e41583..276e61f043c5ec 100644
--- a/drivers/net/ethernet/amd/pds_core/core.c
+++ b/drivers/net/ethernet/amd/pds_core/core.c
@@ -530,6 +530,7 @@ static void pdsc_adminq_wait_and_dec_once_unused(struct pdsc *pdsc)
dev_dbg_ratelimited(pdsc->dev, "%s: adminq in use\n",
__func__);
cpu_relax();
+ cond_resched();
}
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 194/602] pds_core: order completion reads after the ownership check
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (192 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 193/602] pds_core: yield the CPU while waiting for the adminq to drain Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 195/602] pds_core: fix auxiliary device add/del races Greg Kroah-Hartman
` (411 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, sashiko-bot, Nikhil P. Rao,
Eric Joyner, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikhil P. Rao <nikhil.rao@amd.com>
[ Upstream commit dd6b1cc748cd28147c113f9daa76393916ad9494 ]
pdsc_process_adminq() and pdsc_process_notifyq() decide a completion is
valid from its ownership field - the color bit for the adminq, the event
id for the notifyq - then read the rest of the descriptor, with no
barrier in between.
On a weakly ordered architecture the CPU may read the payload first. Add
dma_rmb() between the ownership read and the payload reads.
Fixes: 7e82a8745b95 ("pds_core: Prevent race issues involving the adminq")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260629200358.2626129-1-nikhil.rao%40amd.com?part=2
Signed-off-by: Nikhil P. Rao <nikhil.rao@amd.com>
Reviewed-by: Eric Joyner <eric.joyner@amd.com>
Link: https://patch.msgid.link/20260714204145.1782390-1-nikhil.rao@amd.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/amd/pds_core/adminq.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/amd/pds_core/adminq.c b/drivers/net/ethernet/amd/pds_core/adminq.c
index 506f682d15c10a..12eca570cb1da1 100644
--- a/drivers/net/ethernet/amd/pds_core/adminq.c
+++ b/drivers/net/ethernet/amd/pds_core/adminq.c
@@ -18,7 +18,13 @@ static int pdsc_process_notifyq(struct pdsc_qcq *qcq)
comp = cq_info->comp;
eid = le64_to_cpu(comp->event.eid);
while (eid > pdsc->last_eid) {
- u16 ecode = le16_to_cpu(comp->event.ecode);
+ u16 ecode;
+
+ /* Order the payload read after the event id, the field the
+ * driver uses to detect a new completion.
+ */
+ dma_rmb();
+ ecode = le16_to_cpu(comp->event.ecode);
switch (ecode) {
case PDS_EVENT_LINK_CHANGE:
@@ -101,6 +107,10 @@ void pdsc_process_adminq(struct pdsc_qcq *qcq)
spin_lock_irqsave(&pdsc->adminq_lock, irqflags);
comp = cq->info[cq->tail_idx].comp;
while (pdsc_color_match(comp->color, cq->done_color)) {
+ /* Order the payload reads after the color bit, the field the
+ * driver uses to detect a new completion.
+ */
+ dma_rmb();
q_info = &q->info[q->tail_idx];
q->tail_idx = (q->tail_idx + 1) & (q->num_descs - 1);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 195/602] pds_core: fix auxiliary device add/del races
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (193 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 194/602] pds_core: order completion reads after the ownership check Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 196/602] pds_core: check for workqueue allocation failure Greg Kroah-Hartman
` (410 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Nikhil P. Rao, Brett Creeley,
Pavan Chebbi, Jakub Kicinski, Sasha Levin, sashiko-bot
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikhil P. Rao <nikhil.rao@amd.com>
[ Upstream commit bfa33cd513c7ceb93c5a4c30e5662acd73c0a916 ]
Two paths add or delete the same slot (pf->vfs[vf_id].padev): a VF's
pdsc_reset_done() and the PF's devlink enable_vnet/disable_vnet handler.
They serialize on config_lock, but neither guards the slot under it
correctly.
add() registers and stores a new auxiliary device without first checking
the slot, so a second add of an already-populated slot leaks the first
device. del() makes that check outside config_lock, so two concurrent
dels can both pass it; the first clears the slot, and the second
dereferences a NULL pointer.
Check and update the slot under config_lock in both paths.
Fixes: b699bdc720c0 ("pds_core: specify auxiliary_device to be created")
Reported-by: sashiko-bot@kernel.org # Running on a local machine
Signed-off-by: Nikhil P. Rao <nikhil.rao@amd.com>
Reviewed-by: Brett Creeley <brett.creeley@amd.com>
Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
Link: https://patch.msgid.link/20260714210745.1785625-1-nikhil.rao@amd.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/amd/pds_core/auxbus.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/amd/pds_core/auxbus.c b/drivers/net/ethernet/amd/pds_core/auxbus.c
index 889a18962270aa..7d7c87fe9e8f27 100644
--- a/drivers/net/ethernet/amd/pds_core/auxbus.c
+++ b/drivers/net/ethernet/amd/pds_core/auxbus.c
@@ -177,17 +177,21 @@ void pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf,
{
struct pds_auxiliary_dev *padev;
- if (!*pd_ptr)
- return;
-
mutex_lock(&pf->config_lock);
+ /* A concurrent del may have already torn this device down and
+ * cleared it.
+ */
padev = *pd_ptr;
+ if (!padev)
+ goto out_unlock;
+
pds_client_unregister(pf, padev->client_id);
auxiliary_device_delete(&padev->aux_dev);
auxiliary_device_uninit(&padev->aux_dev);
*pd_ptr = NULL;
+out_unlock:
mutex_unlock(&pf->config_lock);
}
@@ -210,6 +214,13 @@ int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf,
mutex_lock(&pf->config_lock);
+ /* Nothing to do if the aux device is already present. This also
+ * guards against a second add overwriting *pd_ptr and leaking the
+ * first, symmetric with the check in pdsc_auxbus_dev_del().
+ */
+ if (*pd_ptr)
+ goto out_unlock;
+
mask = BIT_ULL(PDSC_S_FW_DEAD) |
BIT_ULL(PDSC_S_STOPPING_DRIVER);
if (cf->state & mask) {
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 196/602] pds_core: check for workqueue allocation failure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (194 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 195/602] pds_core: fix auxiliary device add/del races Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 197/602] sctp: validate stream count in sctp_process_strreset_inreq() Greg Kroah-Hartman
` (409 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, sashiko-bot, Nikhil P. Rao,
Brett Creeley, Pavan Chebbi, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikhil P. Rao <nikhil.rao@amd.com>
[ Upstream commit 3a660ca49e2c3807bffe0519db3cff677a5906e0 ]
pdsc_init_pf() does not check whether create_singlethread_workqueue()
succeeded.
Fail probe on failure. The workqueue is set up before the timer and
mutexes, so its failure path must unwind only the earlier setup.
Fixes: c2dbb0904310 ("pds_core: health timer and workqueue")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260629200358.2626129-1-nikhil.rao%40amd.com?part=2
Signed-off-by: Nikhil P. Rao <nikhil.rao@amd.com>
Reviewed-by: Brett Creeley <brett.creeley@amd.com>
Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
Link: https://patch.msgid.link/20260714212713.1788438-1-nikhil.rao@amd.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/amd/pds_core/main.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c
index 8a4ca474813888..c78b17d230a841 100644
--- a/drivers/net/ethernet/amd/pds_core/main.c
+++ b/drivers/net/ethernet/amd/pds_core/main.c
@@ -239,6 +239,10 @@ static int pdsc_init_pf(struct pdsc *pdsc)
/* General workqueue and timer, but don't start timer yet */
snprintf(wq_name, sizeof(wq_name), "%s.%d", PDS_CORE_DRV_NAME, pdsc->uid);
pdsc->wq = create_singlethread_workqueue(wq_name);
+ if (!pdsc->wq) {
+ err = -ENOMEM;
+ goto err_out_unmap_bars;
+ }
INIT_WORK(&pdsc->health_work, pdsc_health_thread);
INIT_WORK(&pdsc->pci_reset_work, pdsc_pci_reset_thread);
timer_setup(&pdsc->wdtimer, pdsc_wdtimer_cb, 0);
@@ -254,7 +258,7 @@ static int pdsc_init_pf(struct pdsc *pdsc)
err = pdsc_setup(pdsc, PDSC_SETUP_INIT);
if (err) {
mutex_unlock(&pdsc->config_lock);
- goto err_out_unmap_bars;
+ goto err_out_shutdown_timer;
}
err = pdsc_start(pdsc);
@@ -300,13 +304,14 @@ static int pdsc_init_pf(struct pdsc *pdsc)
pdsc_stop(pdsc);
err_out_teardown:
pdsc_teardown(pdsc, PDSC_TEARDOWN_REMOVING);
-err_out_unmap_bars:
+err_out_shutdown_timer:
timer_shutdown_sync(&pdsc->wdtimer);
if (pdsc->wq)
destroy_workqueue(pdsc->wq);
mutex_destroy(&pdsc->config_lock);
mutex_destroy(&pdsc->devcmd_lock);
pci_free_irq_vectors(pdsc->pdev);
+err_out_unmap_bars:
pdsc_unmap_bars(pdsc);
err_out_release_regions:
pci_release_regions(pdsc->pdev);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 197/602] sctp: validate stream count in sctp_process_strreset_inreq()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (195 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 196/602] pds_core: check for workqueue allocation failure Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 198/602] net: mctp i3c: clean up notifier and buses if driver register fails Greg Kroah-Hartman
` (408 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, AutonomousCodeSecurity, Xin Long,
Cen Zhang (Microsoft), Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cen Zhang (Microsoft) <blbllhy@gmail.com>
[ Upstream commit 18ae07691d43183d270de8be9dc8e027906015d9 ]
When processing a RESET_IN_REQUEST from a peer,
sctp_process_strreset_inreq() derives the stream count from the
parameter length but does not check whether the resulting
RESET_OUT_REQUEST would exceed SCTP_MAX_CHUNK_LEN.
The OUT request header (sctp_strreset_outreq, 16 bytes) is 8 bytes
larger than the IN request header (sctp_strreset_inreq, 8 bytes).
Generally, the IP payload is bounded to 65535 bytes, so the stream
list cannot be large enough to trigger the overflow. However, on
interfaces with MTU > 65535 (e.g., loopback with IPv6 jumbograms), a
stream list that fits within the incoming IN parameter can cause a
__u16 overflow in sctp_make_strreset_req() when computing the OUT
request size, leading to an undersized skb allocation and a kernel
BUG:
net/core/skbuff.c:207 skb_panic
net/core/skbuff.c:2625 skb_put
net/sctp/sm_make_chunk.c:1535 sctp_addto_chunk
net/sctp/sm_make_chunk.c:3695 sctp_make_strreset_req
net/sctp/stream.c:655 sctp_process_strreset_inreq
The local setsockopt path validates the generated reset request size.
However, for an incoming-only reset, it accounts for the smaller IN
request even though the peer must generate an OUT request with the same
stream list. Such a request cannot be completed successfully by the
peer.
Reject peer IN requests whose corresponding OUT request would exceed
SCTP_MAX_CHUNK_LEN. Also tighten the local check so it does not send an
IN request that would require an oversized OUT request from the peer.
Fixes: 7f9d68ac944e ("sctp: implement sender-side procedures for SSN Reset Request Parameter")
Reported-by: AutonomousCodeSecurity@microsoft.com
Closes: https://lore.kernel.org/all/20260707203215.2752-1-blbllhy@gmail.com/
Suggested-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: Cen Zhang (Microsoft) <blbllhy@gmail.com>
Acked-by: Xin Long <lucien.xin@gmail.com>
Link: https://patch.msgid.link/20260710010718.20318-1-blbllhy@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/sctp/stream.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/net/sctp/stream.c b/net/sctp/stream.c
index e8922f350bafe6..0f81820c730bae 100644
--- a/net/sctp/stream.c
+++ b/net/sctp/stream.c
@@ -308,7 +308,8 @@ int sctp_send_reset_streams(struct sctp_association *asoc,
goto out;
param_len += str_nums * sizeof(__u16) +
- sizeof(struct sctp_strreset_inreq);
+ (out ? sizeof(struct sctp_strreset_inreq)
+ : sizeof(struct sctp_strreset_outreq));
}
if (param_len > SCTP_MAX_CHUNK_LEN -
@@ -639,6 +640,9 @@ struct sctp_chunk *sctp_process_strreset_inreq(
nums = (ntohs(param.p->length) - sizeof(*inreq)) / sizeof(__u16);
str_p = inreq->list_of_streams;
+ if (nums * sizeof(__u16) + sizeof(struct sctp_strreset_outreq) >
+ SCTP_MAX_CHUNK_LEN - sizeof(struct sctp_reconf_chunk))
+ goto out;
for (i = 0; i < nums; i++) {
if (ntohs(str_p[i]) >= stream->outcnt) {
result = SCTP_STRRESET_ERR_WRONG_SSN;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 198/602] net: mctp i3c: clean up notifier and buses if driver register fails
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (196 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 197/602] sctp: validate stream count in sctp_process_strreset_inreq() Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 199/602] tls: device: push pending open record on splice EOF Greg Kroah-Hartman
` (407 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Ijae Kim, Myeonghun Pak, Jeremy Kerr,
Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Myeonghun Pak <mhun512@gmail.com>
[ Upstream commit 03d1057305ef17ac3f5936ac1580bc9a1a826e14 ]
mctp_i3c_mod_init() registers the I3C bus notifier and then walks the
existing buses with i3c_for_each_bus_locked(mctp_i3c_bus_add_new, NULL)
before registering the I3C device driver. If i3c_driver_register()
fails, the function returns the error directly, leaving the notifier
registered and every mctp_i3c_bus object created for the existing buses
allocated. The notifier is left pointing into the module that failed to
load and the bus list is leaked.
Mirror the module exit path on this failure: unregister the notifier and
tear down the buses that were added before returning the error.
This issue was identified during our ongoing static-analysis research while
reviewing kernel code.
Fixes: c8755b29b58e ("mctp i3c: MCTP I3C driver")
Co-developed-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Myeonghun Pak <mhun512@gmail.com>
Acked-by: Jeremy Kerr <jk@codeconstruct.com.au>
Link: https://patch.msgid.link/20260715072517.13216-1-mhun512@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/mctp/mctp-i3c.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/net/mctp/mctp-i3c.c b/drivers/net/mctp/mctp-i3c.c
index 47513ebbc68079..fbcd48f1971a45 100644
--- a/drivers/net/mctp/mctp-i3c.c
+++ b/drivers/net/mctp/mctp-i3c.c
@@ -731,18 +731,21 @@ static __init int mctp_i3c_mod_init(void)
int rc;
rc = i3c_register_notifier(&mctp_i3c_notifier);
- if (rc < 0) {
- i3c_driver_unregister(&mctp_i3c_driver);
+ if (rc < 0)
return rc;
- }
i3c_for_each_bus_locked(mctp_i3c_bus_add_new, NULL);
rc = i3c_driver_register(&mctp_i3c_driver);
if (rc < 0)
- return rc;
+ goto err_unregister_notifier;
return 0;
+
+err_unregister_notifier:
+ i3c_unregister_notifier(&mctp_i3c_notifier);
+ mctp_i3c_bus_remove_all();
+ return rc;
}
static __exit void mctp_i3c_mod_exit(void)
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 199/602] tls: device: push pending open record on splice EOF
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (197 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 198/602] net: mctp i3c: clean up notifier and buses if driver register fails Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 200/602] selftests: af_unix: add USER_NS config Greg Kroah-Hartman
` (406 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Nils Juenemann, Rishikesh Jethwani,
Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rishikesh Jethwani <rjethwani@purestorage.com>
[ Upstream commit eaa39f9f8ac8c1d032cd26b9cd572804e9d7683f ]
On kTLS device-offload sockets, sendfile() with count > EOF can reach
->splice_eof() with a fully assembled but still-open TLS record left
pending. tls_device_splice_eof() only flushes partially sent records,
so an abrupt close() can drop the final record and the peer receives
a short file.
Fix tls_device_splice_eof() to also push pending open records.
This matches the software path, where splice EOF already flushes
pending open records.
Fixes: d4c1e80b0d1b ("tls/device: Use splice_eof() to flush")
Link: https://lore.kernel.org/netdev/CAMPsyauZ+jzG9AysO0FWv6ZY0kvCUpjX_U7o=oOjCuOQ87BCgg@mail.gmail.com/
Reported-by: Nils Juenemann <nils.juenemann@gmail.com>
Signed-off-by: Rishikesh Jethwani <rjethwani@purestorage.com>
Tested-by: Nils Juenemann <nils.juenemann@gmail.com>
Link: https://patch.msgid.link/20260709224436.1608993-2-rjethwani@purestorage.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/tls/tls_device.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c
index 5c6a4c9a2df755..942edc9b3157af 100644
--- a/net/tls/tls_device.c
+++ b/net/tls/tls_device.c
@@ -594,13 +594,15 @@ void tls_device_splice_eof(struct socket *sock)
struct tls_context *tls_ctx = tls_get_ctx(sk);
struct iov_iter iter = {};
- if (!tls_is_partially_sent_record(tls_ctx))
+ if (!tls_is_partially_sent_record(tls_ctx) &&
+ !tls_is_pending_open_record(tls_ctx))
return;
mutex_lock(&tls_ctx->tx_lock);
lock_sock(sk);
- if (tls_is_partially_sent_record(tls_ctx)) {
+ if (tls_is_partially_sent_record(tls_ctx) ||
+ tls_is_pending_open_record(tls_ctx)) {
iov_iter_bvec(&iter, ITER_SOURCE, NULL, 0, 0);
tls_push_data(sk, &iter, 0, 0, TLS_RECORD_TYPE_DATA);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 200/602] selftests: af_unix: add USER_NS config
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (198 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 199/602] tls: device: push pending open record on splice EOF Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 201/602] selftests: openvswitch: add config file Greg Kroah-Hartman
` (405 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Matthieu Baerts (NGI0),
Kuniyuki Iwashima, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <matttbe@kernel.org>
[ Upstream commit f8b1abed736111f914b2c567d9a3db1f71e788e8 ]
This is required to use unshare(CLONE_NEWUSER).
This has not been seen on NIPA before, because the 'af_unix' tests are
executed with the 'net' ones, merging their config files. USER_NS is
present in tools/testing/selftests/net/config.
This issue is visible when only the af_unix config is used on top of the
default one. This is the recommended way to execute selftest targets.
Fixes: ac011361bd4f ("af_unix: Add test for sock_diag and UDIAG_SHOW_UID.")
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Link: https://patch.msgid.link/20260710-net-sft-fix-containers-v1-1-a2915c294ef5@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
tools/testing/selftests/net/af_unix/config | 1 +
1 file changed, 1 insertion(+)
diff --git a/tools/testing/selftests/net/af_unix/config b/tools/testing/selftests/net/af_unix/config
index 37368567768cc0..9c4fb9c31c9506 100644
--- a/tools/testing/selftests/net/af_unix/config
+++ b/tools/testing/selftests/net/af_unix/config
@@ -1,3 +1,4 @@
CONFIG_UNIX=y
CONFIG_AF_UNIX_OOB=y
CONFIG_UNIX_DIAG=m
+CONFIG_USER_NS=y
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 201/602] selftests: openvswitch: add config file
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (199 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 200/602] selftests: af_unix: add USER_NS config Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 202/602] gtp: check skb_pull_data() return in gtp1u_send_echo_resp() Greg Kroah-Hartman
` (404 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Matthieu Baerts (NGI0),
Eelco Chaudron, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <matttbe@kernel.org>
[ Upstream commit 441a820ccef9af80a9ac5a4c85b9c396e595967c ]
The kselftests doc mentions that a config file should be present "if a
test needs specific kernel config options enabled". This selftest
requires some kernel config, but no config file was provided.
We could say that a sub-target could use the parent's config file, but
the kselftests doc doesn't mention anything about that. Plus the
net/openvswitch target is the only net target without a config file.
Here is a new config file, which is a trimmed version of the net one,
with hopefully the minimal required kconfig on top of 'make defconfig'.
The Fixes tag points to the introduction of the net/openvswitch target,
just to help validating this target on stable kernels.
Fixes: 25f16c873fb1 ("selftests: add openvswitch selftest suite")
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Reviewed-by: Eelco Chaudron <echaudro@redhat.com>
Link: https://patch.msgid.link/20260710-net-sft-fix-containers-v1-2-a2915c294ef5@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
tools/testing/selftests/net/openvswitch/config | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
create mode 100644 tools/testing/selftests/net/openvswitch/config
diff --git a/tools/testing/selftests/net/openvswitch/config b/tools/testing/selftests/net/openvswitch/config
new file mode 100644
index 00000000000000..c659749cd086c7
--- /dev/null
+++ b/tools/testing/selftests/net/openvswitch/config
@@ -0,0 +1,16 @@
+CONFIG_GENEVE=m
+CONFIG_INET_DIAG=y
+CONFIG_IPV6=y
+CONFIG_NETFILTER=y
+CONFIG_NET_IPGRE=m
+CONFIG_NET_IPGRE_DEMUX=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_OVS=y
+CONFIG_OPENVSWITCH=m
+CONFIG_OPENVSWITCH_GENEVE=m
+CONFIG_OPENVSWITCH_GRE=m
+CONFIG_OPENVSWITCH_VXLAN=m
+CONFIG_PSAMPLE=m
+CONFIG_VETH=y
+CONFIG_VLAN_8021Q=y
+CONFIG_VXLAN=m
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 202/602] gtp: check skb_pull_data() return in gtp1u_send_echo_resp()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (200 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 201/602] selftests: openvswitch: add config file Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 203/602] nexthop: initialize extack in nh_res_bucket_migrate() Greg Kroah-Hartman
` (403 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, AutonomousCodeSecurity,
Xiang Mei (Microsoft), Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei (Microsoft) <xmei5@asu.edu>
[ Upstream commit cd170f051dba9ac146fabcd1b91726487c0cb9fa ]
gtp1u_send_echo_resp() ignores skb_pull_data()'s return value. Its
caller gtp1u_udp_encap_recv() only guarantees 16 bytes (udphdr +
gtp1_header), but the pull requests 20 (gtp1_header_long + udphdr). For
a 16-19 byte echo request the pull fails and returns NULL without
advancing skb->data; execution continues, and the following skb_push()
plus the IP header pushed by iptunnel_xmit() move skb->data below
skb->head, tripping skb_under_panic().
Fix it by dropping the packet when skb_pull_data() fails.
skbuff: skb_under_panic: ...
kernel BUG at net/core/skbuff.c:214!
Call Trace:
skb_push (net/core/skbuff.c:2648)
iptunnel_xmit (net/ipv4/ip_tunnel_core.c:82)
gtp_encap_recv (drivers/net/gtp.c:701 drivers/net/gtp.c:808 drivers/net/gtp.c:920)
udp_queue_rcv_one_skb (net/ipv4/udp.c:2388)
...
Kernel panic - not syncing: Fatal exception in interrupt
Fixes: 9af41cc33471 ("gtp: Implement GTP echo response")
Reported-by: AutonomousCodeSecurity@microsoft.com
Signed-off-by: Xiang Mei (Microsoft) <xmei5@asu.edu>
Link: https://patch.msgid.link/20260710230724.942574-1-xmei5@asu.edu
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/gtp.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index dc4770e79990f0..b99cab7f10ce7a 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -665,8 +665,9 @@ static int gtp1u_send_echo_resp(struct gtp_dev *gtp, struct sk_buff *skb)
return -1;
/* pull GTP and UDP headers */
- skb_pull_data(skb,
- sizeof(struct gtp1_header_long) + sizeof(struct udphdr));
+ if (!skb_pull_data(skb, sizeof(struct gtp1_header_long) +
+ sizeof(struct udphdr)))
+ return -1;
gtp_pkt = skb_push(skb, sizeof(struct gtp1u_packet));
memset(gtp_pkt, 0, sizeof(struct gtp1u_packet));
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 203/602] nexthop: initialize extack in nh_res_bucket_migrate()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (201 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 202/602] gtp: check skb_pull_data() return in gtp1u_send_echo_resp() Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 204/602] tipc: fix infinite loop in __tipc_nl_compat_dumpit Greg Kroah-Hartman
` (402 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, AutonomousCodeSecurity,
Xiang Mei (Microsoft), Ido Schimmel, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei (Microsoft) <xmei5@asu.edu>
[ Upstream commit 6347c5314cee49f364aaf2e40ff15415a57a116e ]
nh_res_bucket_migrate() passes an uninitialized netlink_ext_ack to
call_nexthop_res_bucket_notifiers(). When
nh_notifier_res_bucket_info_init() fails (e.g. the kzalloc returns
-ENOMEM), the error is propagated back before any notifier sets
extack._msg, and the error path formats the stale pointer with
pr_err_ratelimited("%s\n", extack._msg). With CONFIG_INIT_STACK_NONE
this dereferences uninitialized stack memory:
Oops: general protection fault, probably for non-canonical address ...
KASAN: maybe wild-memory-access in range [...]
RIP: 0010:string (lib/vsprintf.c:730)
vsnprintf (lib/vsprintf.c:2945)
_printk (kernel/printk/printk.c:2504)
nh_res_bucket_migrate (net/ipv4/nexthop.c:1816)
nh_res_table_upkeep (net/ipv4/nexthop.c:1866)
rtm_new_nexthop (net/ipv4/nexthop.c:3323)
rtnetlink_rcv_msg (net/core/rtnetlink.c:7076)
netlink_sendmsg (net/netlink/af_netlink.c:1900)
Kernel panic - not syncing: Fatal exception
Zero-initialize extack so _msg is NULL on error paths that never set it.
Fixes: 7c37c7e00411 ("nexthop: Implement notifiers for resilient nexthop groups")
Reported-by: AutonomousCodeSecurity@microsoft.com
Signed-off-by: Xiang Mei (Microsoft) <xmei5@asu.edu>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20260713221551.3344650-1-xmei5@asu.edu
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/ipv4/nexthop.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c
index 52d4890be83e86..ef323775f09acb 100644
--- a/net/ipv4/nexthop.c
+++ b/net/ipv4/nexthop.c
@@ -1778,8 +1778,8 @@ static bool nh_res_bucket_migrate(struct nh_res_table *res_table,
bool notify_nl, bool force)
{
struct nh_res_bucket *bucket = &res_table->nh_buckets[bucket_index];
+ struct netlink_ext_ack extack = {};
struct nh_grp_entry *new_nhge;
- struct netlink_ext_ack extack;
int err;
new_nhge = list_first_entry_or_null(&res_table->uw_nh_entries,
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 204/602] tipc: fix infinite loop in __tipc_nl_compat_dumpit
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (202 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 203/602] nexthop: initialize extack in nh_res_bucket_migrate() Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 205/602] wifi: mt76: mt7925: guard link STA in decap offload Greg Kroah-Hartman
` (401 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, syzbot+85d0bec020d805014a3a,
Helen Koike, Tung Nguyen, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Helen Koike <koike@igalia.com>
[ Upstream commit 22f8aa35964e8f2ab026578f45befc9605fd1b28 ]
cmd->dumpit callback can return a negative errno, causing an infinite
loop due to the while(len) condition. As the loop never terminates,
genl_mutex is never released, and other tasks waiting on it starve in D
state.
Check dumpit's return value, propagate it and jump to err_out on error.
Reported-by: syzbot+85d0bec020d805014a3a@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=85d0bec020d805014a3a
Fixes: d0796d1ef63d ("tipc: convert legacy nl bearer dump to nl compat")
Signed-off-by: Helen Koike <koike@igalia.com>
Reviewed-by: Tung Nguyen <tung.quang.nguyen@est.tech
Reviewed-by: Tung Nguyen <tung.quang.nguyen@est.tech>
Link: https://patch.msgid.link/20260713204940.647668-1-koike@igalia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/tipc/netlink_compat.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c
index 079aebb16ed8ff..30e37c05a3f334 100644
--- a/net/tipc/netlink_compat.c
+++ b/net/tipc/netlink_compat.c
@@ -222,6 +222,10 @@ static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd,
int rem;
len = (*cmd->dumpit)(buf, &cb);
+ if (len < 0) {
+ err = len;
+ goto err_out;
+ }
nlmsg_for_each_msg(nlmsg, nlmsg_hdr(buf), len, rem) {
err = nlmsg_parse_deprecated(nlmsg, GENL_HDRLEN,
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 205/602] wifi: mt76: mt7925: guard link STA in decap offload
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (203 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 204/602] tipc: fix infinite loop in __tipc_nl_compat_dumpit Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 206/602] wifi: mt76: mt7915: guard HE capability lookups Greg Kroah-Hartman
` (400 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Guangshuo Li, Felix Fietkau,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <lgs201920130244@gmail.com>
[ Upstream commit 96ea44f2269f30364cffa054ee3a87e595bef0d4 ]
mt7925_sta_set_decap_offload() iterates over the vif valid_links mask
when updating decap offload state for an MLO station. The station may not
have a link STA for every valid link of the vif, so mt792x_sta_to_link()
can return NULL for a link that belongs to the vif but not to the station.
The function currently dereferences mlink before checking whether the
link WCID is ready. If mlink is NULL, setting or clearing
MT_WCID_FLAG_HDR_TRANS dereferences a NULL pointer.
Skip links without a station link before touching mlink->wcid.
Fixes: b859ad65309a ("wifi: mt76: mt7925: add link handling in mt7925_sta_set_decap_offload")
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
Link: https://patch.msgid.link/20260708075539.726200-1-lgs201920130244@gmail.com
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/mediatek/mt76/mt7925/main.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
index 98ec76cf2fe8b4..1dbc6d22b06661 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
@@ -1583,6 +1583,9 @@ static void mt7925_sta_set_decap_offload(struct ieee80211_hw *hw,
mlink = mt792x_sta_to_link(msta, i);
+ if (!mlink)
+ continue;
+
if (enabled)
set_bit(MT_WCID_FLAG_HDR_TRANS, &mlink->wcid.flags);
else
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 206/602] wifi: mt76: mt7915: guard HE capability lookups
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (204 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 205/602] wifi: mt76: mt7925: guard link STA in decap offload Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 207/602] wifi: mt76: connac: fix possible NULL-pointer deref in mt76_connac_mcu_uni_bss_he_tlv() Greg Kroah-Hartman
` (399 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Ruoyu Wang, Lorenzo Bianconi,
Felix Fietkau, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <ruoyuw560@gmail.com>
[ Upstream commit 8e9db062654a388d0fa587acbeeae68dd33eba41 ]
mt7915_mcu_bss_he_tlv() and mt7915_mcu_sta_bfer_tlv() both run after
checking HE support, then dereference the HE PHY capability returned by
mt76_connac_get_he_phy_cap(). That helper can return NULL when no
capability entry matches the vif type.
Fetch the capability before appending the TLV and skip the HE-specific
setup when no matching capability is available.
Fixes: e6d557a78b60 ("mt76: mt7915: rely on mt76_connac_get_phy utilities")
Signed-off-by: Ruoyu Wang <ruoyuw560@gmail.com>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20260620155332.81120-1-ruoyuw560@gmail.com
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
.../net/wireless/mediatek/mt76/mt7915/mcu.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
index 2489364110d6eb..d622d7c7bee41c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -551,6 +551,8 @@ mt7915_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
struct tlv *tlv;
cap = mt76_connac_get_he_phy_cap(phy->mt76, vif);
+ if (!cap)
+ return;
tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_HE_BASIC, sizeof(*he));
@@ -1133,13 +1135,12 @@ mt7915_mcu_sta_bfer_vht(struct ieee80211_sta *sta, struct mt7915_phy *phy,
}
static void
-mt7915_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif,
- struct mt7915_phy *phy, struct sta_rec_bf *bf)
+mt7915_mcu_sta_bfer_he(struct ieee80211_sta *sta,
+ const struct ieee80211_sta_he_cap *vc,
+ struct sta_rec_bf *bf)
{
struct ieee80211_sta_he_cap *pc = &sta->deflink.he_cap;
struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem;
- const struct ieee80211_sta_he_cap *vc =
- mt76_connac_get_he_phy_cap(phy->mt76, vif);
const struct ieee80211_he_cap_elem *ve = &vc->he_cap_elem;
u16 mcs_map = le16_to_cpu(pc->he_mcs_nss_supp.rx_mcs_80);
u8 nss_mcs = mt7915_mcu_get_sta_nss(mcs_map);
@@ -1198,6 +1199,7 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
{
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
struct mt7915_phy *phy = mvif->phy;
+ const struct ieee80211_sta_he_cap *vc = NULL;
int tx_ant = hweight8(phy->mt76->chainmask) - 1;
struct sta_rec_bf *bf;
struct tlv *tlv;
@@ -1216,6 +1218,12 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
if (!ebf && !dev->ibf)
return;
+ if (sta->deflink.he_cap.has_he && ebf) {
+ vc = mt76_connac_get_he_phy_cap(phy->mt76, vif);
+ if (!vc)
+ return;
+ }
+
tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BF, sizeof(*bf));
bf = (struct sta_rec_bf *)tlv;
@@ -1224,7 +1232,7 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
* ht: iBF only, since mac80211 lacks of eBF support
*/
if (sta->deflink.he_cap.has_he && ebf)
- mt7915_mcu_sta_bfer_he(sta, vif, phy, bf);
+ mt7915_mcu_sta_bfer_he(sta, vc, bf);
else if (sta->deflink.vht_cap.vht_supported)
mt7915_mcu_sta_bfer_vht(sta, phy, bf, ebf);
else if (sta->deflink.ht_cap.ht_supported)
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 207/602] wifi: mt76: connac: fix possible NULL-pointer deref in mt76_connac_mcu_uni_bss_he_tlv()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (205 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 206/602] wifi: mt76: mt7915: guard HE capability lookups Greg Kroah-Hartman
@ 2026-07-30 14:09 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 208/602] wifi: mt76: mt7925: fix possible NULL-pointer deref in mt7925_mcu_bss_he_tlv() Greg Kroah-Hartman
` (398 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:09 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Lorenzo Bianconi, Felix Fietkau,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <lorenzo@kernel.org>
[ Upstream commit 2c1fb2335f5e3afb34f91bc07ecb63517c328090 ]
mt76_connac_get_he_phy_cap routine can theoretically return NULL so
check cap pointer before dereferencing it.
Fixes: d0e274af2f2e4 ("mt76: mt76_connac: create mcu library")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20260621-mt76_connac_get_he_phy_cap-fix-v1-1-ed4ccf7a0363@kernel.org
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
index 462b4a68c4f0f1..b1a7fbedffac5c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
@@ -1435,6 +1435,8 @@ mt76_connac_mcu_uni_bss_he_tlv(struct mt76_phy *phy, struct ieee80211_vif *vif,
struct bss_info_uni_he *he;
cap = mt76_connac_get_he_phy_cap(phy, vif);
+ if (!cap)
+ return;
he = (struct bss_info_uni_he *)tlv;
he->he_pe_duration = vif->bss_conf.htc_trig_based_pkt_ext;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 208/602] wifi: mt76: mt7925: fix possible NULL-pointer deref in mt7925_mcu_bss_he_tlv()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (206 preceding siblings ...)
2026-07-30 14:09 ` [PATCH 6.12 207/602] wifi: mt76: connac: fix possible NULL-pointer deref in mt76_connac_mcu_uni_bss_he_tlv() Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 209/602] wifi: mt76: mt7996: check pointer returned by mt76_connac_get_he_phy_cap() Greg Kroah-Hartman
` (397 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Lorenzo Bianconi, Felix Fietkau,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <lorenzo@kernel.org>
[ Upstream commit 8d1b6738c1ab48c086b17e7994034aca94258931 ]
mt76_connac_get_he_phy_cap routine can theoretically return NULL so
check cap pointer before dereferencing it.
Fixes: c948b5da6bbec ("wifi: mt76: mt7925: add Mediatek Wi-Fi7 driver for mt7925 chips")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20260621-mt76_connac_get_he_phy_cap-fix-v1-2-ed4ccf7a0363@kernel.org
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
index 1f113a618515e8..1fc1116d9becca 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
@@ -2646,6 +2646,8 @@ mt7925_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_bss_conf *link_conf,
struct tlv *tlv;
cap = mt76_connac_get_he_phy_cap(phy->mt76, link_conf->vif);
+ if (!cap)
+ return;
tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_HE_BASIC, sizeof(*he));
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 209/602] wifi: mt76: mt7996: check pointer returned by mt76_connac_get_he_phy_cap()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (207 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 208/602] wifi: mt76: mt7925: fix possible NULL-pointer deref in mt7925_mcu_bss_he_tlv() Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 210/602] wifi: mt76: mt7925: fix crash in reset link replay Greg Kroah-Hartman
` (396 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Lorenzo Bianconi, Felix Fietkau,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <lorenzo@kernel.org>
[ Upstream commit e858cf6bf99880343348ff1e8c942aaff1d9d592 ]
mt76_connac_get_he_phy_cap routine can theoretically return NULL so
check cap pointer before dereferencing it.
Fixes: 98686cd21624c ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20260621-mt76_connac_get_he_phy_cap-fix-v1-3-ed4ccf7a0363@kernel.org
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index 54567a5893449e..5730980fdc64eb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -798,6 +798,8 @@ mt7996_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
struct tlv *tlv;
cap = mt76_connac_get_he_phy_cap(phy->mt76, vif);
+ if (!cap)
+ return;
tlv = mt7996_mcu_add_uni_tlv(skb, UNI_BSS_INFO_HE_BASIC, sizeof(*he));
@@ -1537,17 +1539,18 @@ mt7996_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif,
{
struct ieee80211_sta_he_cap *pc = &sta->deflink.he_cap;
struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem;
- const struct ieee80211_sta_he_cap *vc =
- mt76_connac_get_he_phy_cap(phy->mt76, vif);
- const struct ieee80211_he_cap_elem *ve = &vc->he_cap_elem;
u16 mcs_map = le16_to_cpu(pc->he_mcs_nss_supp.rx_mcs_80);
u8 nss_mcs = mt7996_mcu_get_sta_nss(mcs_map);
+ const struct ieee80211_he_cap_elem *ve;
+ const struct ieee80211_sta_he_cap *vc;
u8 snd_dim, sts;
+ vc = mt76_connac_get_he_phy_cap(phy->mt76, vif);
if (!vc)
return;
bf->tx_mode = MT_PHY_TYPE_HE_SU;
+ ve = &vc->he_cap_elem;
mt7996_mcu_sta_sounding_rate(bf);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 210/602] wifi: mt76: mt7925: fix crash in reset link replay
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (208 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 209/602] wifi: mt76: mt7996: check pointer returned by mt76_connac_get_he_phy_cap() Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 211/602] wifi: mt76: mt7996: fix possible NULL-pointer deref in mt7996_mcu_sta_bfer_eht() Greg Kroah-Hartman
` (395 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Sean Wang, Felix Fietkau,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Wang <sean.wang@mediatek.com>
[ Upstream commit bd8b2ec838184236c3fcbf738a926328836adf12 ]
During reset recovery, mt7925_vif_connect_iter() replays firmware state
for links tracked in mvif->valid_links. After MLO link changes or MCU
timeout recovery, the driver bitmap can temporarily contain a link whose
mac80211 bss_conf has already gone away.
This can pass a NULL bss_conf to mt76_connac_mcu_uni_add_dev(), matching
the crash where x1, the second argument, is NULL:
pc : mt76_connac_mcu_uni_add_dev+0x8c/0x1f8 [mt76_connac_lib]
lr : mt7925_vif_connect_iter+0x9c/0x168 [mt7925_common]
x2 : ffffff80a77f6018 x1 : 0000000000000000 x0 : ffffff8099402080
Call trace:
mt76_connac_mcu_uni_add_dev+0x8c/0x1f8 [mt76_connac_lib]
mt7925_vif_connect_iter+0x9c/0x168 [mt7925_common]
mt7925_mac_reset_work+0x264/0x2f8 [mt7925_common]
Skip missing bss_conf entries before replaying the link. Non-MLO AP/STA
reset replay is unchanged because the helper still returns &vif->bss_conf
for the legacy link.
Fixes: 14061994184d ("wifi: mt76: mt7925: add link handling in mt7925_vif_connect_iter")
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
Link: https://patch.msgid.link/20260616161016.19346-1-sean.wang@kernel.org
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/mediatek/mt76/mt7925/mac.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
index f01dbca6e9b9ca..9ed0c2655037a0 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
@@ -1285,6 +1285,9 @@ mt7925_vif_connect_iter(void *priv, u8 *mac,
for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) {
bss_conf = mt792x_vif_to_bss_conf(vif, i);
+ if (!bss_conf)
+ continue;
+
mconf = mt792x_vif_to_link(mvif, i);
mt76_connac_mcu_uni_add_dev(&dev->mphy, bss_conf, &mconf->mt76,
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 211/602] wifi: mt76: mt7996: fix possible NULL-pointer deref in mt7996_mcu_sta_bfer_eht()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (209 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 210/602] wifi: mt76: mt7925: fix crash in reset link replay Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 212/602] wifi: brcmfmac: fix 802.1X-SHA256 call trace warning Greg Kroah-Hartman
` (394 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Lorenzo Bianconi, Felix Fietkau,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <lorenzo@kernel.org>
[ Upstream commit 2fffc472bec490c8357defcee9c075ca74467352 ]
mt76_connac_get_eht_phy_cap routine can theoretically return NULL so
check cap pointer before dereferencing it.
Fixes: ba01944adee9f ("wifi: mt76: mt7996: add EHT beamforming support")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20260621-mt76_connac_get_he_phy_cap-fix-v1-4-ed4ccf7a0363@kernel.org
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index 5730980fdc64eb..a5693efee74b85 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -1604,14 +1604,18 @@ mt7996_mcu_sta_bfer_eht(struct ieee80211_sta *sta, struct ieee80211_vif *vif,
struct ieee80211_sta_eht_cap *pc = &sta->deflink.eht_cap;
struct ieee80211_eht_cap_elem_fixed *pe = &pc->eht_cap_elem;
struct ieee80211_eht_mcs_nss_supp *eht_nss = &pc->eht_mcs_nss_supp;
- const struct ieee80211_sta_eht_cap *vc =
- mt76_connac_get_eht_phy_cap(phy->mt76, vif);
- const struct ieee80211_eht_cap_elem_fixed *ve = &vc->eht_cap_elem;
u8 nss_mcs = u8_get_bits(eht_nss->bw._80.rx_tx_mcs9_max_nss,
IEEE80211_EHT_MCS_NSS_RX) - 1;
+ const struct ieee80211_eht_cap_elem_fixed *ve;
+ const struct ieee80211_sta_eht_cap *vc;
u8 snd_dim, sts;
+ vc = mt76_connac_get_eht_phy_cap(phy->mt76, vif);
+ if (!vc)
+ return;
+
bf->tx_mode = MT_PHY_TYPE_EHT_MU;
+ ve = &vc->eht_cap_elem;
mt7996_mcu_sta_sounding_rate(bf);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 212/602] wifi: brcmfmac: fix 802.1X-SHA256 call trace warning
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (210 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 211/602] wifi: mt76: mt7996: fix possible NULL-pointer deref in mt7996_mcu_sta_bfer_eht() Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 213/602] ovl: fix trusted xattr escape prefix matching Greg Kroah-Hartman
` (393 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Shelley Yang, Arend van Spriel,
Johannes Berg, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shelley Yang <shelley.yang@infineon.com>
[ Upstream commit 7cb34f6c4fe8a68af621d870abe63bfca2275dd6 ]
Based on wpa_auth as 1x_256 mode, need to set up
"use_fwsup" with BRCMF_PROFILE_FWSUP_1X.
Or it will happen trace warning when call brcmf_cfg80211_set_pmk().
[ 4481.831101] ------------[ cut here ]------------
[ 4481.831102] WARNING: CPU: 1 PID: 2997 at
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:7242 brcmf_cfg80211_set_pmk+0x77/0xd0 [brcmfmac]
[...]
[ 4481.831202] Call Trace:
[ 4481.831204] <TASK>
[ 4481.831205] nl80211_set_pmk+0x183/0x250 [cfg80211]
[ 4481.831233] genl_family_rcv_msg_doit+0xea/0x150
[ 4481.831237] genl_rcv_msg+0x104/0x240
[ 4481.831239] ? cfg80211_probe_status+0x2c0/0x2c0 [cfg80211]
[ 4481.831257] ? genl_family_rcv_msg_doit+0x150/0x150
[ 4481.831259] netlink_rcv_skb+0x4e/0x100
[ 4481.831261] genl_rcv+0x24/0x40
[ 4481.831262] netlink_unicast+0x236/0x380
[ 4481.831264] netlink_sendmsg+0x250/0x4b0
[ 4481.831266] sock_sendmsg+0x5c/0x70
[ 4481.831269] ____sys_sendmsg+0x236/0x2b0
[ 4481.831271] ? copy_msghdr_from_user+0x6d/0xa0
[ 4481.831272] ___sys_sendmsg+0x86/0xd0
[ 4481.831274] ? avc_has_perm+0x8c/0x1a0
[ 4481.831276] ? preempt_count_add+0x6a/0xa0
[ 4481.831279] ? sock_has_perm+0x82/0xa0
[ 4481.831280] __sys_sendmsg+0x57/0xa0
[ 4481.831282] do_syscall_64+0x38/0x90
[ 4481.831284] entry_SYSCALL_64_after_hwframe+0x63/0xcd
[ 4481.831286] RIP: 0033:0x7fd270d369b4
Fixes: 2526ff21aa77 ("brcmfmac: support 4-way handshake offloading for 802.1X")
Signed-off-by: Shelley Yang <shelley.yang@infineon.com>
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Link: https://patch.msgid.link/20260525083859.581246-1-shelley.yang@infineon.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index 2b8a85a7bf9eba..c3a3a081791095 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -2122,7 +2122,7 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme)
sme->crypto.akm_suites[0]);
return -EINVAL;
}
- } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) {
+ } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED | WPA2_AUTH_1X_SHA256)) {
switch (sme->crypto.akm_suites[0]) {
case WLAN_AKM_SUITE_8021X:
val = WPA2_AUTH_UNSPECIFIED;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 213/602] ovl: fix trusted xattr escape prefix matching
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (211 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 212/602] wifi: brcmfmac: fix 802.1X-SHA256 call trace warning Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 214/602] amt: re-read skb header pointers after every pull Greg Kroah-Hartman
` (392 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yichong Chen, Amir Goldstein,
Christian Brauner (Amutable), Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yichong Chen <chenyichong@uniontech.com>
[ Upstream commit a8e72879cd0d8422c0b47d6d3c1802274fe73b98 ]
In the trusted.* xattr namespace, ovl_is_escaped_xattr() compares
one byte less than the escaped overlay xattr prefix length. This makes
it match "trusted.overlay.overlay" without requiring the trailing dot.
As a result, an xattr such as "trusted.overlay.overlayfoo" is
incorrectly treated as an escaped overlay xattr. This can be reproduced
by setting "trusted.overlay.overlayfoo" on a lower file and listing xattrs
through an overlay mount. listxattr() then exposes it as
"trusted.overlay.oo", and a following getxattr() on that listed name fails
with ENODATA.
Compare the full escaped prefix, including the trailing dot, so
similarly-prefixed private xattrs are not misclassified.
Fixes: dad02fad84cbc ("ovl: Support escaped overlay.* xattrs")
Signed-off-by: Yichong Chen <chenyichong@uniontech.com>
Link: https://patch.msgid.link/20260708082221.633602-1-chenyichong@uniontech.com
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/overlayfs/xattrs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/overlayfs/xattrs.c b/fs/overlayfs/xattrs.c
index 383978e4663c2a..6ba79ee00f7370 100644
--- a/fs/overlayfs/xattrs.c
+++ b/fs/overlayfs/xattrs.c
@@ -13,7 +13,7 @@ static bool ovl_is_escaped_xattr(struct super_block *sb, const char *name)
OVL_XATTR_ESCAPE_USER_PREFIX_LEN) == 0;
else
return strncmp(name, OVL_XATTR_ESCAPE_TRUSTED_PREFIX,
- OVL_XATTR_ESCAPE_TRUSTED_PREFIX_LEN - 1) == 0;
+ OVL_XATTR_ESCAPE_TRUSTED_PREFIX_LEN) == 0;
}
static bool ovl_is_own_xattr(struct super_block *sb, const char *name)
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 214/602] amt: re-read skb header pointers after every pull
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (212 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 213/602] ovl: fix trusted xattr escape prefix matching Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 215/602] amt: make the head writable before rewriting the L2 header Greg Kroah-Hartman
` (391 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Michael Bommarito, Simon Horman,
Taehee Yoo, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <michael.bommarito@gmail.com>
[ Upstream commit 3656a79f94c471827a08f2cacce5f94ad5e52c24 ]
Several AMT receive and transmit paths cache a pointer into the skb head
(ip_hdr(), ipv6_hdr(), eth_hdr() or the AMT message header) and then call
a helper that can reallocate that head before the cached pointer is used
again. pskb_may_pull(), ip_mc_may_pull(), ipv6_mc_may_pull(),
iptunnel_pull_header(), ip_mc_check_igmp() and ipv6_mc_check_mld() can all
free the old head and move the data, so a pointer taken before the call
dangles afterwards and the later access is a use-after-free of the freed
head.
The affected sites are:
amt_rcv() caches ip_hdr() before amt_parse_type() pulls, then reads
iph->saddr.
amt_dev_xmit() caches ip_hdr()/ipv6_hdr() before ip_mc_check_igmp()/
ipv6_mc_check_mld() and pskb_may_pull(), then reads the group address.
amt_multicast_data_handler() caches eth_hdr() before pskb_may_pull(),
then writes the L2 header.
amt_membership_query_handler() caches the AMT header, the outer and
inner eth_hdr() and ip_hdr() before iptunnel_pull_header() and several
pulls, then reads and writes them.
amt_igmpv3_report_handler() and amt_mldv2_report_handler() cache
ip_hdr()/ipv6_hdr() and the current group record and read the record
count from the report header inside the record loop, across the
*_mc_may_pull() calls.
amt_update_handler() caches ip_hdr() and the AMT membership-update
header before pskb_may_pull(), iptunnel_pull_header(),
ip_mc_check_igmp() and the report handler, then reads iph->daddr and
amtmu->nonce / amtmu->response_mac.
Fix each site by either snapshotting the scalar that is used after the
pull before the first pull runs, or re-deriving the header pointer from
the skb after the last pull that can move the head. Values that are
stable across the pull (source and group address, the response MAC and
nonce, the record count, the outer source MAC) are snapshotted; pointers
that are written through or read repeatedly are re-derived.
Fixes: cbc21dc1cfe9 ("amt: add data plane of amt interface")
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Reviewed-by: Taehee Yoo <ap420073@gmail.com>
Link: https://patch.msgid.link/20260711151934.2955226-2-michael.bommarito@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/amt.c | 79 +++++++++++++++++++++++++++++++++--------------
1 file changed, 55 insertions(+), 24 deletions(-)
diff --git a/drivers/net/amt.c b/drivers/net/amt.c
index ef6848c2e60841..062798fb8aa655 100644
--- a/drivers/net/amt.c
+++ b/drivers/net/amt.c
@@ -1206,7 +1206,7 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev)
data = true;
}
v6 = false;
- group.ip4 = iph->daddr;
+ group.ip4 = ip_hdr(skb)->daddr;
#if IS_ENABLED(CONFIG_IPV6)
} else if (iph->version == 6) {
ip6h = ipv6_hdr(skb);
@@ -1230,7 +1230,7 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev)
data = true;
}
v6 = true;
- group.ip6 = ip6h->daddr;
+ group.ip6 = ipv6_hdr(skb)->daddr;
#endif
} else {
dev->stats.tx_errors++;
@@ -1273,12 +1273,12 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev)
hlist_for_each_entry_rcu(gnode, &tunnel->groups[hash],
node) {
if (!v6) {
- if (gnode->group_addr.ip4 == iph->daddr)
+ if (gnode->group_addr.ip4 == group.ip4)
goto found;
#if IS_ENABLED(CONFIG_IPV6)
} else {
if (ipv6_addr_equal(&gnode->group_addr.ip6,
- &ip6h->daddr))
+ &group.ip6))
goto found;
#endif
}
@@ -1995,14 +1995,18 @@ static void amt_igmpv3_report_handler(struct amt_dev *amt, struct sk_buff *skb,
struct igmpv3_report *ihrv3 = igmpv3_report_hdr(skb);
int len = skb_transport_offset(skb) + sizeof(*ihrv3);
void *zero_grec = (void *)&igmpv3_zero_grec;
- struct iphdr *iph = ip_hdr(skb);
struct amt_group_node *gnode;
union amt_addr group, host;
struct igmpv3_grec *grec;
+ __be32 saddr;
u16 nsrcs;
+ u16 ngrec;
int i;
- for (i = 0; i < ntohs(ihrv3->ngrec); i++) {
+ saddr = ip_hdr(skb)->saddr;
+ ngrec = ntohs(ihrv3->ngrec);
+
+ for (i = 0; i < ngrec; i++) {
len += sizeof(*grec);
if (!ip_mc_may_pull(skb, len))
break;
@@ -2014,10 +2018,13 @@ static void amt_igmpv3_report_handler(struct amt_dev *amt, struct sk_buff *skb,
if (!ip_mc_may_pull(skb, len))
break;
+ grec = (void *)(skb->data + len - sizeof(*grec) -
+ nsrcs * sizeof(__be32));
+
memset(&group, 0, sizeof(union amt_addr));
group.ip4 = grec->grec_mca;
memset(&host, 0, sizeof(union amt_addr));
- host.ip4 = iph->saddr;
+ host.ip4 = saddr;
gnode = amt_lookup_group(tunnel, &group, &host, false);
if (!gnode) {
gnode = amt_add_group(amt, tunnel, &group, &host,
@@ -2157,14 +2164,18 @@ static void amt_mldv2_report_handler(struct amt_dev *amt, struct sk_buff *skb,
struct mld2_report *mld2r = (struct mld2_report *)icmp6_hdr(skb);
int len = skb_transport_offset(skb) + sizeof(*mld2r);
void *zero_grec = (void *)&mldv2_zero_grec;
- struct ipv6hdr *ip6h = ipv6_hdr(skb);
struct amt_group_node *gnode;
union amt_addr group, host;
struct mld2_grec *grec;
+ struct in6_addr saddr;
u16 nsrcs;
+ u16 ngrec;
int i;
- for (i = 0; i < ntohs(mld2r->mld2r_ngrec); i++) {
+ saddr = ipv6_hdr(skb)->saddr;
+ ngrec = ntohs(mld2r->mld2r_ngrec);
+
+ for (i = 0; i < ngrec; i++) {
len += sizeof(*grec);
if (!ipv6_mc_may_pull(skb, len))
break;
@@ -2176,10 +2187,13 @@ static void amt_mldv2_report_handler(struct amt_dev *amt, struct sk_buff *skb,
if (!ipv6_mc_may_pull(skb, len))
break;
+ grec = (void *)(skb->data + len - sizeof(*grec) -
+ nsrcs * sizeof(struct in6_addr));
+
memset(&group, 0, sizeof(union amt_addr));
group.ip6 = grec->grec_mca;
memset(&host, 0, sizeof(union amt_addr));
- host.ip6 = ip6h->saddr;
+ host.ip6 = saddr;
gnode = amt_lookup_group(tunnel, &group, &host, true);
if (!gnode) {
gnode = amt_add_group(amt, tunnel, &group, &host,
@@ -2300,7 +2314,6 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb)
skb_push(skb, sizeof(*eth));
skb_reset_mac_header(skb);
skb_pull(skb, sizeof(*eth));
- eth = eth_hdr(skb);
if (!pskb_may_pull(skb, sizeof(*iph)))
return true;
@@ -2310,6 +2323,7 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb)
if (!ipv4_is_multicast(iph->daddr))
return true;
skb->protocol = htons(ETH_P_IP);
+ eth = eth_hdr(skb);
eth->h_proto = htons(ETH_P_IP);
ip_eth_mc_map(iph->daddr, eth->h_dest);
#if IS_ENABLED(CONFIG_IPV6)
@@ -2323,6 +2337,7 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb)
if (!ipv6_addr_is_multicast(&ip6h->daddr))
return true;
skb->protocol = htons(ETH_P_IPV6);
+ eth = eth_hdr(skb);
eth->h_proto = htons(ETH_P_IPV6);
ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest);
#endif
@@ -2346,10 +2361,12 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
struct sk_buff *skb)
{
struct amt_header_membership_query *amtmq;
- struct igmpv3_query *ihv3;
struct ethhdr *eth, *oeth;
+ struct igmpv3_query *ihv3;
+ u8 h_source[ETH_ALEN];
struct iphdr *iph;
int hdr_size, len;
+ u64 response_mac;
hdr_size = sizeof(*amtmq) + sizeof(struct udphdr);
if (!pskb_may_pull(skb, hdr_size))
@@ -2362,6 +2379,8 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
if (amtmq->nonce != amt->nonce)
return true;
+ response_mac = amtmq->response_mac;
+
hdr_size -= sizeof(*eth);
if (iptunnel_pull_header(skb, hdr_size, htons(ETH_P_TEB), false))
return true;
@@ -2371,6 +2390,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
skb_pull(skb, sizeof(*eth));
skb_reset_network_header(skb);
eth = eth_hdr(skb);
+ ether_addr_copy(h_source, oeth->h_source);
if (!pskb_may_pull(skb, sizeof(*iph)))
return true;
@@ -2383,6 +2403,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
sizeof(*ihv3)))
return true;
+ iph = ip_hdr(skb);
if (!ipv4_is_multicast(iph->daddr))
return true;
@@ -2390,10 +2411,11 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
skb_reset_transport_header(skb);
skb_push(skb, sizeof(*iph) + AMT_IPHDR_OPTS);
WRITE_ONCE(amt->ready4, true);
- amt->mac = amtmq->response_mac;
+ amt->mac = response_mac;
amt->req_cnt = 0;
amt->qi = ihv3->qqic;
skb->protocol = htons(ETH_P_IP);
+ eth = eth_hdr(skb);
eth->h_proto = htons(ETH_P_IP);
ip_eth_mc_map(iph->daddr, eth->h_dest);
#if IS_ENABLED(CONFIG_IPV6)
@@ -2416,10 +2438,11 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
skb_reset_transport_header(skb);
skb_push(skb, sizeof(*ip6h) + AMT_IP6HDR_OPTS);
WRITE_ONCE(amt->ready6, true);
- amt->mac = amtmq->response_mac;
+ amt->mac = response_mac;
amt->req_cnt = 0;
amt->qi = mld2q->mld2q_qqic;
skb->protocol = htons(ETH_P_IPV6);
+ eth = eth_hdr(skb);
eth->h_proto = htons(ETH_P_IPV6);
ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest);
#endif
@@ -2427,7 +2450,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
return true;
}
- ether_addr_copy(eth->h_source, oeth->h_source);
+ ether_addr_copy(eth->h_source, h_source);
skb->pkt_type = PACKET_MULTICAST;
skb->ip_summed = CHECKSUM_NONE;
len = skb->len;
@@ -2450,8 +2473,11 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)
struct ethhdr *eth;
struct iphdr *iph;
int len, hdr_size;
+ u64 response_mac;
+ __be32 saddr;
+ __be32 nonce;
- iph = ip_hdr(skb);
+ saddr = ip_hdr(skb)->saddr;
hdr_size = sizeof(*amtmu) + sizeof(struct udphdr);
if (!pskb_may_pull(skb, hdr_size))
@@ -2461,15 +2487,18 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)
if (amtmu->reserved || amtmu->version)
return true;
+ nonce = amtmu->nonce;
+ response_mac = amtmu->response_mac;
+
if (iptunnel_pull_header(skb, hdr_size, skb->protocol, false))
return true;
skb_reset_network_header(skb);
list_for_each_entry_rcu(tunnel, &amt->tunnel_list, list) {
- if (tunnel->ip4 == iph->saddr) {
- if ((amtmu->nonce == tunnel->nonce &&
- amtmu->response_mac == tunnel->mac)) {
+ if (tunnel->ip4 == saddr) {
+ if ((nonce == tunnel->nonce &&
+ response_mac == tunnel->mac)) {
mod_delayed_work(amt_wq, &tunnel->gc_wq,
msecs_to_jiffies(amt_gmi(amt))
* 3);
@@ -2503,6 +2532,7 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)
eth = eth_hdr(skb);
skb->protocol = htons(ETH_P_IP);
eth->h_proto = htons(ETH_P_IP);
+ iph = ip_hdr(skb);
ip_eth_mc_map(iph->daddr, eth->h_dest);
#if IS_ENABLED(CONFIG_IPV6)
} else if (iph->version == 6) {
@@ -2522,6 +2552,7 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)
eth = eth_hdr(skb);
skb->protocol = htons(ETH_P_IPV6);
eth->h_proto = htons(ETH_P_IPV6);
+ ip6h = ipv6_hdr(skb);
ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest);
#endif
} else {
@@ -2767,7 +2798,7 @@ static void amt_gw_rcv(struct amt_dev *amt, struct sk_buff *skb)
static int amt_rcv(struct sock *sk, struct sk_buff *skb)
{
struct amt_dev *amt;
- struct iphdr *iph;
+ __be32 saddr;
int type;
bool err;
@@ -2780,7 +2811,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb)
}
skb->dev = amt->dev;
- iph = ip_hdr(skb);
+ saddr = ip_hdr(skb)->saddr;
type = amt_parse_type(skb);
if (type == -1) {
err = true;
@@ -2790,7 +2821,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb)
if (amt->mode == AMT_MODE_GATEWAY) {
switch (type) {
case AMT_MSG_ADVERTISEMENT:
- if (iph->saddr != amt->discovery_ip) {
+ if (saddr != amt->discovery_ip) {
netdev_dbg(amt->dev, "Invalid Relay IP\n");
err = true;
goto drop;
@@ -2802,7 +2833,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb)
}
goto out;
case AMT_MSG_MULTICAST_DATA:
- if (iph->saddr != amt->remote_ip) {
+ if (saddr != amt->remote_ip) {
netdev_dbg(amt->dev, "Invalid Relay IP\n");
err = true;
goto drop;
@@ -2813,7 +2844,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb)
else
goto out;
case AMT_MSG_MEMBERSHIP_QUERY:
- if (iph->saddr != amt->remote_ip) {
+ if (saddr != amt->remote_ip) {
netdev_dbg(amt->dev, "Invalid Relay IP\n");
err = true;
goto drop;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 215/602] amt: make the head writable before rewriting the L2 header
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (213 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 214/602] amt: re-read skb header pointers after every pull Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 216/602] net: bridge: vlan: fix vlan range dumps starting with pvid Greg Kroah-Hartman
` (390 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Michael Bommarito, Simon Horman,
Taehee Yoo, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <michael.bommarito@gmail.com>
[ Upstream commit 53969d704fa5b7c1751e277fac96bfc22b435eac ]
amt_multicast_data_handler(), amt_membership_query_handler() and
amt_update_handler() rewrite the ethernet header of the decapsulated skb
in place (eth->h_proto, eth->h_dest and, for the query, also
eth->h_source) before handing it up the stack. The skb head may be
shared, for example when a packet tap has cloned it on the underlay
interface, so writing through it corrupts the other reader's copy.
Call skb_cow_head() before the rewrite so the head is private. It is
placed before the pointers into the head are (re-)derived, so a
reallocation caused by the copy is picked up by those derivations.
Fixes: cbc21dc1cfe9 ("amt: add data plane of amt interface")
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Reviewed-by: Taehee Yoo <ap420073@gmail.com>
Link: https://patch.msgid.link/20260711151934.2955226-3-michael.bommarito@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/amt.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/net/amt.c b/drivers/net/amt.c
index 062798fb8aa655..77d6c443d81bf6 100644
--- a/drivers/net/amt.c
+++ b/drivers/net/amt.c
@@ -2315,6 +2315,9 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb)
skb_reset_mac_header(skb);
skb_pull(skb, sizeof(*eth));
+ if (skb_cow_head(skb, 0))
+ return true;
+
if (!pskb_may_pull(skb, sizeof(*iph)))
return true;
iph = ip_hdr(skb);
@@ -2391,6 +2394,8 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
skb_reset_network_header(skb);
eth = eth_hdr(skb);
ether_addr_copy(h_source, oeth->h_source);
+ if (skb_cow_head(skb, 0))
+ return true;
if (!pskb_may_pull(skb, sizeof(*iph)))
return true;
@@ -2516,6 +2521,9 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)
if (!pskb_may_pull(skb, sizeof(*iph)))
return true;
+ if (skb_cow_head(skb, 0))
+ return true;
+
iph = ip_hdr(skb);
if (iph->version == 4) {
if (ip_mc_check_igmp(skb)) {
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 216/602] net: bridge: vlan: fix vlan range dumps starting with pvid
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (214 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 215/602] amt: make the head writable before rewriting the L2 header Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 217/602] net: hsr: fix memory leak on slave unregistration by removing synced VLANs Greg Kroah-Hartman
` (389 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Nikolay Aleksandrov, Ido Schimmel,
Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikolay Aleksandrov <razor@blackwall.org>
[ Upstream commit 43171c97e4714bf601b468401b37732244639c21 ]
There is a bug in all range dumps that rely on br_vlan_can_enter_range()
when the PVID is a range starting VLAN, all following VLANs that match
its flags can enter the range, but when the range is filled in only the
PVID VLAN is dumped and the rest of the range is discarded because
br_vlan_fill_vids() checks for the PVID flag. Since the PVID VLAN can
be only one, we need to break ranges around it, the best way to do that
consistently for all is to alter br_vlan_can_enter_range() to take into
account the PVID and return false to break the range when it's matched.
Before the fix:
$ ip l add br0 type bridge vlan_filtering 1
$ ip l add dumdum type dummy
$ ip l set dumdum master br0
$ ip l set br0 up
$ ip l set dumdum up
$ bridge vlan add dev dumdum vid 1 pvid untagged master
$ bridge vlan add dev dumdum vid 2 untagged master
$ bridge vlan show dev dumdum # use legacy dump to show all vlans
port vlan-id
dumdum 1 PVID Egress Untagged
2 Egress Untagged
$ bridge -d vlan show dev dumdum # use the new dump (RTM_GETVLAN)
port vlan-id
dumdum 1 PVID Egress Untagged
state forwarding mcast_router 1
VLAN 2 is missing, and if there are more matching VLANs afterwards
they'd be missing too.
After the fix:
[ same setup steps ]
$ bridge vlan show dev dumdum
port vlan-id
dumdum 1 PVID Egress Untagged
2 Egress Untagged
$ bridge -d vlan show dev dumdum # use the new dump (RTM_GETVLAN)
port vlan-id
dumdum 1 PVID Egress Untagged
state forwarding mcast_router 1
2 Egress Untagged
state forwarding mcast_router 1
Fixes: 0ab558795184 ("net: bridge: vlan: add rtm range support")
Signed-off-by: Nikolay Aleksandrov <razor@blackwall.org>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20260721140922.682265-2-razor@blackwall.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/bridge/br_netlink_tunnel.c | 3 ++-
net/bridge/br_private.h | 6 ++++--
net/bridge/br_vlan.c | 10 ++++++----
net/bridge/br_vlan_options.c | 3 +--
4 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/net/bridge/br_netlink_tunnel.c b/net/bridge/br_netlink_tunnel.c
index 71a12da30004c7..a713668ea34f0e 100644
--- a/net/bridge/br_netlink_tunnel.c
+++ b/net/bridge/br_netlink_tunnel.c
@@ -271,7 +271,8 @@ static void __vlan_tunnel_handle_range(const struct net_bridge_port *p,
if (!*v_start)
goto out_init;
- if (v && curr_change && br_vlan_can_enter_range(v, *v_end)) {
+ if (v && curr_change &&
+ br_vlan_can_enter_range(v, *v_end, br_get_pvid(vg))) {
*v_end = v;
return;
}
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index b2e4e2d04f02b8..3854ea1a515470 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -1587,7 +1587,8 @@ void br_vlan_notify(const struct net_bridge *br,
u16 vid, u16 vid_range,
int cmd);
bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr,
- const struct net_bridge_vlan *range_end);
+ const struct net_bridge_vlan *range_end,
+ u16 pvid);
void br_vlan_fill_forward_path_pvid(struct net_bridge *br,
struct net_device_path_ctx *ctx,
@@ -1828,7 +1829,8 @@ static inline void br_vlan_notify(const struct net_bridge *br,
}
static inline bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr,
- const struct net_bridge_vlan *range_end)
+ const struct net_bridge_vlan *range_end,
+ u16 pvid)
{
return true;
}
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index 13d6c3f51c29d0..1aa38303529487 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -1943,9 +1943,11 @@ void br_vlan_notify(const struct net_bridge *br,
/* check if v_curr can enter a range ending in range_end */
bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr,
- const struct net_bridge_vlan *range_end)
+ const struct net_bridge_vlan *range_end,
+ u16 pvid)
{
- return v_curr->vid - range_end->vid == 1 &&
+ return v_curr->vid != pvid && range_end->vid != pvid &&
+ v_curr->vid - range_end->vid == 1 &&
range_end->flags == v_curr->flags &&
br_vlan_opts_eq_range(v_curr, range_end);
}
@@ -2027,8 +2029,8 @@ static int br_vlan_dump_dev(const struct net_device *dev,
idx += range_end->vid - range_start->vid + 1;
range_start = v;
- } else if (dump_stats || v->vid == pvid ||
- !br_vlan_can_enter_range(v, range_end)) {
+ } else if (dump_stats ||
+ !br_vlan_can_enter_range(v, range_end, pvid)) {
u16 vlan_flags = br_vlan_flags(range_start, pvid);
if (!br_vlan_fill_vids(skb, range_start->vid,
diff --git a/net/bridge/br_vlan_options.c b/net/bridge/br_vlan_options.c
index 8fa89b04ee942d..4a736e005bad7e 100644
--- a/net/bridge/br_vlan_options.c
+++ b/net/bridge/br_vlan_options.c
@@ -310,8 +310,7 @@ int br_vlan_process_options(const struct net_bridge *br,
continue;
}
- if (v->vid == pvid ||
- !br_vlan_can_enter_range(v, curr_end)) {
+ if (!br_vlan_can_enter_range(v, curr_end, pvid)) {
br_vlan_notify(br, p, curr_start->vid,
curr_end->vid, RTM_NEWVLAN);
curr_start = v;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 217/602] net: hsr: fix memory leak on slave unregistration by removing synced VLANs
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (215 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 216/602] net: bridge: vlan: fix vlan range dumps starting with pvid Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 218/602] net: dpaa: fix mode setting Greg Kroah-Hartman
` (388 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, syzbot+456957213f32970c0762,
Eric Dumazet, Fernando Fernandez Mancera, Felix Maurer,
Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <edumazet@google.com>
[ Upstream commit dcf15eaf5641812f1cfc5e96537380132a7da89d ]
When an HSR master device is brought UP, it auto-adds VLAN 0 via
vlan_vid0_add(), which propagates VID 0 to its slave devices (slave A and B).
If a slave device is later unregistered while HSR is active (e.g., during
netns cleanup or interface destruction), hsr_del_port() is called to
detach the slave port from the HSR master. However, hsr_del_port() currently
does not delete the VLAN IDs that were synced to the slave device by HSR.
As a result, the slave device retains a refcount on VID 0 (and any other
synced VLANs). When the slave device is destroyed, its vlan_info /
vlan_vid_info structure remains allocated, leading to a memory leak.
Fix this by calling vlan_vids_del_by_dev(port->dev, master->dev) in
hsr_del_port() before unlinking slave A or slave B ports, matching the
propagation logic in hsr_ndo_vlan_rx_add_vid() / hsr_ndo_vlan_rx_kill_vid()
and the cleanup behavior in bonding and team drivers.
Fixes: 1a8a63a5305e ("net: hsr: Add VLAN CTAG filter support")
Reported-by: syzbot+456957213f32970c0762@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/netdev/6a4cb6ca.57639fcc.86d58.000b.GAE@google.com/T/#u
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
Reviewed-by: Felix Maurer <fmaurer@redhat.com>
Link: https://patch.msgid.link/20260721101240.995597-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/hsr/hsr_slave.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c
index 70472726c60494..ffc72597295273 100644
--- a/net/hsr/hsr_slave.c
+++ b/net/hsr/hsr_slave.c
@@ -238,6 +238,8 @@ void hsr_del_port(struct hsr_port *port)
netdev_rx_handler_unregister(port->dev);
if (!port->hsr->fwd_offloaded)
dev_set_promiscuity(port->dev, -1);
+ if (port->type == HSR_PT_SLAVE_A || port->type == HSR_PT_SLAVE_B)
+ vlan_vids_del_by_dev(port->dev, master->dev);
netdev_upper_dev_unlink(port->dev, master->dev);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 218/602] net: dpaa: fix mode setting
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (216 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 217/602] net: hsr: fix memory leak on slave unregistration by removing synced VLANs Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 219/602] sctp: auth: verify auth requirement when auth_chunk is NULL Greg Kroah-Hartman
` (387 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sean Anderson, Michael Walle,
Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Walle <mwalle@kernel.org>
[ Upstream commit da2c6bcc5e30b1496ac587785dcacf6e849eb6ef ]
Before converting to the phylink interface, the init function would have
set a non-reserved I/F mode in the maccfg2 register. After converting to
phylink, 0 is written as mode, which is a reserved value (although it's
the hardware default). Without a valid mode, a SGMII link is never
established between the MAC and the PHY and thus .link_up() is never
called which could set the correct mode according to the actual speed.
Fix it by setting the maximum speed of the phy_interface_t in use in
.mac_config() - just like the driver did before the phylink conversion.
Fixes: 5d93cfcf7360 ("net: dpaa: Convert to phylink")
Suggested-by: Sean Anderson <sean.anderson@linux.dev>
Signed-off-by: Michael Walle <mwalle@kernel.org>
Reviewed-by: Sean Anderson <sean.anderson@linux.dev>
Reviewed-by: Sean Anderson <sean.anderson@linux.dev>
Link: https://patch.msgid.link/20260717132401.2653252-1-mwalle@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
.../net/ethernet/freescale/fman/fman_dtsec.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
index 3088da7adf0f84..074ca626a51508 100644
--- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c
+++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c
@@ -900,22 +900,28 @@ static void dtsec_mac_config(struct phylink_config *config, unsigned int mode,
{
struct mac_device *mac_dev = fman_config_to_mac(config);
struct dtsec_regs __iomem *regs = mac_dev->fman_mac->regs;
- u32 tmp;
+ u32 ecntrl, maccfg2;
+
+ maccfg2 = ioread32be(®s->maccfg2);
+ maccfg2 &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE);
switch (state->interface) {
case PHY_INTERFACE_MODE_RMII:
- tmp = DTSEC_ECNTRL_RMM;
+ ecntrl = DTSEC_ECNTRL_RMM;
+ maccfg2 |= MACCFG2_NIBBLE_MODE;
break;
case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_TXID:
- tmp = DTSEC_ECNTRL_GMIIM | DTSEC_ECNTRL_RPM;
+ ecntrl = DTSEC_ECNTRL_GMIIM | DTSEC_ECNTRL_RPM;
+ maccfg2 |= MACCFG2_BYTE_MODE;
break;
case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_1000BASEX:
case PHY_INTERFACE_MODE_2500BASEX:
- tmp = DTSEC_ECNTRL_TBIM | DTSEC_ECNTRL_SGMIIM;
+ ecntrl = DTSEC_ECNTRL_TBIM | DTSEC_ECNTRL_SGMIIM;
+ maccfg2 |= MACCFG2_BYTE_MODE;
break;
default:
dev_warn(mac_dev->dev, "cannot configure dTSEC for %s\n",
@@ -923,7 +929,8 @@ static void dtsec_mac_config(struct phylink_config *config, unsigned int mode,
return;
}
- iowrite32be(tmp, ®s->ecntrl);
+ iowrite32be(ecntrl, ®s->ecntrl);
+ iowrite32be(maccfg2, ®s->maccfg2);
}
static void dtsec_link_up(struct phylink_config *config, struct phy_device *phy,
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 219/602] sctp: auth: verify auth requirement when auth_chunk is NULL
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (217 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 218/602] net: dpaa: fix mode setting Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 220/602] vmxnet3: fix BUG_ON in vmxnet3_get_hdr_len() for Geneve packets Greg Kroah-Hartman
` (386 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Qing Luo, Xin Long, Jakub Kicinski,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qing Luo <luoqing@kylinos.cn>
[ Upstream commit 8e04823c120b376ef7dab14b60ebf6823aa16c14 ]
sctp_auth_chunk_verify() returns true unconditionally when
chunk->auth_chunk is NULL, silently skipping authentication.
This is incorrect when:
1. skb_clone() failed in the BH receive path, leaving auth_chunk
NULL. In sctp_endpoint_bh_rcv() asoc is NULL for new
connections, so the early sctp_auth_recv_cid() check cannot
catch this.
2. No AUTH chunk precedes COOKIE-ECHO, so skb_clone() is never
called and auth_chunk remains NULL.
Fix by checking sctp_auth_recv_cid() when auth_chunk is NULL:
if authentication is required, return false to drop the chunk;
otherwise continue normally.
Fixes: bbd0d59809f9 ("[SCTP]: Implement the receive and verification of AUTH chunk")
Signed-off-by: Qing Luo <luoqing@kylinos.cn>
Acked-by: Xin Long <lucien.xin@gmail.com>
Link: https://patch.msgid.link/20260721015532.120157-2-l1138897701@163.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/sctp/sm_statefuns.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 96e92719ff4df3..818878f484a795 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -641,7 +641,7 @@ static bool sctp_auth_chunk_verify(struct net *net, struct sctp_chunk *chunk,
struct sctp_chunk auth;
if (!chunk->auth_chunk)
- return true;
+ return !sctp_auth_recv_cid(chunk->chunk_hdr->type, asoc);
/* SCTP-AUTH: auth_chunk pointer is only set when the cookie-echo
* is supposed to be authenticated and we have to do delayed
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 220/602] vmxnet3: fix BUG_ON in vmxnet3_get_hdr_len() for Geneve packets
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (218 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 219/602] sctp: auth: verify auth requirement when auth_chunk is NULL Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 221/602] iomap: correct the range of a partial dirty clear Greg Kroah-Hartman
` (385 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Harshaka Narayana, Ronak Doshi,
Sankararaman Jayaraman, Simon Horman, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Harshaka Narayana <harshaka.narayana@broadcom.com>
[ Upstream commit 34a71f5361fc3adb5b7138da78750b0d535a8252 ]
vmxnet3_get_hdr_len() assumes gdesc->rcd.v4/v6/tcp always describe the
outer header, but for a Geneve-encapsulated packet the device can set
them based on the inner header instead, signalled by the
VMXNET3_RCD_HDR_INNER_SHIFT bit in the completion descriptor. Since the
function never skips the outer encapsulation, this mismatch triggers:
- BUG_ON(hdr.ipv4->protocol != IPPROTO_TCP), because the outer
protocol is UDP (Geneve), not TCP.
- BUG_ON(hdr.eth->h_proto != ...), when the tunnel's outer and inner
IP versions differ (e.g. outer IPv6/inner IPv4 or vice versa).
Check VMXNET3_RCD_HDR_INNER_SHIFT up front and bail out, since the
function cannot locate the inner header it would need to parse. Also
convert the remaining BUG_ON()s in this function to return 0
defensively.
Fixes: 45dac1d6ea04 ("vmxnet3: Changes for vmxnet3 adapter version 2 (fwd)")
Signed-off-by: Harshaka Narayana <harshaka.narayana@broadcom.com>
Reviewed-by: Ronak Doshi <ronak.doshi@broadcom.com>
Reviewed-by: Sankararaman Jayaraman <sankararaman.jayaraman@broadcom.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260713140915.3381715-1-harshaka.narayana@broadcom.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/vmxnet3/vmxnet3_drv.c | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index e1e472b3a301ef..538738231a5a95 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -1518,7 +1518,11 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb,
struct ipv6hdr *ipv6;
struct tcphdr *tcp;
} hdr;
- BUG_ON(gdesc->rcd.tcp == 0);
+
+ /* v4/v6/tcp then describe the inner header, which we can't locate. */
+ if ((le32_to_cpu(gdesc->dword[0]) & (1UL << VMXNET3_RCD_HDR_INNER_SHIFT)) ||
+ gdesc->rcd.tcp == 0)
+ return 0;
maplen = skb_headlen(skb);
if (unlikely(sizeof(struct iphdr) + sizeof(struct tcphdr) > maplen))
@@ -1532,15 +1536,21 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb,
hdr.eth = eth_hdr(skb);
if (gdesc->rcd.v4) {
- BUG_ON(hdr.eth->h_proto != htons(ETH_P_IP) &&
- hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IP));
+ if (hdr.eth->h_proto != htons(ETH_P_IP) &&
+ hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IP))
+ return 0;
+
hdr.ptr += hlen;
- BUG_ON(hdr.ipv4->protocol != IPPROTO_TCP);
+ if (hdr.ipv4->protocol != IPPROTO_TCP)
+ return 0;
+
hlen = hdr.ipv4->ihl << 2;
hdr.ptr += hdr.ipv4->ihl << 2;
} else if (gdesc->rcd.v6) {
- BUG_ON(hdr.eth->h_proto != htons(ETH_P_IPV6) &&
- hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IPV6));
+ if (hdr.eth->h_proto != htons(ETH_P_IPV6) &&
+ hdr.veth->h_vlan_encapsulated_proto != htons(ETH_P_IPV6))
+ return 0;
+
hdr.ptr += hlen;
/* Use an estimated value, since we also need to handle
* TSO case.
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 221/602] iomap: correct the range of a partial dirty clear
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (219 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 220/602] vmxnet3: fix BUG_ON in vmxnet3_get_hdr_len() for Geneve packets Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 222/602] tipc: fix u16 MTU truncation in media and bearer MTU validation Greg Kroah-Hartman
` (384 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Zhang Yi, Joanne Koong,
Darrick J. Wong, Christoph Hellwig, Christian Brauner (Amutable),
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Yi <yi.zhang@huawei.com>
[ Upstream commit 88c26515313169806a412a362b32a1eca53d21bd ]
The block range calculation in ifs_clear_range_dirty() is incorrect when
partially clearing a range in a folio. We cannot clear the dirty bit of
the first block or the last block if the start or end offset is not
blocksize-aligned. This has not yet caused any issues since we always
clear a whole folio in iomap_writeback_folio().
Fix this by rounding up the first block to blocksize alignment, and
calculate the last block by rounding down (using truncation). Correct
the nr_blks calculation accordingly.
Fixes: 4ce02c679722 ("iomap: Add per-block dirty state tracking to improve performance")
Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
Link: https://patch.msgid.link/20260714082325.325163-2-yi.zhang@huaweicloud.com
Reviewed-by: Joanne Koong <joannelkoong@gmail.com>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/iomap/buffered-io.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index 5f885286b2f4a0..44f5c9889cefcb 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -137,13 +137,17 @@ static void ifs_clear_range_dirty(struct folio *folio,
{
struct inode *inode = folio->mapping->host;
unsigned int blks_per_folio = i_blocks_per_folio(inode, folio);
- unsigned int first_blk = (off >> inode->i_blkbits);
- unsigned int last_blk = (off + len - 1) >> inode->i_blkbits;
- unsigned int nr_blks = last_blk - first_blk + 1;
+ unsigned int first_blk = round_up(off, i_blocksize(inode)) >>
+ inode->i_blkbits;
+ unsigned int last_blk = (off + len) >> inode->i_blkbits;
unsigned long flags;
+ if (first_blk >= last_blk)
+ return;
+
spin_lock_irqsave(&ifs->state_lock, flags);
- bitmap_clear(ifs->state, first_blk + blks_per_folio, nr_blks);
+ bitmap_clear(ifs->state, first_blk + blks_per_folio,
+ last_blk - first_blk);
spin_unlock_irqrestore(&ifs->state_lock, flags);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 222/602] tipc: fix u16 MTU truncation in media and bearer MTU validation
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (220 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 221/602] iomap: correct the range of a partial dirty clear Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 223/602] drm/tests: shmem: Set DMA mask to 64-bit in drm_gem_shmem Greg Kroah-Hartman
` (383 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, AutonomousCodeSecurity,
Vadim Fedorenko, Cen Zhang (Microsoft), Simon Horman, Paolo Abeni,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cen Zhang (Microsoft) <blbllhy@gmail.com>
[ Upstream commit 9f29cd8a8e7901a2617c8064ce9f50fc67b97cb8 ]
Both TIPC_NL_MEDIA_SET and TIPC_NL_BEARER_SET accept user-supplied
MTU values but only enforce a minimum bound, not a maximum. When a user
sets the MTU to a value exceeding U16_MAX (65535), it passes validation
but is silently truncated when assigned to u16 fields l->mtu and
l->advertised_mtu in tipc_link_create(). Values like 65536 (0x10000)
truncate to 0, causing a division by zero in tipc_link_set_queue_limits()
which computes TIPC_MAX_PUBL / (l->mtu / ITEM_SIZE). Other overflowing
values (e.g. 65537-131071) produce small incorrect MTU values, resulting
in link malfunction behaviors.
Crash stack (triggered as unprivileged user via user namespace):
tipc_link_set_queue_limits net/tipc/link.c:2531
tipc_link_create net/tipc/link.c:520
tipc_node_check_dest net/tipc/node.c:1279
tipc_disc_rcv net/tipc/discover.c:252
tipc_rcv net/tipc/node.c:2129
tipc_udp_recv net/tipc/udp_media.c:392
Two independent paths lack the upper bound check:
1. tipc_udp_mtu_bad() -- called from __tipc_nl_media_set() (MEDIA_SET)
2. inline check in __tipc_nl_bearer_set() at bearer.c:1160 (BEARER_SET)
Fix both by rejecting MTU values above U16_MAX.
Fixes: 901271e0403a ("tipc: implement configuration of UDP media MTU")
Reported-by: AutonomousCodeSecurity@microsoft.com
Closes: https://lore.kernel.org/all/CAB8m9WgETt0AjmFwE=F-CKjGXsK6_WDv0=kbYRcC8-noo+amnA@mail.gmail.com
Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Signed-off-by: Cen Zhang (Microsoft) <blbllhy@gmail.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260714041541.307702-1-blbllhy@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/tipc/netlink.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/net/tipc/netlink.c b/net/tipc/netlink.c
index 8336a9664703fe..1307dd1a961341 100644
--- a/net/tipc/netlink.c
+++ b/net/tipc/netlink.c
@@ -113,12 +113,16 @@ const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = {
};
/* Properties valid for media, bearer and link */
+static const struct netlink_range_validation tipc_nl_mtu_range = {
+ .max = U16_MAX,
+};
+
const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX + 1] = {
[TIPC_NLA_PROP_UNSPEC] = { .type = NLA_UNSPEC },
[TIPC_NLA_PROP_PRIO] = { .type = NLA_U32 },
[TIPC_NLA_PROP_TOL] = { .type = NLA_U32 },
[TIPC_NLA_PROP_WIN] = { .type = NLA_U32 },
- [TIPC_NLA_PROP_MTU] = { .type = NLA_U32 },
+ [TIPC_NLA_PROP_MTU] = NLA_POLICY_FULL_RANGE(NLA_U32, &tipc_nl_mtu_range),
[TIPC_NLA_PROP_BROADCAST] = { .type = NLA_U32 },
[TIPC_NLA_PROP_BROADCAST_RATIO] = { .type = NLA_U32 }
};
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 223/602] drm/tests: shmem: Set DMA mask to 64-bit in drm_gem_shmem
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (221 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 222/602] tipc: fix u16 MTU truncation in media and bearer MTU validation Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 224/602] net: stmmac: fix l3l4 filter rejecting unsupported offload requests Greg Kroah-Hartman
` (382 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Thomas Zimmermann,
José Expósito, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: José Expósito <jose.exposito@redhat.com>
[ Upstream commit b04a248cfa6cfa1e7dc9ce91cb1eb88b1a70dd69 ]
drm_gem_shmem_test_purge [1] and drm_gem_shmem_test_get_pages_sgt [2]
intermittently fail on ppc64le and s390x CI systems with a DMA address
overflow:
DMA addr 0x0000000100307000+4096 overflow (mask ffffffff, bus limit 0)
WARNING: kernel/dma/direct.h:114 dma_direct_map_sg+0x778/0x920
drm_gem_shmem_test_purge: ASSERTION FAILED at
drivers/gpu/drm/tests/drm_gem_shmem_test.c:330
Expected sgt is not error, but is: -5
The call chain leading to the failure is:
drm_gem_shmem_test_purge() / drm_gem_shmem_test_get_pages_sgt()
drm_gem_shmem_get_pages_sgt()
drm_gem_shmem_get_pages_sgt_locked() [drm_gem_shmem_helper.c]
dma_map_sgtable() [mapping.c]
__dma_map_sg_attrs()
dma_direct_map_sg() [direct.c]
dma_direct_map_phys() [kernel/dma/direct.h]
dma_capable() Checks addr against DMA mask
-> FAILS: addr > 0xFFFFFFFF
The root cause is that KUnit devices are initialized with a 32-bit DMA
mask (DMA_BIT_MASK(32)) in lib/kunit/device.c. On ppc64le and s390x
systems with physical memory above 4GB, page allocations can land at
addresses that exceed this mask. When drm_gem_shmem_get_pages_sgt()
attempts to DMA-map these pages via dma_map_sgtable(), the DMA layer
rejects the mapping because the physical address overflows the 32-bit
mask.
The failure is intermittent because pages may or may not be allocated
above 4GB on any given run depend on memory pressure.
Fix by setting a 64-bit DMA mask on the device before calling
drm_gem_shmem_get_pages_sgt() for all tests, following the same pattern
already used in drm_gem_shmem_test_obj_create_private().
[1] https://s3.amazonaws.com/arr-cki-prod-trusted-artifacts/trusted-artifacts/2643976103/test_s390x/15128551935/artifacts/jobwatch/logs/recipes/21561049/tasks/220716793/results/1014626315/logs/dmesg.log
[2] https://s3.amazonaws.com/arr-cki-prod-trusted-artifacts/trusted-artifacts/2643976103/test_ppc64le/15128551933/artifacts/jobwatch/logs/recipes/21561041/tasks/220716705/results/1014628163/logs/dmesg.log
Fixes: 93032ae634d4 ("drm/test: add a test suite for GEM objects backed by shmem")
Closes: https://datawarehouse.cki-project.org/issue/5345
Closes: https://datawarehouse.cki-project.org/issue/3184
Assisted-by: Claude:claude-4.6-opus
Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
Signed-off-by: José Expósito <jose.exposito@redhat.com>
Link: https://patch.msgid.link/20260703150808.3832-1-jose.exposito89@gmail.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/tests/drm_gem_shmem_test.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/tests/drm_gem_shmem_test.c b/drivers/gpu/drm/tests/drm_gem_shmem_test.c
index 0c8c46ca158c06..cc40d63ab809e7 100644
--- a/drivers/gpu/drm/tests/drm_gem_shmem_test.c
+++ b/drivers/gpu/drm/tests/drm_gem_shmem_test.c
@@ -90,13 +90,9 @@ static void drm_gem_shmem_test_obj_create_private(struct kunit *test)
sg_init_one(sgt->sgl, buf, TEST_SIZE);
/*
- * Set the DMA mask to 64-bits and map the sgtables
- * otherwise drm_gem_shmem_free will cause a warning
- * on debug kernels.
+ * Map the sgtables otherwise drm_gem_shmem_free will cause a warning on
+ * debug kernels.
*/
- ret = dma_set_mask(drm_dev->dev, DMA_BIT_MASK(64));
- KUNIT_ASSERT_EQ(test, ret, 0);
-
ret = dma_map_sgtable(drm_dev->dev, sgt, DMA_BIDIRECTIONAL, 0);
KUNIT_ASSERT_EQ(test, ret, 0);
@@ -342,11 +338,19 @@ static int drm_gem_shmem_test_init(struct kunit *test)
{
struct device *dev;
struct drm_device *drm_dev;
+ int ret;
/* Allocate a parent device */
dev = drm_kunit_helper_alloc_device(test);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
+ /*
+ * Set the DMA mask to 64-bits to avoid intermittent failures calling
+ * drm_gem_shmem_get_pages_sgt().
+ */
+ ret = dma_set_mask(dev, DMA_BIT_MASK(64));
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
/*
* The DRM core will automatically initialize the GEM core and create
* a DRM Memory Manager object which provides an address space pool
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 224/602] net: stmmac: fix l3l4 filter rejecting unsupported offload requests
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (222 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 223/602] drm/tests: shmem: Set DMA mask to 64-bit in drm_gem_shmem Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 225/602] net: stmmac: reset residual action in L3L4 filters on delete Greg Kroah-Hartman
` (381 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Rohan G Thomas, Nazim Amirul,
Maxime Chevallier, Jakub Raczynski, Paolo Abeni, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@altera.com>
[ Upstream commit 5536d7c843637e9430279b94935fcf7df98babb3 ]
The basic flow parser in tc_add_basic_flow() does not validate match
keys before proceeding. Unsupported offload configurations such as
partial protocol masks, non-IPv4 network proto, or non-TCP/UDP transport
proto are silently accepted instead of returning -EOPNOTSUPP.
Add validation to return -EOPNOTSUPP early for:
- No network or transport proto present in the key
- Partial protocol mask (only full mask supported)
- Network proto is not IPv4
- Transport proto is not TCP or UDP
Each rejection includes an extack message so the user knows which part
of the match is unsupported.
Also propagate -EOPNOTSUPP from tc_add_basic_flow() in tc_add_flow()
by returning it directly rather than using break. The break was silently
discarding the error for FLOW_CLS_REPLACE operations where entry->in_use
is already true, causing tc_add_flow() to return 0 (success) for
unsupported replace requests.
Fixes: 425eabddaf0f ("net: stmmac: Implement L3/L4 Filters using TC Flower")
Signed-off-by: Rohan G Thomas <rohan.g.thomas@altera.com>
Signed-off-by: Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@altera.com>
Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Link: https://patch.msgid.link/20260714023716.29865-4-muhammad.nazim.amirul.nazle.asmade@altera.com
Reviewed-by: Jakub Raczynski <j.raczynski@samsung.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
.../net/ethernet/stmicro/stmmac/stmmac_tc.c | 34 +++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
index 75ad2da1a37f1a..f0874b20b0a2cd 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
@@ -446,6 +446,7 @@ static int tc_parse_flow_actions(struct stmmac_priv *priv,
}
#define ETHER_TYPE_FULL_MASK cpu_to_be16(~0)
+#define IP_PROTO_FULL_MASK 0xFF
static int tc_add_basic_flow(struct stmmac_priv *priv,
struct flow_cls_offload *cls,
@@ -461,6 +462,37 @@ static int tc_add_basic_flow(struct stmmac_priv *priv,
flow_rule_match_basic(rule, &match);
+ /* Both network proto and transport proto not present in the key */
+ if (!match.mask || !(match.mask->n_proto || match.mask->ip_proto)) {
+ NL_SET_ERR_MSG_MOD(cls->common.extack,
+ "filter must specify network or transport protocol");
+ return -EOPNOTSUPP;
+ }
+
+ /* If the proto is present in the key and is not full mask */
+ if ((match.mask->n_proto && match.mask->n_proto != ETHER_TYPE_FULL_MASK) ||
+ (match.mask->ip_proto && match.mask->ip_proto != IP_PROTO_FULL_MASK)) {
+ NL_SET_ERR_MSG_MOD(cls->common.extack,
+ "only full protocol mask is supported");
+ return -EOPNOTSUPP;
+ }
+
+ /* Network proto is present in the key and is not IPv4 */
+ if (match.mask->n_proto && match.key->n_proto != cpu_to_be16(ETH_P_IP)) {
+ NL_SET_ERR_MSG_MOD(cls->common.extack,
+ "only IPv4 network protocol is supported");
+ return -EOPNOTSUPP;
+ }
+
+ /* Transport proto is present in the key and is not TCP or UDP */
+ if (match.mask->ip_proto &&
+ match.key->ip_proto != IPPROTO_TCP &&
+ match.key->ip_proto != IPPROTO_UDP) {
+ NL_SET_ERR_MSG_MOD(cls->common.extack,
+ "only TCP and UDP transport protocols are supported");
+ return -EOPNOTSUPP;
+ }
+
entry->ip_proto = match.key->ip_proto;
return 0;
}
@@ -598,6 +630,8 @@ static int tc_add_flow(struct stmmac_priv *priv,
ret = tc_flow_parsers[i].fn(priv, cls, entry);
if (!ret)
entry->in_use = true;
+ else if (ret == -EOPNOTSUPP)
+ return ret;
}
if (!entry->in_use)
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 225/602] net: stmmac: reset residual action in L3L4 filters on delete
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (223 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 224/602] net: stmmac: fix l3l4 filter rejecting unsupported offload requests Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 226/602] net: stmmac: enable the MAC on link up for all supported speeds Greg Kroah-Hartman
` (380 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Rohan G Thomas, Nazim Amirul,
Maxime Chevallier, Jakub Raczynski, Paolo Abeni, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@altera.com>
[ Upstream commit a448f821289934b961dd9d8d0beb006cc8937ba2 ]
When deleting an L3/L4 flower filter entry, the action field is not
reset. If a filter was previously configured with a drop action, that
action may persist and affect subsequent filter configurations
unintentionally.
Clear the action field when the filter entry is deleted.
Fixes: 425eabddaf0f ("net: stmmac: Implement L3/L4 Filters using TC Flower")
Signed-off-by: Rohan G Thomas <rohan.g.thomas@altera.com>
Signed-off-by: Nazim Amirul <muhammad.nazim.amirul.nazle.asmade@altera.com>
Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Link: https://patch.msgid.link/20260714023716.29865-5-muhammad.nazim.amirul.nazle.asmade@altera.com
Reviewed-by: Jakub Raczynski <j.raczynski@samsung.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
index f0874b20b0a2cd..49f133dec810d8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
@@ -661,6 +661,7 @@ static int tc_del_flow(struct stmmac_priv *priv,
entry->in_use = false;
entry->cookie = 0;
entry->is_l4 = false;
+ entry->action = 0;
return ret;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 226/602] net: stmmac: enable the MAC on link up for all supported speeds
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (224 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 225/602] net: stmmac: reset residual action in L3L4 filters on delete Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 227/602] net: gre: fix lltx regression for GRE tunnels with SEQ/CSUM Greg Kroah-Hartman
` (379 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Maxime Chevallier, vadik likholetov,
Jacob Keller, Paolo Abeni, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: vadik likholetov <vadikas@gmail.com>
[ Upstream commit 9c99db3a2080b8c2cbbb1100369586a9bea43321 ]
stmmac_mac_link_down() clears the MAC's transmit and receive enable bits.
stmmac_mac_link_up() is expected to set them again through
stmmac_mac_set(..., true), but it first switches on the negotiated speed
and returns early for a speed the switch does not list. The MAC is then
left gated off.
The speed selection is split into three switches, keyed on the interface.
The generic branch -- taken for everything that is neither USXGMII nor
XLGMII, so including PHY_INTERFACE_MODE_10GBASER -- lists only SPEED_2500,
SPEED_1000, SPEED_100 and SPEED_10.
MGBE on Tegra234 runs 10GBASE-R into an Aquantia AQR113C. That PHY does
rate matching, so phylink_link_up() replaces the media speed with the
MAC-side interface speed before calling into the MAC:
case RATE_MATCH_PAUSE:
speed = phylink_interface_max_speed(link_state.interface);
duplex = DUPLEX_FULL;
The driver is therefore called as
stmmac_mac_link_up(interface=10GBASER, speed=10000, duplex=1)
which falls through to "default: return;". The interface stops passing
traffic after the first link flap.
The failure is easy to misread. The link still comes up, because the PHY
is polled over MDIO and needs no MAC, so the interface reports carrier 1
at the media speed. The DMA is untouched, so its start bits stay set and
descriptors are still consumed. Only the MAC itself is gated off: the
receiver counts nothing (mmc_rx_framecount_gb stops advancing, RE is 0)
and nothing reaches the wire (TE is 0). The interface survives boot only
because stmmac_hw_setup(), called from ndo_open, enables the MAC
unconditionally -- so the problem appears only once the cable has been
unplugged and plugged back in, and "ip link set dev <ethX> down && ip
link set dev <ethX> up" appears to fix it.
The interface is not what the speed bits depend on: with the single
exception of 2.5G, which is selected through the XGMII block on USXGMII
and through the regular speed bits otherwise, each speed maps to one
field of struct mac_link. The per-interface switches are speed
validation, and phylink already validates the speed against
priv->hw->link.caps. So collapse the three switches into one keyed on the
speed alone, keeping the interface test only for the 2.5G case. This
covers 10G on 10GBASE-R, and equally 5G, and 1G/100/10 on USXGMII, all of
which hit "default: return;" today.
A core that does not support a speed leaves the corresponding mac_link
field at 0, and phylink will not offer it that speed in the first place.
For dwxgmac2 at 10G, link.xgmii.speed10000 is XGMAC_CONFIG_SS_10000,
which is 0 and is the correct speed selection for a 10GBASE-R MAC: ctrl
then equals old_ctrl, the register write is skipped, and execution
reaches stmmac_mac_set(..., true).
Log an error in the default case, since a speed with no entry here leaves
the MAC disabled and the symptom does not point at the cause.
Fixes: d8ca113724e7 ("net: stmmac: tegra: Add MGBE support")
Suggested-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Signed-off-by: vadik likholetov <vadikas@gmail.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Link: https://patch.msgid.link/20260713074911.30090-1-vadikas@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
.../net/ethernet/stmicro/stmmac/stmmac_main.c | 92 ++++++++-----------
1 file changed, 37 insertions(+), 55 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 893746b2a49613..44fd0fadc137dd 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1032,63 +1032,45 @@ static void stmmac_mac_link_up(struct phylink_config *config,
old_ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
ctrl = old_ctrl & ~priv->hw->link.speed_mask;
- if (interface == PHY_INTERFACE_MODE_USXGMII) {
- switch (speed) {
- case SPEED_10000:
- ctrl |= priv->hw->link.xgmii.speed10000;
- break;
- case SPEED_5000:
- ctrl |= priv->hw->link.xgmii.speed5000;
- break;
- case SPEED_2500:
+ switch (speed) {
+ case SPEED_100000:
+ ctrl |= priv->hw->link.xlgmii.speed100000;
+ break;
+ case SPEED_50000:
+ ctrl |= priv->hw->link.xlgmii.speed50000;
+ break;
+ case SPEED_40000:
+ ctrl |= priv->hw->link.xlgmii.speed40000;
+ break;
+ case SPEED_25000:
+ ctrl |= priv->hw->link.xlgmii.speed25000;
+ break;
+ case SPEED_10000:
+ ctrl |= priv->hw->link.xgmii.speed10000;
+ break;
+ case SPEED_5000:
+ ctrl |= priv->hw->link.xgmii.speed5000;
+ break;
+ case SPEED_2500:
+ if (interface == PHY_INTERFACE_MODE_USXGMII)
ctrl |= priv->hw->link.xgmii.speed2500;
- break;
- default:
- return;
- }
- } else if (interface == PHY_INTERFACE_MODE_XLGMII) {
- switch (speed) {
- case SPEED_100000:
- ctrl |= priv->hw->link.xlgmii.speed100000;
- break;
- case SPEED_50000:
- ctrl |= priv->hw->link.xlgmii.speed50000;
- break;
- case SPEED_40000:
- ctrl |= priv->hw->link.xlgmii.speed40000;
- break;
- case SPEED_25000:
- ctrl |= priv->hw->link.xlgmii.speed25000;
- break;
- case SPEED_10000:
- ctrl |= priv->hw->link.xgmii.speed10000;
- break;
- case SPEED_2500:
- ctrl |= priv->hw->link.speed2500;
- break;
- case SPEED_1000:
- ctrl |= priv->hw->link.speed1000;
- break;
- default:
- return;
- }
- } else {
- switch (speed) {
- case SPEED_2500:
+ else
ctrl |= priv->hw->link.speed2500;
- break;
- case SPEED_1000:
- ctrl |= priv->hw->link.speed1000;
- break;
- case SPEED_100:
- ctrl |= priv->hw->link.speed100;
- break;
- case SPEED_10:
- ctrl |= priv->hw->link.speed10;
- break;
- default:
- return;
- }
+ break;
+ case SPEED_1000:
+ ctrl |= priv->hw->link.speed1000;
+ break;
+ case SPEED_100:
+ ctrl |= priv->hw->link.speed100;
+ break;
+ case SPEED_10:
+ ctrl |= priv->hw->link.speed10;
+ break;
+ default:
+ netdev_err(priv->dev,
+ "unsupported speed %s on %s, leaving the MAC disabled\n",
+ phy_speed_to_str(speed), phy_modes(interface));
+ return;
}
priv->speed = speed;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 227/602] net: gre: fix lltx regression for GRE tunnels with SEQ/CSUM
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (225 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 226/602] net: stmmac: enable the MAC on link up for all supported speeds Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 228/602] octeontx2-vf: set TC flower flag on MCAM entry allocation Greg Kroah-Hartman
` (378 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yun Zhou, Ido Schimmel, Paolo Abeni,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yun Zhou <yun.zhou@windriver.com>
[ Upstream commit 675ed582c1aa4d919dd535490de08c015005c653 ]
Before commit 00d066a4d4ed ("netdev_features: convert NETIF_F_LLTX to
dev->lltx"), NETIF_F_LLTX was set unconditionally in both
__gre_tunnel_init() and ip6gre_tnl_init_features() alongside
GRE_FEATURES:
dev->features |= GRE_FEATURES | NETIF_F_LLTX;
When that commit converted NETIF_F_LLTX to the dev->lltx flag, it
placed 'dev->lltx = true' after the SEQ/CSUM early returns instead
of before them. This causes GRE/GRETAP/ip6gre tunnels with SEQ or
CSUM+encap to lose lockless TX, reintroducing _xmit_lock acquisition
around their ndo_start_xmit. Since GRE xmit re-enters the stack via
ip_tunnel_xmit(), holding _xmit_lock risks ABBA deadlock with the
underlay device.
CPU0 CPU1
---- ----
lock(&qdisc_xmit_lock_key#6);
lock(&qdisc_xmit_lock_key#3);
lock(&qdisc_xmit_lock_key#6);
lock(&qdisc_xmit_lock_key#3);
Fix by moving dev->lltx = true before the early returns in both
functions, restoring the original unconditional behavior.
Fixes: 00d066a4d4ed ("netdev_features: convert NETIF_F_LLTX to dev->lltx")
Signed-off-by: Yun Zhou <yun.zhou@windriver.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20260713150945.1779628-1-yun.zhou@windriver.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/ipv4/ip_gre.c | 4 ++--
net/ipv6/ip6_gre.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index ffad16b023addf..f344e9bb31fbb3 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -1012,6 +1012,8 @@ static void __gre_tunnel_init(struct net_device *dev)
dev->features |= GRE_FEATURES;
dev->hw_features |= GRE_FEATURES;
+ dev->lltx = true;
+
/* TCP offload with GRE SEQ is not supported, nor can we support 2
* levels of outer headers requiring an update.
*/
@@ -1023,8 +1025,6 @@ static void __gre_tunnel_init(struct net_device *dev)
dev->features |= NETIF_F_GSO_SOFTWARE;
dev->hw_features |= NETIF_F_GSO_SOFTWARE;
-
- dev->lltx = true;
}
static int ipgre_tunnel_init(struct net_device *dev)
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index f1dc1244ade301..dac2e589849df3 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -1483,6 +1483,8 @@ static void ip6gre_tnl_init_features(struct net_device *dev)
dev->features |= GRE6_FEATURES;
dev->hw_features |= GRE6_FEATURES;
+ dev->lltx = true;
+
/* TCP offload with GRE SEQ is not supported, nor can we support 2
* levels of outer headers requiring an update.
*/
@@ -1494,8 +1496,6 @@ static void ip6gre_tnl_init_features(struct net_device *dev)
dev->features |= NETIF_F_GSO_SOFTWARE;
dev->hw_features |= NETIF_F_GSO_SOFTWARE;
-
- dev->lltx = true;
}
static int ip6gre_tunnel_init_common(struct net_device *dev)
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 228/602] octeontx2-vf: set TC flower flag on MCAM entry allocation
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (226 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 227/602] net: gre: fix lltx regression for GRE tunnels with SEQ/CSUM Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 229/602] ipv4: icmp: fill flow parameters in icmp_route_lookup decoy lookup Greg Kroah-Hartman
` (377 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Suman Ghosh, Ratheesh Kannoth,
Simon Horman, Paolo Abeni, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Suman Ghosh <sumang@marvell.com>
[ Upstream commit 0d4d31e3cc5dd6204fa1495c4107f5075acce5ed ]
When MCAM entries are allocated for a VF netdev via the devlink
mcam_count parameter, only OTX2_FLAG_NTUPLE_SUPPORT was set. That
enabled ethtool ntuple filters but not tc flower offload. Also set
OTX2_FLAG_TC_FLOWER_SUPPORT when entries are successfully allocated.
Fixes: 2da489432747 ("octeontx2-pf: devlink params support to set mcam entry count")
Signed-off-by: Suman Ghosh <sumang@marvell.com>
Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260715052007.2099851-1-rkannoth@marvell.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
index 2750326bfcf8b1..a9057711b62255 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
@@ -151,6 +151,7 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16 count)
if (allocated) {
pfvf->flags |= OTX2_FLAG_MCAM_ENTRIES_ALLOC;
pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT;
+ pfvf->flags |= OTX2_FLAG_TC_FLOWER_SUPPORT;
}
if (allocated != count)
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 229/602] ipv4: icmp: fill flow parameters in icmp_route_lookup decoy lookup
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (227 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 228/602] octeontx2-vf: set TC flower flag on MCAM entry allocation Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 230/602] ppp: use IFF_NO_QUEUE in virtual interfaces Greg Kroah-Hartman
` (376 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Muhammad Ziad, Eric Dumazet,
David Ahern, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <edumazet@google.com>
[ Upstream commit 853e164c2b321f0711361bc23505aaeb7dc432c3 ]
When Linux forwards a packet and needs to generate an ICMP error,
icmp_route_lookup() performs a reverse-path relookup. For non-local
destinations, it performs a decoy lookup to find the expected egress
interface (rt2->dst.dev) before validating the path with ip_route_input().
Currently, the decoy flow structure (fl4_2) only sets .daddr = fl4_dec.saddr,
leaving .saddr, .flowi4_dscp, .flowi4_proto, .flowi4_mark, .flowi4_oif,
.fl4_sport, .fl4_dport, and .flowi4_uid zeroed out.
When policy routing rules (such as ip rule add from $SRC lookup 100, or
dscp/fwmark/ipproto/port rules, or VRF bindings) are configured:
1. The decoy lookup fails to match the policy rule because saddr and other
key flow selectors are missing in fl4_2.
2. It resolves a route using the default table instead, returning an incorrect
egress netdev.
3. Passing the wrong netdev to ip_route_input() causes strict reverse-path
filtering (rp_filter=1) to fail, logging false-positive "martian source"
warnings and causing the relookup to fail.
Fix this by initializing fl4_2 from fl4_dec and:
- Swapping source/destination IP addresses.
- Swapping L4 ports for transport protocols with ports (TCP, UDP, SCTP, DCCP)
so port-based policy routing matches correctly. Non-port protocols (such as
ICMP or GRE) leave the flowi_uli union fields intact to prevent corruption.
- Setting .flowi4_oif = l3mdev_master_ifindex(route_lookup_dev) to ensure
VRF routing tables are respected.
- Setting .flowi4_flags |= FLOWI_FLAG_ANYSRC to allow output route lookups
for non-local source IP addresses.
- Using __ip_route_output_key() instead of ip_route_output_key() for fl4_2
so that raw FIB routing is used without triggering spurious XFRM policy
lookups on the decoy flow (the actual XFRM lookup is performed later using
fl4_dec).
Fixes: 415b3334a21a ("icmp: Fix regression in nexthop resolution during replies.")
Reported-by: Muhammad Ziad <muhzi100@gmail.com>
Closes: https://lore.kernel.org/netdev/CAOAwikA60AYKdFr_UDLyja3oU4hqyAE7uFZWqum5uRdaQsgRYg@mail.gmail.com/
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Link: https://patch.msgid.link/20260722104236.2938082-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/ipv4/icmp.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 4f55b6041feb49..c7af8b914e13cd 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -540,11 +540,23 @@ static struct rtable *icmp_route_lookup(struct net *net, struct flowi4 *fl4,
if (IS_ERR(rt2))
err = PTR_ERR(rt2);
} else {
- struct flowi4 fl4_2 = {};
+ struct flowi4 fl4_2 = fl4_dec;
unsigned long orefdst;
- fl4_2.daddr = fl4_dec.saddr;
- rt2 = ip_route_output_key(net, &fl4_2);
+ swap(fl4_2.daddr, fl4_2.saddr);
+ switch (fl4_2.flowi4_proto) {
+ case IPPROTO_TCP:
+ case IPPROTO_UDP:
+ case IPPROTO_SCTP:
+ case IPPROTO_DCCP:
+ swap(fl4_2.fl4_sport, fl4_2.fl4_dport);
+ break;
+ }
+
+ fl4_2.flowi4_oif = l3mdev_master_ifindex(route_lookup_dev);
+ fl4_2.flowi4_flags |= FLOWI_FLAG_ANYSRC;
+
+ rt2 = __ip_route_output_key(net, &fl4_2);
if (IS_ERR(rt2)) {
err = PTR_ERR(rt2);
goto relookup_failed;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 230/602] ppp: use IFF_NO_QUEUE in virtual interfaces
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (228 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 229/602] ipv4: icmp: fill flow parameters in icmp_route_lookup decoy lookup Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 231/602] ppp: convert to percpu netstats Greg Kroah-Hartman
` (375 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Qingfang Deng,
Toke Høiland-Jørgensen, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qingfang Deng <dqfext@gmail.com>
[ Upstream commit 95d0d094ba26432ec467e2260f4bf553053f1f8f ]
For PPPoE, PPTP, and PPPoL2TP, the start_xmit() function directly
forwards packets to the underlying network stack and never returns
anything other than 1. So these interfaces do not require a qdisc,
and the IFF_NO_QUEUE flag should be set.
Introduces a direct_xmit flag in struct ppp_channel to indicate when
IFF_NO_QUEUE should be applied. The flag is set in ppp_connect_channel()
for relevant protocols.
While at it, remove the usused latency member from struct ppp_channel.
Signed-off-by: Qingfang Deng <dqfext@gmail.com>
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
Link: https://patch.msgid.link/20250301135517.695809-1-dqfext@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: 543adf072165 ("ppp: annotate data races in ppp_generic")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ppp/ppp_generic.c | 4 ++++
drivers/net/ppp/pppoe.c | 1 +
drivers/net/ppp/pptp.c | 1 +
include/linux/ppp_channel.h | 3 +--
net/l2tp/l2tp_ppp.c | 1 +
5 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 9f787adef3eb38..9599b67688432e 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -3508,6 +3508,10 @@ ppp_connect_channel(struct channel *pch, int unit)
ret = -ENOTCONN;
goto outl;
}
+ if (pch->chan->direct_xmit)
+ ppp->dev->priv_flags |= IFF_NO_QUEUE;
+ else
+ ppp->dev->priv_flags &= ~IFF_NO_QUEUE;
spin_unlock_bh(&pch->downl);
if (pch->file.hdrlen > ppp->file.hdrlen)
ppp->file.hdrlen = pch->file.hdrlen;
diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c
index 937cf9b17f9aeb..944adf8b6e02b6 100644
--- a/drivers/net/ppp/pppoe.c
+++ b/drivers/net/ppp/pppoe.c
@@ -699,6 +699,7 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
po->chan.mtu = dev->mtu - sizeof(struct pppoe_hdr) - 2;
po->chan.private = sk;
po->chan.ops = &pppoe_chan_ops;
+ po->chan.direct_xmit = true;
error = ppp_register_net_channel(dev_net(dev), &po->chan);
if (error) {
diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c
index cec3bb22471b54..90737cb718928a 100644
--- a/drivers/net/ppp/pptp.c
+++ b/drivers/net/ppp/pptp.c
@@ -469,6 +469,7 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr,
po->chan.mtu -= PPTP_HEADER_OVERHEAD;
po->chan.hdrlen = 2 + sizeof(struct pptp_gre_header);
+ po->chan.direct_xmit = true;
error = ppp_register_channel(&po->chan);
if (error) {
pr_err("PPTP: failed to register PPP channel (%d)\n", error);
diff --git a/include/linux/ppp_channel.h b/include/linux/ppp_channel.h
index 45e6e427ceb8a0..f73fbea0dbc239 100644
--- a/include/linux/ppp_channel.h
+++ b/include/linux/ppp_channel.h
@@ -42,8 +42,7 @@ struct ppp_channel {
int hdrlen; /* amount of headroom channel needs */
void *ppp; /* opaque to channel */
int speed; /* transfer rate (bytes/second) */
- /* the following is not used at present */
- int latency; /* overhead time in milliseconds */
+ bool direct_xmit; /* no qdisc, xmit directly */
};
#ifdef __KERNEL__
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index bf78edee1ef8a7..f388bf9abf378d 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -796,6 +796,7 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
po->chan.private = sk;
po->chan.ops = &pppol2tp_chan_ops;
po->chan.mtu = pppol2tp_tunnel_mtu(tunnel);
+ po->chan.direct_xmit = true;
error = ppp_register_net_channel(sock_net(sk), &po->chan);
if (error) {
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 231/602] ppp: convert to percpu netstats
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (229 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 230/602] ppp: use IFF_NO_QUEUE in virtual interfaces Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 232/602] ppp: enable TX scatter-gather Greg Kroah-Hartman
` (374 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Qingfang Deng, Jakub Kicinski,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qingfang Deng <dqfext@gmail.com>
[ Upstream commit 1a3e9b7a6b09e8ab3d2af019e4a392622685855e ]
Convert to percpu netstats to avoid lock contention when reading them.
Signed-off-by: Qingfang Deng <dqfext@gmail.com>
Link: https://patch.msgid.link/20250610083211.909015-1-dqfext@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: 543adf072165 ("ppp: annotate data races in ppp_generic")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ppp/ppp_generic.c | 52 +++++++++++++----------------------
1 file changed, 19 insertions(+), 33 deletions(-)
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 9599b67688432e..68cd438a5b5eb5 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -107,18 +107,6 @@ struct ppp_file {
#define PF_TO_PPP(pf) PF_TO_X(pf, struct ppp)
#define PF_TO_CHANNEL(pf) PF_TO_X(pf, struct channel)
-/*
- * Data structure to hold primary network stats for which
- * we want to use 64 bit storage. Other network stats
- * are stored in dev->stats of the ppp strucute.
- */
-struct ppp_link_stats {
- u64 rx_packets;
- u64 tx_packets;
- u64 rx_bytes;
- u64 tx_bytes;
-};
-
/*
* Data structure describing one ppp unit.
* A ppp unit corresponds to a ppp network interface device
@@ -162,7 +150,6 @@ struct ppp {
struct bpf_prog *active_filter; /* filter for pkts to reset idle */
#endif /* CONFIG_PPP_FILTER */
struct net *ppp_net; /* the net we belong to */
- struct ppp_link_stats stats64; /* 64 bit network stats */
};
/*
@@ -1545,23 +1532,12 @@ ppp_net_siocdevprivate(struct net_device *dev, struct ifreq *ifr,
static void
ppp_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats64)
{
- struct ppp *ppp = netdev_priv(dev);
-
- ppp_recv_lock(ppp);
- stats64->rx_packets = ppp->stats64.rx_packets;
- stats64->rx_bytes = ppp->stats64.rx_bytes;
- ppp_recv_unlock(ppp);
-
- ppp_xmit_lock(ppp);
- stats64->tx_packets = ppp->stats64.tx_packets;
- stats64->tx_bytes = ppp->stats64.tx_bytes;
- ppp_xmit_unlock(ppp);
-
stats64->rx_errors = dev->stats.rx_errors;
stats64->tx_errors = dev->stats.tx_errors;
stats64->rx_dropped = dev->stats.rx_dropped;
stats64->tx_dropped = dev->stats.tx_dropped;
stats64->rx_length_errors = dev->stats.rx_length_errors;
+ dev_fetch_sw_netstats(stats64, dev->tstats);
}
static int ppp_dev_init(struct net_device *dev)
@@ -1659,6 +1635,7 @@ static void ppp_setup(struct net_device *dev)
dev->type = ARPHRD_PPP;
dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
dev->priv_destructor = ppp_dev_priv_destructor;
+ dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
netif_keep_dst(dev);
}
@@ -1804,8 +1781,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
#endif /* CONFIG_PPP_FILTER */
}
- ++ppp->stats64.tx_packets;
- ppp->stats64.tx_bytes += skb->len - PPP_PROTO_LEN;
+ dev_sw_netstats_tx_add(ppp->dev, 1, skb->len - PPP_PROTO_LEN);
switch (proto) {
case PPP_IP:
@@ -2483,8 +2459,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
break;
}
- ++ppp->stats64.rx_packets;
- ppp->stats64.rx_bytes += skb->len - 2;
+ dev_sw_netstats_rx_add(ppp->dev, skb->len - PPP_PROTO_LEN);
npi = proto_to_npindex(proto);
if (npi < 0) {
@@ -3312,14 +3287,25 @@ static void
ppp_get_stats(struct ppp *ppp, struct ppp_stats *st)
{
struct slcompress *vj = ppp->vj;
+ int cpu;
memset(st, 0, sizeof(*st));
- st->p.ppp_ipackets = ppp->stats64.rx_packets;
+ for_each_possible_cpu(cpu) {
+ struct pcpu_sw_netstats *p = per_cpu_ptr(ppp->dev->tstats, cpu);
+ u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
+
+ rx_packets = u64_stats_read(&p->rx_packets);
+ rx_bytes = u64_stats_read(&p->rx_bytes);
+ tx_packets = u64_stats_read(&p->tx_packets);
+ tx_bytes = u64_stats_read(&p->tx_bytes);
+
+ st->p.ppp_ipackets += rx_packets;
+ st->p.ppp_ibytes += rx_bytes;
+ st->p.ppp_opackets += tx_packets;
+ st->p.ppp_obytes += tx_bytes;
+ }
st->p.ppp_ierrors = ppp->dev->stats.rx_errors;
- st->p.ppp_ibytes = ppp->stats64.rx_bytes;
- st->p.ppp_opackets = ppp->stats64.tx_packets;
st->p.ppp_oerrors = ppp->dev->stats.tx_errors;
- st->p.ppp_obytes = ppp->stats64.tx_bytes;
if (!vj)
return;
st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 232/602] ppp: enable TX scatter-gather
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (230 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 231/602] ppp: convert to percpu netstats Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 233/602] ppp: annotate data races in ppp_generic Greg Kroah-Hartman
` (373 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Qingfang Deng, Paolo Abeni,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qingfang Deng <dqfext@gmail.com>
[ Upstream commit 42fcb213e58a7da33d5d2d7517b4e521025c68c3 ]
PPP channels using chan->direct_xmit prepend the PPP header to a skb and
call dev_queue_xmit() directly. In this mode the skb does not need to be
linear, but the PPP netdevice currently does not advertise
scatter-gather features, causing unnecessary linearization and
preventing GSO.
Enable NETIF_F_SG and NETIF_F_FRAGLIST on PPP devices. In case a linear
buffer is required (PPP compression, multilink, and channels without
direct_xmit), call skb_linearize() explicitly.
Signed-off-by: Qingfang Deng <dqfext@gmail.com>
Link: https://patch.msgid.link/20260129012902.941-1-dqfext@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Stable-dep-of: 543adf072165 ("ppp: annotate data races in ppp_generic")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ppp/ppp_generic.c | 30 +++++++++++++++++++++++++-----
1 file changed, 25 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 68cd438a5b5eb5..f217f6dee38f10 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -1636,6 +1636,8 @@ static void ppp_setup(struct net_device *dev)
dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
dev->priv_destructor = ppp_dev_priv_destructor;
dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
+ dev->features = NETIF_F_SG | NETIF_F_FRAGLIST;
+ dev->hw_features = dev->features;
netif_keep_dst(dev);
}
@@ -1700,6 +1702,10 @@ pad_compress_skb(struct ppp *ppp, struct sk_buff *skb)
ppp->xcomp->comp_extra + ppp->dev->hard_header_len;
int compressor_skb_size = ppp->dev->mtu +
ppp->xcomp->comp_extra + PPP_HDRLEN;
+
+ if (skb_linearize(skb))
+ return NULL;
+
new_skb = alloc_skb(new_skb_size, GFP_ATOMIC);
if (!new_skb) {
if (net_ratelimit())
@@ -1787,6 +1793,10 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
case PPP_IP:
if (!ppp->vj || (ppp->flags & SC_COMP_TCP) == 0)
break;
+
+ if (skb_linearize(skb))
+ goto drop;
+
/* try to do VJ TCP header compression */
new_skb = alloc_skb(skb->len + ppp->dev->hard_header_len - 2,
GFP_ATOMIC);
@@ -1884,19 +1894,26 @@ ppp_push(struct ppp *ppp)
}
if ((ppp->flags & SC_MULTILINK) == 0) {
+ struct ppp_channel *chan;
/* not doing multilink: send it down the first channel */
list = list->next;
pch = list_entry(list, struct channel, clist);
spin_lock(&pch->downl);
- if (pch->chan) {
- if (pch->chan->ops->start_xmit(pch->chan, skb))
- ppp->xmit_pending = NULL;
- } else {
- /* channel got unregistered */
+ chan = pch->chan;
+ if (unlikely(!chan || (!chan->direct_xmit && skb_linearize(skb)))) {
+ /* channel got unregistered, or it requires a linear
+ * skb but linearization failed
+ */
kfree_skb(skb);
ppp->xmit_pending = NULL;
+ goto out;
}
+
+ if (chan->ops->start_xmit(chan, skb))
+ ppp->xmit_pending = NULL;
+
+out:
spin_unlock(&pch->downl);
return;
}
@@ -1981,6 +1998,8 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
return 0; /* can't take now, leave it in xmit_pending */
/* Do protocol field compression */
+ if (skb_linearize(skb))
+ goto err_linearize;
p = skb->data;
len = skb->len;
if (*p == 0 && mp_protocol_compress) {
@@ -2139,6 +2158,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
noskb:
spin_unlock(&pch->downl);
+ err_linearize:
if (ppp->debug & 1)
netdev_err(ppp->dev, "PPP: no memory (fragment)\n");
++ppp->dev->stats.tx_errors;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 233/602] ppp: annotate data races in ppp_generic
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (231 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 232/602] ppp: enable TX scatter-gather Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 234/602] hinic: remove unused ethtool RSS user configuration buffers Greg Kroah-Hartman
` (372 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Eric Dumazet, Qingfang Deng,
Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <edumazet@google.com>
[ Upstream commit 543adf072165aaf2e3b635c0476204f9658ed3bf ]
Several fields in struct ppp can be read or updated concurrently
from multiple CPUs without synchronization, causing data races:
1. ppp->mru is read concurrently in ppp_receive_nonmp_frame() while
being updated via PPPIOCSMRU ioctl. Protect ppp->mru updates in
PPPIOCSMRU with ppp_recv_lock(ppp).
2. PPPIOCGFLAGS reads ppp->flags, ppp->xstate, and ppp->rstate
unlocked. Wrap the read in ppp_lock(ppp) to get a consistent
snapshot.
3. ppp->debug is updated via PPPIOCSDEBUG and read concurrently on
fast paths. Annotate reads with READ_ONCE() and writes with
WRITE_ONCE().
4. ppp->last_xmit and ppp->last_recv are updated on TX/RX data paths
and read via PPPIOCGIDLE32 / PPPIOCGIDLE64 ioctls. Annotate with
WRITE_ONCE() / READ_ONCE() and use max() to handle jiffies
subtraction.
5. ppp->npmode[] is updated via PPPIOCSNPMODE and read on TX/RX
paths. Annotate with WRITE_ONCE() / READ_ONCE().
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Qingfang Deng <qingfang.deng@linux.dev>
Link: https://patch.msgid.link/20260722101605.2868548-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ppp/ppp_generic.c | 50 ++++++++++++++++++++---------------
1 file changed, 28 insertions(+), 22 deletions(-)
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index f217f6dee38f10..5d6d69632c847a 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -813,7 +813,9 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case PPPIOCSMRU:
if (get_user(val, p))
break;
+ ppp_recv_lock(ppp);
ppp->mru = val;
+ ppp_recv_unlock(ppp);
err = 0;
break;
@@ -834,7 +836,9 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break;
case PPPIOCGFLAGS:
+ ppp_lock(ppp);
val = ppp->flags | ppp->xstate | ppp->rstate;
+ ppp_unlock(ppp);
if (put_user(val, p))
break;
err = 0;
@@ -858,7 +862,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case PPPIOCSDEBUG:
if (get_user(val, p))
break;
- ppp->debug = val;
+ WRITE_ONCE(ppp->debug, val);
err = 0;
break;
@@ -869,16 +873,16 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break;
case PPPIOCGIDLE32:
- idle32.xmit_idle = (jiffies - ppp->last_xmit) / HZ;
- idle32.recv_idle = (jiffies - ppp->last_recv) / HZ;
- if (copy_to_user(argp, &idle32, sizeof(idle32)))
+ idle32.xmit_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_xmit))) / HZ;
+ idle32.recv_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_recv))) / HZ;
+ if (copy_to_user(argp, &idle32, sizeof(idle32)))
break;
err = 0;
break;
case PPPIOCGIDLE64:
- idle64.xmit_idle = (jiffies - ppp->last_xmit) / HZ;
- idle64.recv_idle = (jiffies - ppp->last_recv) / HZ;
+ idle64.xmit_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_xmit))) / HZ;
+ idle64.recv_idle = max(0L, (long)(jiffies - READ_ONCE(ppp->last_recv))) / HZ;
if (copy_to_user(argp, &idle64, sizeof(idle64)))
break;
err = 0;
@@ -919,7 +923,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (copy_to_user(argp, &npi, sizeof(npi)))
break;
} else {
- ppp->npmode[i] = npi.mode;
+ WRITE_ONCE(ppp->npmode[i], npi.mode);
/* we may be able to transmit more packets now (??) */
netif_wake_queue(ppp->dev);
}
@@ -1454,7 +1458,7 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
goto outf;
/* Drop, accept or reject the packet */
- switch (ppp->npmode[npi]) {
+ switch (READ_ONCE(ppp->npmode[npi])) {
case NPMODE_PASS:
break;
case NPMODE_QUEUE:
@@ -1769,7 +1773,7 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
*(__be16 *)skb_push(skb, 2) = htons(PPP_FILTER_OUTBOUND_TAG);
if (ppp->pass_filter &&
bpf_prog_run(ppp->pass_filter, skb) == 0) {
- if (ppp->debug & 1)
+ if (READ_ONCE(ppp->debug) & 1)
netdev_printk(KERN_DEBUG, ppp->dev,
"PPP: outbound frame "
"not passed\n");
@@ -1779,11 +1783,11 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
/* if this packet passes the active filter, record the time */
if (!(ppp->active_filter &&
bpf_prog_run(ppp->active_filter, skb) == 0))
- ppp->last_xmit = jiffies;
+ WRITE_ONCE(ppp->last_xmit, jiffies);
skb_pull(skb, 2);
#else
/* for data packets, record the time */
- ppp->last_xmit = jiffies;
+ WRITE_ONCE(ppp->last_xmit, jiffies);
#endif /* CONFIG_PPP_FILTER */
}
@@ -2159,7 +2163,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
noskb:
spin_unlock(&pch->downl);
err_linearize:
- if (ppp->debug & 1)
+ if (READ_ONCE(ppp->debug) & 1)
netdev_err(ppp->dev, "PPP: no memory (fragment)\n");
++ppp->dev->stats.tx_errors;
++ppp->nxseq;
@@ -2505,7 +2509,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
*(__be16 *)skb_push(skb, 2) = htons(PPP_FILTER_INBOUND_TAG);
if (ppp->pass_filter &&
bpf_prog_run(ppp->pass_filter, skb) == 0) {
- if (ppp->debug & 1)
+ if (READ_ONCE(ppp->debug) & 1)
netdev_printk(KERN_DEBUG, ppp->dev,
"PPP: inbound frame "
"not passed\n");
@@ -2514,14 +2518,14 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
}
if (!(ppp->active_filter &&
bpf_prog_run(ppp->active_filter, skb) == 0))
- ppp->last_recv = jiffies;
+ WRITE_ONCE(ppp->last_recv, jiffies);
__skb_pull(skb, 2);
} else
#endif /* CONFIG_PPP_FILTER */
- ppp->last_recv = jiffies;
+ WRITE_ONCE(ppp->last_recv, jiffies);
if ((ppp->dev->flags & IFF_UP) == 0 ||
- ppp->npmode[npi] != NPMODE_PASS) {
+ READ_ONCE(ppp->npmode[npi]) != NPMODE_PASS) {
kfree_skb(skb);
} else {
/* chop off protocol */
@@ -2774,7 +2778,7 @@ ppp_mp_reconstruct(struct ppp *ppp)
seq = seq_before(minseq, PPP_MP_CB(p)->sequence)?
minseq + 1: PPP_MP_CB(p)->sequence;
- if (ppp->debug & 1)
+ if (READ_ONCE(ppp->debug) & 1)
netdev_printk(KERN_DEBUG, ppp->dev,
"lost frag %u..%u\n",
oldseq, seq-1);
@@ -2823,7 +2827,7 @@ ppp_mp_reconstruct(struct ppp *ppp)
struct sk_buff *tmp2;
skb_queue_reverse_walk_from_safe(list, p, tmp2) {
- if (ppp->debug & 1)
+ if (READ_ONCE(ppp->debug) & 1)
netdev_printk(KERN_DEBUG, ppp->dev,
"discarding frag %u\n",
PPP_MP_CB(p)->sequence);
@@ -2845,7 +2849,7 @@ ppp_mp_reconstruct(struct ppp *ppp)
skb_queue_walk_safe(list, p, tmp) {
if (p == head)
break;
- if (ppp->debug & 1)
+ if (READ_ONCE(ppp->debug) & 1)
netdev_printk(KERN_DEBUG, ppp->dev,
"discarding frag %u\n",
PPP_MP_CB(p)->sequence);
@@ -2853,7 +2857,7 @@ ppp_mp_reconstruct(struct ppp *ppp)
kfree_skb(p);
}
- if (ppp->debug & 1)
+ if (READ_ONCE(ppp->debug) & 1)
netdev_printk(KERN_DEBUG, ppp->dev,
" missed pkts %u..%u\n",
ppp->nextseq,
@@ -3163,7 +3167,8 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound)
if (!ppp->rc_state)
break;
if (ppp->rcomp->decomp_init(ppp->rc_state, dp, len,
- ppp->file.index, 0, ppp->mru, ppp->debug)) {
+ ppp->file.index, 0, ppp->mru,
+ READ_ONCE(ppp->debug))) {
ppp->rstate |= SC_DECOMP_RUN;
ppp->rstate &= ~(SC_DC_ERROR | SC_DC_FERROR);
}
@@ -3172,7 +3177,8 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound)
if (!ppp->xc_state)
break;
if (ppp->xcomp->comp_init(ppp->xc_state, dp, len,
- ppp->file.index, 0, ppp->debug))
+ ppp->file.index, 0,
+ READ_ONCE(ppp->debug)))
ppp->xstate |= SC_COMP_RUN;
}
break;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 234/602] hinic: remove unused ethtool RSS user configuration buffers
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (232 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 233/602] ppp: annotate data races in ppp_generic Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 235/602] net: qrtr: restrict socket creation to the initial network namespace Greg Kroah-Hartman
` (371 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Chenguang Zhao, Joe Damato,
Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chenguang Zhao <zhaochenguang@kylinos.cn>
[ Upstream commit fe0c002928c6749b7f4a726f6f600f6dd70280ea ]
rss_indir_user and rss_hkey_user are allocated and filled in
__set_rss_rxfh() when the user configures RSS via ethtool, but
nothing ever reads them. hinic_get_rxfh() fetches the state from
the device, and the hardware is programmed from the original
indir/key arguments. These buffers only leaked on driver unload.
Drop the unused allocations, memcpys, and struct fields.
Fixes: 4fdc51bb4e92 ("hinic: add support for rss parameters with ethtool")
Signed-off-by: Chenguang Zhao <zhaochenguang@kylinos.cn>
Reviewed-by: Joe Damato <joe@dama.to>
Link: https://patch.msgid.link/20260722025353.328179-1-chenguang.zhao@linux.dev
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/huawei/hinic/hinic_dev.h | 2 --
.../net/ethernet/huawei/hinic/hinic_ethtool.c | 21 -------------------
2 files changed, 23 deletions(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_dev.h
index 52ea97c818b8ec..d9ab94910a2a79 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_dev.h
+++ b/drivers/net/ethernet/huawei/hinic/hinic_dev.h
@@ -104,8 +104,6 @@ struct hinic_dev {
u16 num_rss;
u16 rss_limit;
struct hinic_rss_type rss_type;
- u8 *rss_hkey_user;
- s32 *rss_indir_user;
struct hinic_intr_coal_info *rx_intr_coalesce;
struct hinic_intr_coal_info *tx_intr_coalesce;
struct hinic_sriov_info sriov_info;
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
index c559dd4291d306..dba76a768e672a 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
@@ -1061,17 +1061,6 @@ static int __set_rss_rxfh(struct net_device *netdev,
int err;
if (indir) {
- if (!nic_dev->rss_indir_user) {
- nic_dev->rss_indir_user =
- kzalloc(sizeof(u32) * HINIC_RSS_INDIR_SIZE,
- GFP_KERNEL);
- if (!nic_dev->rss_indir_user)
- return -ENOMEM;
- }
-
- memcpy(nic_dev->rss_indir_user, indir,
- sizeof(u32) * HINIC_RSS_INDIR_SIZE);
-
err = hinic_rss_set_indir_tbl(nic_dev,
nic_dev->rss_tmpl_idx, indir);
if (err)
@@ -1079,16 +1068,6 @@ static int __set_rss_rxfh(struct net_device *netdev,
}
if (key) {
- if (!nic_dev->rss_hkey_user) {
- nic_dev->rss_hkey_user =
- kzalloc(HINIC_RSS_KEY_SIZE * 2, GFP_KERNEL);
-
- if (!nic_dev->rss_hkey_user)
- return -ENOMEM;
- }
-
- memcpy(nic_dev->rss_hkey_user, key, HINIC_RSS_KEY_SIZE);
-
err = hinic_rss_set_template_tbl(nic_dev,
nic_dev->rss_tmpl_idx, key);
if (err)
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 235/602] net: qrtr: restrict socket creation to the initial network namespace
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (233 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 234/602] hinic: remove unused ethtool RSS user configuration buffers Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 236/602] dpll: add clock quality level attribute and op Greg Kroah-Hartman
` (370 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Aldo Ariel Panzardo, Jakub Kicinski,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aldo Ariel Panzardo <qwe.aldo@gmail.com>
[ Upstream commit 3b536db8fb32da9e9c62f2bb45e2e319331f0426 ]
QRTR keeps its entire port and node state in module-global variables
that are not partitioned per network namespace: qrtr_local_nid is a
single global node id (always 1) and qrtr_ports is a single global
xarray. qrtr_port_lookup() and qrtr_local_enqueue() operate on that
global state with no network-namespace check, and qrtr_create() places
no restriction on the namespace a socket is created in.
As a result an unprivileged process that creates an AF_QIPCRTR socket
in a separate network namespace, e.g. via
unshare(CLONE_NEWUSER | CLONE_NEWNET), can send QRTR datagrams -
including control-plane messages such as QRTR_TYPE_NEW_SERVER - to QRTR
sockets owned by another namespace, and vice versa. The receiving
socket sees such a message as coming from node id 1, indistinguishable
from a legitimate local client, breaking the isolation that network
namespaces are expected to provide.
QRTR is a transport to global hardware endpoints (the modem and other
remote processors) and has no per-namespace semantics; its in-kernel
name service already creates its socket in init_net only. Confine the
socket family to the initial network namespace, as other
non-namespace-aware socket families do (see llc_ui_create() and the
ieee802154 socket code).
Fixes: bdabad3e363d ("net: Add Qualcomm IPC router")
Signed-off-by: Aldo Ariel Panzardo <qwe.aldo@gmail.com>
Link: https://patch.msgid.link/20260716154319.3297699-1-qwe.aldo@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/qrtr/af_qrtr.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/net/qrtr/af_qrtr.c b/net/qrtr/af_qrtr.c
index 305523cebe3baa..fcd24a7df3f00d 100644
--- a/net/qrtr/af_qrtr.c
+++ b/net/qrtr/af_qrtr.c
@@ -1261,6 +1261,14 @@ static int qrtr_create(struct net *net, struct socket *sock,
if (sock->type != SOCK_DGRAM)
return -EPROTOTYPE;
+ /* QRTR keeps its port and node state in module-global variables that
+ * are not partitioned per network namespace, and the in-kernel name
+ * service only operates in init_net. Confine the family to init_net so
+ * a socket in another namespace cannot reach the global control plane.
+ */
+ if (!net_eq(net, &init_net))
+ return -EAFNOSUPPORT;
+
sk = sk_alloc(net, AF_QIPCRTR, GFP_KERNEL, &qrtr_proto, kern);
if (!sk)
return -ENOMEM;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 236/602] dpll: add clock quality level attribute and op
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (234 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 235/602] net: qrtr: restrict socket creation to the initial network namespace Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 237/602] net/mlx5: DPLL, Add clock quality level op implementation Greg Kroah-Hartman
` (369 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Jiri Pirko, Jakub Kicinski,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiri Pirko <jiri@nvidia.com>
[ Upstream commit a1afb959add1fad43cb337448c244ed70bac3109 ]
In order to allow driver expose quality level of the clock it is
running, introduce a new netlink attr with enum to carry it to the
userspace. Also, introduce an op the dpll netlink code calls into the
driver to obtain the value.
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
Link: https://patch.msgid.link/20241030081157.966604-2-jiri@resnulli.us
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: 11c057d23465 ("net/mlx5: Fix MCIA register buffer overflow on 32 dword reads")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
Documentation/netlink/specs/dpll.yaml | 41 +++++++++++++++++++++++++++
drivers/dpll/dpll_netlink.c | 24 ++++++++++++++++
include/linux/dpll.h | 4 +++
include/uapi/linux/dpll.h | 24 ++++++++++++++++
4 files changed, 93 insertions(+)
diff --git a/Documentation/netlink/specs/dpll.yaml b/Documentation/netlink/specs/dpll.yaml
index cb5763f79ac2ae..c799d43b8833d1 100644
--- a/Documentation/netlink/specs/dpll.yaml
+++ b/Documentation/netlink/specs/dpll.yaml
@@ -85,6 +85,36 @@ definitions:
This may happen for example if dpll device was previously
locked on an input pin of type PIN_TYPE_SYNCE_ETH_PORT.
render-max: true
+ -
+ type: enum
+ name: clock-quality-level
+ doc: |
+ level of quality of a clock device. This mainly applies when
+ the dpll lock-status is DPLL_LOCK_STATUS_HOLDOVER.
+ The current list is defined according to the table 11-7 contained
+ in ITU-T G.8264/Y.1364 document. One may extend this list freely
+ by other ITU-T defined clock qualities, or different ones defined
+ by another standardization body (for those, please use
+ different prefix).
+ entries:
+ -
+ name: itu-opt1-prc
+ value: 1
+ -
+ name: itu-opt1-ssu-a
+ -
+ name: itu-opt1-ssu-b
+ -
+ name: itu-opt1-eec1
+ -
+ name: itu-opt1-prtc
+ -
+ name: itu-opt1-eprtc
+ -
+ name: itu-opt1-eeec
+ -
+ name: itu-opt1-eprc
+ render-max: true
-
type: const
name: temp-divider
@@ -252,6 +282,17 @@ attribute-sets:
name: lock-status-error
type: u32
enum: lock-status-error
+ -
+ name: clock-quality-level
+ type: u32
+ enum: clock-quality-level
+ multi-attr: true
+ doc: |
+ Level of quality of a clock device. This mainly applies when
+ the dpll lock-status is DPLL_LOCK_STATUS_HOLDOVER. This could
+ be put to message multiple times to indicate possible parallel
+ quality levels (e.g. one specified by ITU option 1 and another
+ one specified by option 2).
-
name: pin
enum-name: dpll_a_pin
diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
index e3fb08e1578d85..c66f57a5814c8c 100644
--- a/drivers/dpll/dpll_netlink.c
+++ b/drivers/dpll/dpll_netlink.c
@@ -187,6 +187,27 @@ dpll_msg_add_temp(struct sk_buff *msg, struct dpll_device *dpll,
return 0;
}
+static int
+dpll_msg_add_clock_quality_level(struct sk_buff *msg, struct dpll_device *dpll,
+ struct netlink_ext_ack *extack)
+{
+ const struct dpll_device_ops *ops = dpll_device_ops(dpll);
+ DECLARE_BITMAP(qls, DPLL_CLOCK_QUALITY_LEVEL_MAX) = { 0 };
+ enum dpll_clock_quality_level ql;
+ int ret;
+
+ if (!ops->clock_quality_level_get)
+ return 0;
+ ret = ops->clock_quality_level_get(dpll, dpll_priv(dpll), qls, extack);
+ if (ret)
+ return ret;
+ for_each_set_bit(ql, qls, DPLL_CLOCK_QUALITY_LEVEL_MAX)
+ if (nla_put_u32(msg, DPLL_A_CLOCK_QUALITY_LEVEL, ql))
+ return -EMSGSIZE;
+
+ return 0;
+}
+
static int
dpll_msg_add_pin_prio(struct sk_buff *msg, struct dpll_pin *pin,
struct dpll_pin_ref *ref,
@@ -623,6 +644,9 @@ dpll_device_get_one(struct dpll_device *dpll, struct sk_buff *msg,
if (ret)
return ret;
ret = dpll_msg_add_lock_status(msg, dpll, extack);
+ if (ret)
+ return ret;
+ ret = dpll_msg_add_clock_quality_level(msg, dpll, extack);
if (ret)
return ret;
ret = dpll_msg_add_mode(msg, dpll, extack);
diff --git a/include/linux/dpll.h b/include/linux/dpll.h
index 3c03b19d939070..5d62e9a0b8243c 100644
--- a/include/linux/dpll.h
+++ b/include/linux/dpll.h
@@ -28,6 +28,10 @@ struct dpll_device_ops {
struct netlink_ext_ack *extack);
int (*temp_get)(const struct dpll_device *dpll, void *dpll_priv,
s32 *temp, struct netlink_ext_ack *extack);
+ int (*clock_quality_level_get)(const struct dpll_device *dpll,
+ void *dpll_priv,
+ unsigned long *qls,
+ struct netlink_ext_ack *extack);
};
struct dpll_pin_ops {
diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
index 7fa641b3a20adb..12a43bf9a863bc 100644
--- a/include/uapi/linux/dpll.h
+++ b/include/uapi/linux/dpll.h
@@ -79,6 +79,29 @@ enum dpll_lock_status_error {
DPLL_LOCK_STATUS_ERROR_MAX = (__DPLL_LOCK_STATUS_ERROR_MAX - 1)
};
+/**
+ * enum dpll_clock_quality_level - level of quality of a clock device. This
+ * mainly applies when the dpll lock-status is DPLL_LOCK_STATUS_HOLDOVER. The
+ * current list is defined according to the table 11-7 contained in ITU-T
+ * G.8264/Y.1364 document. One may extend this list freely by other ITU-T
+ * defined clock qualities, or different ones defined by another
+ * standardization body (for those, please use different prefix).
+ */
+enum dpll_clock_quality_level {
+ DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_PRC = 1,
+ DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_SSU_A,
+ DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_SSU_B,
+ DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EEC1,
+ DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_PRTC,
+ DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EPRTC,
+ DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EEEC,
+ DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EPRC,
+
+ /* private: */
+ __DPLL_CLOCK_QUALITY_LEVEL_MAX,
+ DPLL_CLOCK_QUALITY_LEVEL_MAX = (__DPLL_CLOCK_QUALITY_LEVEL_MAX - 1)
+};
+
#define DPLL_TEMP_DIVIDER 1000
/**
@@ -180,6 +203,7 @@ enum dpll_a {
DPLL_A_TEMP,
DPLL_A_TYPE,
DPLL_A_LOCK_STATUS_ERROR,
+ DPLL_A_CLOCK_QUALITY_LEVEL,
__DPLL_A_MAX,
DPLL_A_MAX = (__DPLL_A_MAX - 1)
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 237/602] net/mlx5: DPLL, Add clock quality level op implementation
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (235 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 236/602] dpll: add clock quality level attribute and op Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 238/602] net/mlx5: Remove newline at the end of a netlink error message Greg Kroah-Hartman
` (368 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Arkadiusz Kubalewski, Jiri Pirko,
Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiri Pirko <jiri@nvidia.com>
[ Upstream commit e2017f27b6f888fb4ebc5c9a6d984bbf2f8b99ff ]
Use MSECQ register to query clock quality from firmware. Implement the
dpll op and fill-up the quality level value properly.
Reviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
Link: https://patch.msgid.link/20241030081157.966604-3-jiri@resnulli.us
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: 11c057d23465 ("net/mlx5: Fix MCIA register buffer overflow on 32 dword reads")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
.../net/ethernet/mellanox/mlx5/core/dpll.c | 81 +++++++++++++++++++
1 file changed, 81 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/dpll.c b/drivers/net/ethernet/mellanox/mlx5/core/dpll.c
index 904e08de852eac..31142f6cc37293 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/dpll.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/dpll.c
@@ -166,9 +166,90 @@ static int mlx5_dpll_device_mode_get(const struct dpll_device *dpll,
return 0;
}
+enum {
+ MLX5_DPLL_SSM_CODE_PRC = 0b0010,
+ MLX5_DPLL_SSM_CODE_SSU_A = 0b0100,
+ MLX5_DPLL_SSM_CODE_SSU_B = 0b1000,
+ MLX5_DPLL_SSM_CODE_EEC1 = 0b1011,
+ MLX5_DPLL_SSM_CODE_PRTC = 0b0010,
+ MLX5_DPLL_SSM_CODE_EPRTC = 0b0010,
+ MLX5_DPLL_SSM_CODE_EEEC = 0b1011,
+ MLX5_DPLL_SSM_CODE_EPRC = 0b0010,
+};
+
+enum {
+ MLX5_DPLL_ENHANCED_SSM_CODE_PRC = 0xff,
+ MLX5_DPLL_ENHANCED_SSM_CODE_SSU_A = 0xff,
+ MLX5_DPLL_ENHANCED_SSM_CODE_SSU_B = 0xff,
+ MLX5_DPLL_ENHANCED_SSM_CODE_EEC1 = 0xff,
+ MLX5_DPLL_ENHANCED_SSM_CODE_PRTC = 0x20,
+ MLX5_DPLL_ENHANCED_SSM_CODE_EPRTC = 0x21,
+ MLX5_DPLL_ENHANCED_SSM_CODE_EEEC = 0x22,
+ MLX5_DPLL_ENHANCED_SSM_CODE_EPRC = 0x23,
+};
+
+#define __MLX5_DPLL_SSM_COMBINED_CODE(ssm_code, enhanced_ssm_code) \
+ ((ssm_code) | ((enhanced_ssm_code) << 8))
+
+#define MLX5_DPLL_SSM_COMBINED_CODE(type) \
+ __MLX5_DPLL_SSM_COMBINED_CODE(MLX5_DPLL_SSM_CODE_##type, \
+ MLX5_DPLL_ENHANCED_SSM_CODE_##type)
+
+static int mlx5_dpll_clock_quality_level_get(const struct dpll_device *dpll,
+ void *priv, unsigned long *qls,
+ struct netlink_ext_ack *extack)
+{
+ u8 network_option, ssm_code, enhanced_ssm_code;
+ u32 out[MLX5_ST_SZ_DW(msecq_reg)] = {};
+ u32 in[MLX5_ST_SZ_DW(msecq_reg)] = {};
+ struct mlx5_dpll *mdpll = priv;
+ int err;
+
+ err = mlx5_core_access_reg(mdpll->mdev, in, sizeof(in),
+ out, sizeof(out), MLX5_REG_MSECQ, 0, 0);
+ if (err)
+ return err;
+ network_option = MLX5_GET(msecq_reg, out, network_option);
+ if (network_option != 1)
+ goto errout;
+ ssm_code = MLX5_GET(msecq_reg, out, local_ssm_code);
+ enhanced_ssm_code = MLX5_GET(msecq_reg, out, local_enhanced_ssm_code);
+
+ switch (__MLX5_DPLL_SSM_COMBINED_CODE(ssm_code, enhanced_ssm_code)) {
+ case MLX5_DPLL_SSM_COMBINED_CODE(PRC):
+ __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_PRC, qls);
+ return 0;
+ case MLX5_DPLL_SSM_COMBINED_CODE(SSU_A):
+ __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_SSU_A, qls);
+ return 0;
+ case MLX5_DPLL_SSM_COMBINED_CODE(SSU_B):
+ __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_SSU_B, qls);
+ return 0;
+ case MLX5_DPLL_SSM_COMBINED_CODE(EEC1):
+ __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EEC1, qls);
+ return 0;
+ case MLX5_DPLL_SSM_COMBINED_CODE(PRTC):
+ __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_PRTC, qls);
+ return 0;
+ case MLX5_DPLL_SSM_COMBINED_CODE(EPRTC):
+ __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EPRTC, qls);
+ return 0;
+ case MLX5_DPLL_SSM_COMBINED_CODE(EEEC):
+ __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EEEC, qls);
+ return 0;
+ case MLX5_DPLL_SSM_COMBINED_CODE(EPRC):
+ __set_bit(DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EPRC, qls);
+ return 0;
+ }
+errout:
+ NL_SET_ERR_MSG_MOD(extack, "Invalid clock quality level obtained from firmware\n");
+ return -EINVAL;
+}
+
static const struct dpll_device_ops mlx5_dpll_device_ops = {
.lock_status_get = mlx5_dpll_device_lock_status_get,
.mode_get = mlx5_dpll_device_mode_get,
+ .clock_quality_level_get = mlx5_dpll_clock_quality_level_get,
};
static int mlx5_dpll_pin_direction_get(const struct dpll_pin *pin,
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 238/602] net/mlx5: Remove newline at the end of a netlink error message
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (236 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 237/602] net/mlx5: DPLL, Add clock quality level op implementation Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 239/602] net/mlx5: Refactor EEPROM query error handling to return status separately Greg Kroah-Hartman
` (367 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Tariq Toukan, Gal Pressman,
Michal Swiatkowski, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gal Pressman <gal@nvidia.com>
[ Upstream commit 3a2295ff3f00d44c97baec37c43b6ede3eea9df9 ]
Netlink error messages should not have a newline at the end of the
string.
Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
Signed-off-by: Gal Pressman <gal@nvidia.com>
Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
Link: https://patch.msgid.link/20250226093904.6632-3-gal@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: 11c057d23465 ("net/mlx5: Fix MCIA register buffer overflow on 32 dword reads")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/mellanox/mlx5/core/dpll.c | 2 +-
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c | 2 +-
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c | 2 +-
drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c | 6 +++---
4 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/dpll.c b/drivers/net/ethernet/mellanox/mlx5/core/dpll.c
index 31142f6cc37293..1e5522a194839c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/dpll.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/dpll.c
@@ -242,7 +242,7 @@ static int mlx5_dpll_clock_quality_level_get(const struct dpll_device *dpll,
return 0;
}
errout:
- NL_SET_ERR_MSG_MOD(extack, "Invalid clock quality level obtained from firmware\n");
+ NL_SET_ERR_MSG_MOD(extack, "Invalid clock quality level obtained from firmware");
return -EINVAL;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c
index b9cf79e2712440..7a18a469961db8 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c
@@ -140,7 +140,7 @@ static int mlx5e_tc_tun_parse_vxlan_gbp_option(struct mlx5e_priv *priv,
gbp_mask = (u32 *)&enc_opts.mask->data[0];
if (*gbp_mask & ~VXLAN_GBP_MASK) {
- NL_SET_ERR_MSG_FMT_MOD(extack, "Wrong VxLAN GBP mask(0x%08X)\n", *gbp_mask);
+ NL_SET_ERR_MSG_FMT_MOD(extack, "Wrong VxLAN GBP mask(0x%08X)", *gbp_mask);
return -EINVAL;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index 1f55c5a7edf31b..d278542677efb2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -2013,7 +2013,7 @@ static int mlx5e_get_module_eeprom_by_page(struct net_device *netdev,
if (size_read < 0) {
NL_SET_ERR_MSG_FMT_MOD(
extack,
- "Query module eeprom by page failed, read %u bytes, err %d\n",
+ "Query module eeprom by page failed, read %u bytes, err %d",
i, size_read);
return size_read;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c
index c5ea1d1d2b035c..282cef59e6173f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c
@@ -1861,7 +1861,7 @@ int mlx5_esw_bridge_port_mdb_add(struct net_device *dev, u16 vport_num, u16 esw_
"Failed to lookup bridge port to add MDB (MAC=%pM,vport=%u)\n",
addr, vport_num);
NL_SET_ERR_MSG_FMT_MOD(extack,
- "Failed to lookup bridge port to add MDB (MAC=%pM,vport=%u)\n",
+ "Failed to lookup bridge port to add MDB (MAC=%pM,vport=%u)",
addr, vport_num);
return -EINVAL;
}
@@ -1874,7 +1874,7 @@ int mlx5_esw_bridge_port_mdb_add(struct net_device *dev, u16 vport_num, u16 esw_
"Failed to lookup bridge port vlan metadata to create MDB (MAC=%pM,vid=%u,vport=%u)\n",
addr, vid, vport_num);
NL_SET_ERR_MSG_FMT_MOD(extack,
- "Failed to lookup vlan metadata for MDB (MAC=%pM,vid=%u,vport=%u)\n",
+ "Failed to lookup vlan metadata for MDB (MAC=%pM,vid=%u,vport=%u)",
addr, vid, vport_num);
return -EINVAL;
}
@@ -1882,7 +1882,7 @@ int mlx5_esw_bridge_port_mdb_add(struct net_device *dev, u16 vport_num, u16 esw_
err = mlx5_esw_bridge_port_mdb_attach(dev, port, addr, vid);
if (err) {
- NL_SET_ERR_MSG_FMT_MOD(extack, "Failed to add MDB (MAC=%pM,vid=%u,vport=%u)\n",
+ NL_SET_ERR_MSG_FMT_MOD(extack, "Failed to add MDB (MAC=%pM,vid=%u,vport=%u)",
addr, vid, vport_num);
return err;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 239/602] net/mlx5: Refactor EEPROM query error handling to return status separately
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (237 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 238/602] net/mlx5: Remove newline at the end of a netlink error message Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 240/602] net/mlx5: Fix MCIA register buffer overflow on 32 dword reads Greg Kroah-Hartman
` (366 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Matthew W Carlis, Gal Pressman,
Jianbo Liu, Tariq Toukan, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gal Pressman <gal@nvidia.com>
[ Upstream commit 2e4c44b12f4da60d3e8dcbc1ccf38bb28a878050 ]
Matthew and Jakub reported [1] issues where inventory automation tools
are calling EEPROM query repeatedly on a port that doesn't have an SFP
connected, resulting in millions of error prints.
Move MCIA register status extraction from the query functions to the
callers, allowing use of extack reporting instead of a dmesg print when
using the netlink API.
[1] https://lore.kernel.org/netdev/20251028194011.39877-1-mattc@purestorage.com/
Cc: Matthew W Carlis <mattc@purestorage.com>
Signed-off-by: Gal Pressman <gal@nvidia.com>
Reviewed-by: Jianbo Liu <jianbol@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/1763415729-1238421-2-git-send-email-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: 11c057d23465 ("net/mlx5: Fix MCIA register buffer overflow on 32 dword reads")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
.../ethernet/mellanox/mlx5/core/en_ethtool.c | 19 +++++-----
.../ethernet/mellanox/mlx5/core/mlx5_core.h | 4 +--
.../net/ethernet/mellanox/mlx5/core/port.c | 35 +++++++++----------
3 files changed, 30 insertions(+), 28 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index d278542677efb2..026f2867b84900 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -1912,7 +1912,7 @@ static int mlx5e_get_module_info(struct net_device *netdev,
int size_read = 0;
u8 data[4] = {0};
- size_read = mlx5_query_module_eeprom(dev, 0, 2, data);
+ size_read = mlx5_query_module_eeprom(dev, 0, 2, data, NULL);
if (size_read < 2)
return -EIO;
@@ -1954,6 +1954,7 @@ static int mlx5e_get_module_eeprom(struct net_device *netdev,
struct mlx5_core_dev *mdev = priv->mdev;
int offset = ee->offset;
int size_read;
+ u8 status = 0;
int i = 0;
if (!ee->len)
@@ -1963,15 +1964,15 @@ static int mlx5e_get_module_eeprom(struct net_device *netdev,
while (i < ee->len) {
size_read = mlx5_query_module_eeprom(mdev, offset, ee->len - i,
- data + i);
-
+ data + i, &status);
if (!size_read)
/* Done reading */
return 0;
if (size_read < 0) {
- netdev_err(priv->netdev, "%s: mlx5_query_eeprom failed:0x%x\n",
- __func__, size_read);
+ netdev_err(netdev,
+ "%s: mlx5_query_eeprom failed:0x%x, status %u\n",
+ __func__, size_read, status);
return size_read;
}
@@ -1991,6 +1992,7 @@ static int mlx5e_get_module_eeprom_by_page(struct net_device *netdev,
struct mlx5_core_dev *mdev = priv->mdev;
u8 *data = page_data->data;
int size_read;
+ u8 status = 0;
int i = 0;
if (!page_data->length)
@@ -2004,7 +2006,8 @@ static int mlx5e_get_module_eeprom_by_page(struct net_device *netdev,
query.page = page_data->page;
while (i < page_data->length) {
query.size = page_data->length - i;
- size_read = mlx5_query_module_eeprom_by_page(mdev, &query, data + i);
+ size_read = mlx5_query_module_eeprom_by_page(mdev, &query,
+ data + i, &status);
/* Done reading, return how many bytes was read */
if (!size_read)
@@ -2013,8 +2016,8 @@ static int mlx5e_get_module_eeprom_by_page(struct net_device *netdev,
if (size_read < 0) {
NL_SET_ERR_MSG_FMT_MOD(
extack,
- "Query module eeprom by page failed, read %u bytes, err %d",
- i, size_read);
+ "Query module eeprom by page failed, read %u bytes, err %d, status %u",
+ i, size_read, status);
return size_read;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
index 1ca75f1815ef64..2e152f8571c7df 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
@@ -342,11 +342,11 @@ int mlx5_set_port_fcs(struct mlx5_core_dev *mdev, u8 enable);
void mlx5_query_port_fcs(struct mlx5_core_dev *mdev, bool *supported,
bool *enabled);
int mlx5_query_module_eeprom(struct mlx5_core_dev *dev,
- u16 offset, u16 size, u8 *data);
+ u16 offset, u16 size, u8 *data, u8 *status);
int
mlx5_query_module_eeprom_by_page(struct mlx5_core_dev *dev,
struct mlx5_module_eeprom_query_params *params,
- u8 *data);
+ u8 *data, u8 *status);
int mlx5_query_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *out);
int mlx5_set_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *in);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c
index 79c477e05e46cf..c0f189b8cd1ad6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c
@@ -289,11 +289,11 @@ int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num)
}
static int mlx5_query_module_id(struct mlx5_core_dev *dev, int module_num,
- u8 *module_id)
+ u8 *module_id, u8 *status)
{
u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {};
u32 out[MLX5_ST_SZ_DW(mcia_reg)];
- int err, status;
+ int err;
u8 *ptr;
MLX5_SET(mcia_reg, in, i2c_device_address, MLX5_I2C_ADDR_LOW);
@@ -308,12 +308,12 @@ static int mlx5_query_module_id(struct mlx5_core_dev *dev, int module_num,
if (err)
return err;
- status = MLX5_GET(mcia_reg, out, status);
- if (status) {
- mlx5_core_err(dev, "query_mcia_reg failed: status: 0x%x\n",
- status);
+ if (MLX5_GET(mcia_reg, out, status)) {
+ if (status)
+ *status = MLX5_GET(mcia_reg, out, status);
return -EIO;
}
+
ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0);
*module_id = ptr[0];
@@ -370,13 +370,14 @@ static int mlx5_mcia_max_bytes(struct mlx5_core_dev *dev)
}
static int mlx5_query_mcia(struct mlx5_core_dev *dev,
- struct mlx5_module_eeprom_query_params *params, u8 *data)
+ struct mlx5_module_eeprom_query_params *params,
+ u8 *data, u8 *status)
{
u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {};
u32 out[MLX5_ST_SZ_DW(mcia_reg)];
- int status, err;
void *ptr;
u16 size;
+ int err;
size = min_t(int, params->size, mlx5_mcia_max_bytes(dev));
@@ -392,12 +393,9 @@ static int mlx5_query_mcia(struct mlx5_core_dev *dev,
if (err)
return err;
- status = MLX5_GET(mcia_reg, out, status);
- if (status) {
- mlx5_core_err(dev, "query_mcia_reg failed: status: 0x%x\n",
- status);
+ *status = MLX5_GET(mcia_reg, out, status);
+ if (*status)
return -EIO;
- }
ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0);
memcpy(data, ptr, size);
@@ -406,7 +404,7 @@ static int mlx5_query_mcia(struct mlx5_core_dev *dev,
}
int mlx5_query_module_eeprom(struct mlx5_core_dev *dev,
- u16 offset, u16 size, u8 *data)
+ u16 offset, u16 size, u8 *data, u8 *status)
{
struct mlx5_module_eeprom_query_params query = {0};
u8 module_id;
@@ -416,7 +414,8 @@ int mlx5_query_module_eeprom(struct mlx5_core_dev *dev,
if (err)
return err;
- err = mlx5_query_module_id(dev, query.module_number, &module_id);
+ err = mlx5_query_module_id(dev, query.module_number, &module_id,
+ status);
if (err)
return err;
@@ -442,12 +441,12 @@ int mlx5_query_module_eeprom(struct mlx5_core_dev *dev,
query.size = size;
query.offset = offset;
- return mlx5_query_mcia(dev, &query, data);
+ return mlx5_query_mcia(dev, &query, data, status);
}
int mlx5_query_module_eeprom_by_page(struct mlx5_core_dev *dev,
struct mlx5_module_eeprom_query_params *params,
- u8 *data)
+ u8 *data, u8 *status)
{
int err;
@@ -461,7 +460,7 @@ int mlx5_query_module_eeprom_by_page(struct mlx5_core_dev *dev,
return -EINVAL;
}
- return mlx5_query_mcia(dev, params, data);
+ return mlx5_query_mcia(dev, params, data, status);
}
static int mlx5_query_port_pvlc(struct mlx5_core_dev *dev, u32 *pvlc,
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 240/602] net/mlx5: Fix MCIA register buffer overflow on 32 dword reads
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (238 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 239/602] net/mlx5: Refactor EEPROM query error handling to return status separately Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 241/602] net/mlx5: E-Switch, fix zero num_dest in prio_tag egress vlan rule Greg Kroah-Hartman
` (365 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Gal Pressman, Alex Lazar,
Tariq Toukan, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gal Pressman <gal@nvidia.com>
[ Upstream commit 11c057d23465c7a5817a7284c896d19d54c0b616 ]
The MCIA register can return up to 32 dwords (128 bytes) when the device
advertises the mcia_32dwords capability, but struct
mlx5_ifc_mcia_reg_bits only defines dword_0..11, leaving room for just
12 dwords (48 bytes) of data.
mlx5_query_mcia() clamps the read size to mlx5_mcia_max_bytes() and then
memcpy()s that many bytes out of the register, potentially reading past
the end of the 'out' buffer. On kernels built with FORTIFY_SOURCE this
is caught as a buffer overflow while reading the module EEPROM via
ethtool:
detected buffer overflow in memcpy
kernel BUG at lib/string_helpers.c:1048!
RIP: 0010:fortify_panic+0x13/0x20
Call Trace:
mlx5_query_mcia.isra.0+0x200/0x210 [mlx5_core]
mlx5_query_module_eeprom_by_page+0x4a/0xa0 [mlx5_core]
mlx5e_get_module_eeprom_by_page+0xbb/0x120 [mlx5_core]
eeprom_prepare_data+0xf3/0x170
ethnl_default_doit+0xf1/0x3b0
Extend the mcia_reg layout to 32 dwords.
Fixes: 271907ee2f29 ("net/mlx5: Query the maximum MCIA register read size from firmware")
Signed-off-by: Gal Pressman <gal@nvidia.com>
Reviewed-by: Alex Lazar <alazar@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260717072338.1240582-1-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/mellanox/mlx5/core/port.c | 4 ++--
include/linux/mlx5/mlx5_ifc.h | 13 +------------
2 files changed, 3 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c
index c0f189b8cd1ad6..1a60a989b16349 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c
@@ -314,7 +314,7 @@ static int mlx5_query_module_id(struct mlx5_core_dev *dev, int module_num,
return -EIO;
}
- ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0);
+ ptr = MLX5_ADDR_OF(mcia_reg, out, dwords);
*module_id = ptr[0];
@@ -397,7 +397,7 @@ static int mlx5_query_mcia(struct mlx5_core_dev *dev,
if (*status)
return -EIO;
- ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0);
+ ptr = MLX5_ADDR_OF(mcia_reg, out, dwords);
memcpy(data, ptr, size);
return size;
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h
index 6ea35c8ce00fb4..c0864fa3883b84 100644
--- a/include/linux/mlx5/mlx5_ifc.h
+++ b/include/linux/mlx5/mlx5_ifc.h
@@ -11803,18 +11803,7 @@ struct mlx5_ifc_mcia_reg_bits {
u8 reserved_at_60[0x20];
- u8 dword_0[0x20];
- u8 dword_1[0x20];
- u8 dword_2[0x20];
- u8 dword_3[0x20];
- u8 dword_4[0x20];
- u8 dword_5[0x20];
- u8 dword_6[0x20];
- u8 dword_7[0x20];
- u8 dword_8[0x20];
- u8 dword_9[0x20];
- u8 dword_10[0x20];
- u8 dword_11[0x20];
+ u8 dwords[0x400];
};
struct mlx5_ifc_dcbx_param_bits {
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 241/602] net/mlx5: E-Switch, fix zero num_dest in prio_tag egress vlan rule
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (239 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 240/602] net/mlx5: Fix MCIA register buffer overflow on 32 dword reads Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 242/602] net/mlx5e: Report zero bandwidth for non-ETS traffic classes Greg Kroah-Hartman
` (364 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yael Chemla, Cosmin Ratiu,
Tariq Toukan, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yael Chemla <ychemla@nvidia.com>
[ Upstream commit d12956d083eb70f2c6d72711aebaf8c2ce21e170 ]
esw_egress_acl_vlan_create() hardcodes num_dest=0 in its
mlx5_add_flow_rules() call. When invoked from the non-bond path
fwd_dest is NULL and num_dest=0 is correct. When invoked from
esw_acl_egress_ofld_rules_create() during a bond event, fwd_dest is
non-NULL and flow_act.action carries MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
but _mlx5_add_flow_rules() rejects a non-NULL dest pointer paired with
dest_num<=0 and returns -EINVAL. The error propagates as
"configure slave vport egress fwd, err(-22)". The passive vport's egress
ACL table ends up with its flow groups allocated but no FTEs, so
prio-tagged packets are not popped and bond failover is broken on
prio_tag_required devices.
Fix by passing fwd_dest ? 1 : 0 as num_dest to match the actual number
of destinations supplied.
Fixes: bf773dc0e6d5 ("net/mlx5: E-Switch, Introduce APIs to enable egress acl forward-to-vport rule")
Signed-off-by: Yael Chemla <ychemla@nvidia.com>
Reviewed-by: Cosmin Ratiu <cratiu@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260717073306.1242399-1-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c
index d599e50af346be..fc545bfb54de76 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c
@@ -71,7 +71,7 @@ int esw_egress_acl_vlan_create(struct mlx5_eswitch *esw,
flow_act.action = flow_action;
vport->egress.allowed_vlan =
mlx5_add_flow_rules(vport->egress.acl, spec,
- &flow_act, fwd_dest, 0);
+ &flow_act, fwd_dest, fwd_dest ? 1 : 0);
if (IS_ERR(vport->egress.allowed_vlan)) {
err = PTR_ERR(vport->egress.allowed_vlan);
esw_warn(esw->dev,
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 242/602] net/mlx5e: Report zero bandwidth for non-ETS traffic classes
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (240 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 241/602] net/mlx5: E-Switch, fix zero num_dest in prio_tag egress vlan rule Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 243/602] net/mlx5e: Reject unsupported CB Shaper TSA in ETS validation Greg Kroah-Hartman
` (363 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Alexei Lazar, Carolina Jubran,
Tariq Toukan, Pavan Chebbi, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexei Lazar <alazar@nvidia.com>
[ Upstream commit ffb1873b2df11945b8c395e859169248675c91c5 ]
The IEEE 802.1Qaz standard defines that bandwidth allocation percentages
only apply to Enhanced Transmission Selection (ETS) traffic classes.
For STRICT and VENDOR transmission selection algorithms, bandwidth
percentage values are not applicable.
Currently for non-ETS 100 bandwidth is being reported for all traffic
classes in the get operation due to hardware limitation, regardless of
their TSA type.
Fix this by reporting 0 for non-ETS traffic classes.
Fixes: 820c2c5e773d ("net/mlx5e: Read ETS settings directly from firmware")
Signed-off-by: Alexei Lazar <alazar@nvidia.com>
Reviewed-by: Carolina Jubran <cjubran@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
Link: https://patch.msgid.link/20260717075125.1244877-2-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
index 84e700777941ec..d74ff20f825954 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
@@ -158,6 +158,13 @@ static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev,
}
memcpy(ets->tc_tsa, priv->dcbx.tc_tsa, sizeof(ets->tc_tsa));
+ /* Report 0 for non ETS TSA */
+ for (i = 0; i < ets->ets_cap; i++) {
+ if (ets->tc_tx_bw[i] == MLX5E_MAX_BW_ALLOC &&
+ priv->dcbx.tc_tsa[i] != IEEE_8021QAZ_TSA_ETS)
+ ets->tc_tx_bw[i] = 0;
+ }
+
return err;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 243/602] net/mlx5e: Reject unsupported CB Shaper TSA in ETS validation
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (241 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 242/602] net/mlx5e: Report zero bandwidth for non-ETS traffic classes Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 244/602] octeontx2-pf: tc: fix egress ratelimiting Greg Kroah-Hartman
` (362 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Alexei Lazar, Carolina Jubran,
Tariq Toukan, Pavan Chebbi, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexei Lazar <alazar@nvidia.com>
[ Upstream commit 9173e1d3c7c7d49a71eee813091f9e834ec7cee5 ]
Credit Based (CB) TSA is not supported by the mlx5 driver, so reject
any configurations that specify it.
Fixes: 08fb1dacdd76 ("net/mlx5e: Support DCBNL IEEE ETS")
Signed-off-by: Alexei Lazar <alazar@nvidia.com>
Reviewed-by: Carolina Jubran <cjubran@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
Link: https://patch.msgid.link/20260717075125.1244877-3-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
index d74ff20f825954..98ca8f486d52cd 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
@@ -309,6 +309,14 @@ static int mlx5e_dbcnl_validate_ets(struct net_device *netdev,
}
}
+ for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
+ if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_CB_SHAPER) {
+ netdev_err(netdev,
+ "Failed to validate ETS: CB Shaper is not supported\n");
+ return -EOPNOTSUPP;
+ }
+ }
+
/* Validate Bandwidth Sum */
for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) {
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 244/602] octeontx2-pf: tc: fix egress ratelimiting
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (242 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 243/602] net/mlx5e: Reject unsupported CB Shaper TSA in ETS validation Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 245/602] net: ipv6: fix dif and sdif mismatch in raw6_icmp_error Greg Kroah-Hartman
` (361 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Hariprasad Kelam, Nitin Shetty J,
Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hariprasad Kelam <hkelam@marvell.com>
[ Upstream commit bb0d96ebe5f4d1acccf4dc36ca7f01f9a8fa1ba1 ]
The egress rate calculation computes an incorrect mantissa and exponent,
causing up to ~50% deviation from the configured rate at lower speeds.
Rework the computation to follow the hardware rate formula:
rate = 2 * (1 + mantissa/256) * 2^exp / (1 << div_exp)
Keep div_exp = 0 and derive exp and mantissa from half of the requested
rate. Rates below 2 Mbps are floored to the smallest encodable step
(exp = 0, mantissa = 0).
Fixes: e638a83f167e ("octeontx2-pf: TC_MATCHALL egress ratelimiting offload")
Signed-off-by: Hariprasad Kelam <hkelam@marvell.com>
Signed-off-by: Nitin Shetty J <nshettyj@marvell.com>
Link: https://patch.msgid.link/20260717084349.2227796-1-nshettyj@marvell.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
.../ethernet/marvell/octeontx2/nic/otx2_tc.c | 29 ++++++++++---------
1 file changed, 16 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
index ed041c3f714f26..b26fc848430f50 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
@@ -30,6 +30,7 @@
#define OTX2_UNSUPP_LSE_DEPTH GENMASK(6, 4)
#define MCAST_INVALID_GRP (-1U)
+#define RATE_MANTISSA_BITS 8
struct otx2_tc_flow_stats {
u64 bytes;
@@ -90,28 +91,30 @@ static void otx2_get_egress_burst_cfg(struct otx2_nic *nic, u32 burst,
static void otx2_get_egress_rate_cfg(u64 maxrate, u32 *exp,
u32 *mantissa, u32 *div_exp)
{
- u64 tmp;
-
/* Rate calculation by hardware
*
* PIR_ADD = ((256 + mantissa) << exp) / 256
* rate = (2 * PIR_ADD) / ( 1 << div_exp)
* The resultant rate is in Mbps.
+ *
+ * Use div_exp = 0 and compute exp/mantissa for maxrate / 2; the
+ * leading factor of two yields the full rate. Rates below 2 Mbps
+ * are floored to the smallest step (exp = 0, mantissa = 0).
*/
- /* 2Mbps to 100Gbps can be expressed with div_exp = 0.
- * Setting this to '0' will ease the calculation of
- * exponent and mantissa.
- */
*div_exp = 0;
-
if (maxrate) {
- *exp = ilog2(maxrate) ? ilog2(maxrate) - 1 : 0;
- tmp = maxrate - rounddown_pow_of_two(maxrate);
- if (maxrate < MAX_RATE_MANTISSA)
- *mantissa = tmp * 2;
- else
- *mantissa = tmp / (1ULL << (*exp - 7));
+ maxrate = maxrate / 2;
+ if (!maxrate) {
+ /* Rates below 2 Mbps map to the smallest step */
+ *exp = 0;
+ *mantissa = 0;
+ } else {
+ *exp = ilog2(maxrate);
+ /* Clear MSB and derive fractional bits */
+ maxrate &= ~BIT(*exp);
+ *mantissa = (maxrate << RATE_MANTISSA_BITS) >> *exp;
+ }
} else {
/* Instead of disabling rate limiting, set all values to max */
*exp = MAX_RATE_EXPONENT;
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 245/602] net: ipv6: fix dif and sdif mismatch in raw6_icmp_error
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (243 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 244/602] octeontx2-pf: tc: fix egress ratelimiting Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 246/602] ice: allow creating VFs when !CONFIG_ICE_SWITCHDEV Greg Kroah-Hartman
` (360 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Li RongQing, Joe Damato,
Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li RongQing <lirongqing@baidu.com>
[ Upstream commit 440e274da4d1b93c7df2cb0ce893c3009dd4db55 ]
In raw6_icmp_error(), raw_v6_match() is called with inet6_iif(skb) passed
to both the 'dif' and 'sdif' arguments. This is a copy-paste or typo error,
as the last argument should represent the secondary interface index (sdif).
This mismatch breaks ICMPv6 error handling for IPv6 raw sockets in VRF
(Virtual Routing and Forwarding) environments. When a raw socket is bound
to a VRF master device, raw_v6_match() fails to find a match because it is
not given the correct sdif value, causing the socket to miss relevant
ICMPv6 error notifications.
Fix this by properly passing inet6_sdif(skb) as the last argument to
raw_v6_match().
Fixes: 5108ab4bf446fa ("net: ipv6: add second dif to raw socket lookups")
Signed-off-by: Li RongQing <lirongqing@baidu.com>
Reviewed-by: Joe Damato <joe@dama.to>
Link: https://patch.msgid.link/20260717143230.1836-1-lirongqing@baidu.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/ipv6/raw.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index d148f1b03c5d09..deaaae63bda0ab 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -348,7 +348,7 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr,
const struct ipv6hdr *ip6h = (const struct ipv6hdr *)skb->data;
if (!raw_v6_match(net, sk, nexthdr, &ip6h->saddr, &ip6h->daddr,
- inet6_iif(skb), inet6_iif(skb)))
+ inet6_iif(skb), inet6_sdif(skb)))
continue;
rawv6_err(sk, skb, type, code, inner_offset, info);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 246/602] ice: allow creating VFs when !CONFIG_ICE_SWITCHDEV
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (244 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 245/602] net: ipv6: fix dif and sdif mismatch in raw6_icmp_error Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 247/602] ice: fix LAG recipe to profile association Greg Kroah-Hartman
` (359 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Vincent Chen, Aleksandr Loktionov,
Rafal Romanowski, Tony Nguyen, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vincent Chen <vincent.chen@sifive.com>
[ Upstream commit 99d0f42b0e5c57e4c02070a908aaff082881293a ]
Currently ice_eswitch_attach_vf() is called unconditionally in
ice_start_vfs(), which causes VF creation to fail when CONFIG_ICE_SWITCHDEV
is not defined.
Fix this by adding switchdev mode checks at the call sites before
calling ice_eswitch_attach_vf(), consistent with how
ice_eswitch_attach_sf() is already handled in ice_devlink_port_new().
This is similar to commit aacca7a83b97 ("ice: allow creating VFs for
!CONFIG_NET_SWITCHDEV") which fixed the same issue for the previous
ice_eswitch_configure() API.
Fixes: 415db8399d06 ("ice: make representor code generic")
Signed-off-by: Vincent Chen <vincent.chen@sifive.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Link: https://patch.msgid.link/20260717185340.3595286-2-anthony.l.nguyen@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/intel/ice/ice_eswitch.c | 3 ---
drivers/net/ethernet/intel/ice/ice_sriov.c | 14 ++++++++------
drivers/net/ethernet/intel/ice/ice_vf_lib.c | 3 ++-
3 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c
index 32b52ecff04ffb..fa7f1e02bfafed 100644
--- a/drivers/net/ethernet/intel/ice/ice_eswitch.c
+++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c
@@ -506,9 +506,6 @@ int ice_eswitch_attach_vf(struct ice_pf *pf, struct ice_vf *vf)
struct ice_repr *repr;
int err;
- if (!ice_is_eswitch_mode_switchdev(pf))
- return 0;
-
repr = ice_repr_create_vf(vf);
if (IS_ERR(repr))
return PTR_ERR(repr);
diff --git a/drivers/net/ethernet/intel/ice/ice_sriov.c b/drivers/net/ethernet/intel/ice/ice_sriov.c
index 8aabf7749aa5e0..d33a761cfdc04e 100644
--- a/drivers/net/ethernet/intel/ice/ice_sriov.c
+++ b/drivers/net/ethernet/intel/ice/ice_sriov.c
@@ -596,12 +596,14 @@ static int ice_start_vfs(struct ice_pf *pf)
goto teardown;
}
- retval = ice_eswitch_attach_vf(pf, vf);
- if (retval) {
- dev_err(ice_pf_to_dev(pf), "Failed to attach VF %d to eswitch, error %d",
- vf->vf_id, retval);
- ice_vf_vsi_release(vf);
- goto teardown;
+ if (ice_is_eswitch_mode_switchdev(pf)) {
+ retval = ice_eswitch_attach_vf(pf, vf);
+ if (retval) {
+ dev_err(ice_pf_to_dev(pf), "Failed to attach VF %d to eswitch, error %d",
+ vf->vf_id, retval);
+ ice_vf_vsi_release(vf);
+ goto teardown;
+ }
}
set_bit(ICE_VF_STATE_INIT, vf->vf_states);
diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c
index afa9e7ce463763..71530ae79a87e8 100644
--- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c
+++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c
@@ -811,7 +811,8 @@ void ice_reset_all_vfs(struct ice_pf *pf)
}
ice_vf_post_vsi_rebuild(vf);
- ice_eswitch_attach_vf(pf, vf);
+ if (ice_is_eswitch_mode_switchdev(pf))
+ ice_eswitch_attach_vf(pf, vf);
mutex_unlock(&vf->cfg_lock);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 247/602] ice: fix LAG recipe to profile association
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (245 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 246/602] ice: allow creating VFs when !CONFIG_ICE_SWITCHDEV Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 248/602] rds: tcp: unregister sysctl before tearing down listen socket Greg Kroah-Hartman
` (358 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Marcin Szycik, Michal Swiatkowski,
Aleksandr Loktionov, Dave Ertman, Simon Horman, Tony Nguyen,
Jakub Kicinski, Sasha Levin, Rinitha S
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marcin Szycik <marcin.szycik@linux.intel.com>
[ Upstream commit d6da9b7d48599db078aea6144997a381f8d90d45 ]
ice_init_lag() associates recipes to profiles, assuming that Link
Aggregation-related profiles will always have profile ID lower than 70
(ICE_PROFID_IPV6_GTPU_IPV6_TCP_INNER). This value seems arbitrary and
might not always be valid for some versions of DDP package, i.e. LAG
profiles may have profile ID greater than 70. This would lead to
misconfigured switch and LAG not working properly.
Fix it by checking up to maximum profile ID.
Fixes: 1e0f9881ef79 ("ice: Flesh out implementation of support for SRIOV on bonded interface")
Signed-off-by: Marcin Szycik <marcin.szycik@linux.intel.com>
Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Reviewed-by: Dave Ertman <david.m.ertman@intel.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Tested-by: Rinitha S <sx.rinitha@intel.com> (A Contingent worker at Intel)
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Link: https://patch.msgid.link/20260717185340.3595286-7-anthony.l.nguyen@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/intel/ice/ice_lag.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_lag.c b/drivers/net/ethernet/intel/ice/ice_lag.c
index d132eb4775513c..da1cd103a4d905 100644
--- a/drivers/net/ethernet/intel/ice/ice_lag.c
+++ b/drivers/net/ethernet/intel/ice/ice_lag.c
@@ -2095,7 +2095,7 @@ int ice_init_lag(struct ice_pf *pf)
goto free_rcp_res;
/* associate recipes to profiles */
- for (n = 0; n < ICE_PROFID_IPV6_GTPU_IPV6_TCP_INNER; n++) {
+ for (n = 0; n < ICE_MAX_NUM_PROFILES; n++) {
err = ice_aq_get_recipe_to_profile(&pf->hw, n,
&recipe_bits, NULL);
if (err)
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 248/602] rds: tcp: unregister sysctl before tearing down listen socket
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (246 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 247/602] ice: fix LAG recipe to profile association Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 249/602] net: airoha: fix ETS channel derivation in airoha_tc_setup_qdisc_ets() Greg Kroah-Hartman
` (357 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, AutonomousCodeSecurity,
Allison Henderson, Cen Zhang (Microsoft), Jakub Kicinski,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cen Zhang (Microsoft) <blbllhy@gmail.com>
[ Upstream commit 167e54c703ccd4fa028feb568b0d1002020cff86 ]
rds_tcp_exit_net() frees the per-netns RDS TCP listen socket via
rds_tcp_kill_sock() before unregistering the per-netns sysctl table. Since
rds_tcp_skbuf_handler() derives the netns from
rtn->rds_tcp_listen_sock->sk, a concurrent sysctl write can race with
netns teardown and dereference the freed socket/sk.
KASAN reports the race as:
BUG: KASAN: slab-use-after-free in rds_tcp_skbuf_handler+0x2aa/0x2e0
rds_tcp_skbuf_handler net/rds/tcp.c:721
proc_sys_call_handler fs/proc/proc_sysctl.c
vfs_write fs/read_write.c
__x64_sys_pwrite64 fs/read_write.c
Fix this by unregistering the RDS TCP sysctl table before calling
rds_tcp_kill_sock(). unregister_net_sysctl_table() prevents new sysctl
handlers from starting and waits for in-flight handlers to finish, so
the listen socket can then be released safely. The fix was tested
against the linked reproducer.
Fixes: 7f5611cbc487 ("rds: sysctl: rds_tcp_{rcv,snd}buf: avoid using current->nsproxy")
Reported-by: AutonomousCodeSecurity@microsoft.com
Link: https://lore.kernel.org/all/20260719203718.9680-1-blbllhy@gmail.com
Reviewed-by: Allison Henderson <achender@kernel.org>
Signed-off-by: Cen Zhang (Microsoft) <blbllhy@gmail.com>
Link: https://patch.msgid.link/20260719210357.10179-1-blbllhy@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/rds/tcp.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/rds/tcp.c b/net/rds/tcp.c
index b66dfcc3efaa0f..06a2d8d48bbacf 100644
--- a/net/rds/tcp.c
+++ b/net/rds/tcp.c
@@ -637,13 +637,13 @@ static void __net_exit rds_tcp_exit_net(struct net *net)
{
struct rds_tcp_net *rtn = net_generic(net, rds_tcp_netid);
- rds_tcp_kill_sock(net);
-
if (rtn->rds_tcp_sysctl)
unregister_net_sysctl_table(rtn->rds_tcp_sysctl);
if (net != &init_net)
kfree(rtn->ctl_table);
+
+ rds_tcp_kill_sock(net);
}
static struct pernet_operations rds_tcp_net_ops = {
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 249/602] net: airoha: fix ETS channel derivation in airoha_tc_setup_qdisc_ets()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (247 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 248/602] rds: tcp: unregister sysctl before tearing down listen socket Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 250/602] bpf, sockmap: Fix cork use-after-free in tcp_bpf_sendmsg() Greg Kroah-Hartman
` (356 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Simon Horman, Lorenzo Bianconi,
Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <lorenzo@kernel.org>
[ Upstream commit 649ea07fc25a17aa51bff710baac1ab161022a7c ]
Derive the hardware QoS channel from opt->parent instead of opt->handle
in airoha_tc_setup_qdisc_ets(). The ETS qdisc handle is either
user-specified or auto-allocated by qdisc_alloc_handle() and bears no
relation to the HTB leaf classid that identifies the hardware channel.
HTB derives the channel from TC_H_MIN(opt->classid), and ETS is always
attached as a child of an HTB leaf, so its opt->parent matches that
classid. Using opt->handle instead can cause two ETS qdiscs on different
HTB leaves to collide on the same hardware channel, corrupting scheduler
configuration and stats.
Fixes: 20bf7d07c956 ("net: airoha: Add sched ETS offload support")
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20260720-airoha-ets-handle-fix-v2-1-6f7129ddc06f@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/airoha/airoha_eth.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index db4b87c17a2864..58e5791e9cd4d4 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -2803,8 +2803,7 @@ static int airoha_tc_setup_qdisc_ets(struct airoha_gdm_port *port,
if (opt->parent == TC_H_ROOT)
return -EINVAL;
- channel = TC_H_MAJ(opt->handle) >> 16;
- channel = channel % AIROHA_NUM_QOS_CHANNELS;
+ channel = TC_H_MIN(opt->parent) % AIROHA_NUM_QOS_CHANNELS;
switch (opt->command) {
case TC_ETS_REPLACE:
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 250/602] bpf, sockmap: Fix cork use-after-free in tcp_bpf_sendmsg()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (248 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 249/602] net: airoha: fix ETS channel derivation in airoha_tc_setup_qdisc_ets() Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 251/602] drm: renesas: rzg2l_mipi_dsi: Increase reset deassertion delay Greg Kroah-Hartman
` (355 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Chengfeng Ye, Emil Tsalapatis,
Jakub Sitnicki, Eduard Zingerman, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chengfeng Ye <nicoyip.dev@gmail.com>
[ Upstream commit 2d66a033864e27ab8d5e44cb36f31d9d2413bee4 ]
tcp_bpf_sendmsg() keeps msg_tx across sk_stream_wait_memory(), which
drops and reacquires the socket lock. Its error path tries to decide
whether msg_tx names the local temporary message by comparing it with
the current value of psock->cork.
This comparison is unsafe when two threads send on the same socket:
Thread A Thread B
msg_tx = psock->cork
sk_msg_alloc() fails
sk_stream_wait_memory()
releases the socket lock acquires the socket lock
completes the cork
psock->cork = NULL
frees the cork
reacquires the socket lock
msg_tx != psock->cork
sk_msg_free(msg_tx)
The stale cork is therefore mistaken for the local temporary message
and freed again. KASAN reported:
BUG: KASAN: slab-use-after-free in sk_msg_free+0x49/0x50
Read of size 4 at addr ffff88810c908800 by task poc/90
Call Trace:
sk_msg_free+0x49/0x50
tcp_bpf_sendmsg+0x14f5/0x1cc0
__sys_sendto+0x32c/0x3a0
__x64_sys_sendto+0xdb/0x1b0
Allocated by task 89:
__kasan_kmalloc+0x8f/0xa0
tcp_bpf_sendmsg+0x16b3/0x1cc0
Freed by task 91:
__kasan_slab_free+0x43/0x70
kfree+0x131/0x3c0
tcp_bpf_sendmsg+0xec3/0x1cc0
msg_tx can only name the stack-local tmp or the shared cork. Check for
tmp directly so a changed psock->cork cannot turn a shared message into
an apparent local one.
Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface")
Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com>
Link: https://lore.kernel.org/bpf/87fr18lmzo.fsf%40cloudflare.com/
Link: https://lore.kernel.org/netdev/20260719161630.2901208-1-nicoyip.dev%40gmail.com/ [v1]
Link: https://patch.msgid.link/20260724103856.3399001-1-nicoyip.dev@gmail.com
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/ipv4/tcp_bpf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c
index b9a58fde9c31b7..132ffc13087f5a 100644
--- a/net/ipv4/tcp_bpf.c
+++ b/net/ipv4/tcp_bpf.c
@@ -590,7 +590,7 @@ static int tcp_bpf_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
wait_for_memory:
err = sk_stream_wait_memory(sk, &timeo);
if (err) {
- if (msg_tx && msg_tx != psock->cork)
+ if (msg_tx == &tmp)
sk_msg_free(sk, msg_tx);
goto out_err;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 251/602] drm: renesas: rzg2l_mipi_dsi: Increase reset deassertion delay
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (249 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 250/602] bpf, sockmap: Fix cork use-after-free in tcp_bpf_sendmsg() Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 252/602] drm/rockchip: cdn-dp: add missing check in cdn_dp_config_video() Greg Kroah-Hartman
` (354 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Tommaso Merciai, Biju Das
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Biju Das <biju.das.jz@bp.renesas.com>
commit 7cbba8a8ba0219a267844d3116dbc77cecb4fcf8 upstream.
The RZ/G2L hardware manual (Rev. 1.50, May 2025), Section 34.4.2.1,
requires waiting at least 1 msec after deasserting the CMN_RSTB signal
before the DSI-Tx module is ready. Increase the delay from 1 usec to
1 msec by replacing udelay(1) with fsleep(1000) for RZ/G2L SoCs.
Fixes: 7a043f978ed1 ("drm: rcar-du: Add RZ/G2L DSI driver")
Cc: stable@vger.kernel.org
Reviewed-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
Tested-by: Tommaso Merciai <tommaso.merciai.xr@bp.renesas.com>
Link: https://patch.msgid.link/20260330104450.128512-3-biju.das.jz@bp.renesas.com
Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
@@ -238,7 +238,7 @@ static int rzg2l_mipi_dsi_dphy_init(stru
if (ret < 0)
return ret;
- udelay(1);
+ fsleep(1000);
return 0;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 252/602] drm/rockchip: cdn-dp: add missing check in cdn_dp_config_video()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (250 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 251/602] drm: renesas: rzg2l_mipi_dsi: Increase reset deassertion delay Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 253/602] drm/imagination: Count paired job fence as dependency in prepare_job() Greg Kroah-Hartman
` (353 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sergey Shtylyov, Chaoyi Chen,
Heiko Stuebner
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sergey Shtylyov <s.shtylyov@auroraos.dev>
commit 46c31e1604d121221167cb09380de8c7d53290b9 upstream.
The result of cdn_dp_reg_write() is checked everywhere (with the error
being logged by the callers) except one place in cdn_dp_config_video().
Add the missing result check, bailing out early on error...
Found by Linux Verification Center (linuxtesting.org) with the Svace static
analysis tool.
Fixes: 1a0f7ed3abe2 ("drm/rockchip: cdn-dp: add cdn DP support for rk3399")
Signed-off-by: Sergey Shtylyov <s.shtylyov@auroraos.dev>
Cc: stable@vger.kernel.org
Reviewed-by: Chaoyi Chen <chaoyi.chen@rock-chips.com>
Signed-off-by: Heiko Stuebner <heiko@sntech.de>
Link: https://patch.msgid.link/adf6b313-f7db-4d8f-9000-8c65446ba041@auroraos.dev
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/rockchip/cdn-dp-reg.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/gpu/drm/rockchip/cdn-dp-reg.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-reg.c
@@ -683,6 +683,8 @@ int cdn_dp_config_video(struct cdn_dp_de
val = div_u64(8 * (symbol + 1), bit_per_pix) - val;
val += 2;
ret = cdn_dp_reg_write(dp, DP_VC_TABLE(15), val);
+ if (ret)
+ goto err_config_video;
switch (video->color_depth) {
case 6:
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 253/602] drm/imagination: Count paired job fence as dependency in prepare_job()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (251 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 252/602] drm/rockchip: cdn-dp: add missing check in cdn_dp_config_video() Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 254/602] drm/bridge: cdns-dsi: Replace deprecated UNIVERSAL_DEV_PM_OPS() Greg Kroah-Hartman
` (352 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Alessio Belle, Brajesh Gupta,
Matt Coster
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alessio Belle <alessio.belle@imgtec.com>
commit 9cd74f935306cd857f46686975c43383e1d95f94 upstream.
The DRM scheduler's prepare_job() callback counts the remaining
non-signaled native dependencies for a job, preventing job submission
until those (plus job data and fence update) can fit in the job queue's
CCCB.
This means checking which dependencies can be waited upon in the
firmware, i.e. whether they are backed by a UFO object, i.e. whether
their drm_sched_fence::parent has been assigned to a
pvr_queue_fence::base fence. That happens when the job owning the fence
is submitted to the firmware.
Paired geometry and fragment jobs are submitted at the same time, which
means the dependency between them can't be checked this way before
submission.
Update job_count_remaining_native_deps() to take into account the
dependency between paired jobs.
This fixes cases where prepare_job() underestimated the space left in
an almost full fragment CCCB, wrongly unblocking run_job(), which then
returned early without writing the full sequence of commands to the
CCCB.
The above lead to kernel warnings such as the following and potentially
job timeouts (depending on waiters on the missing commands):
[ 375.702979] WARNING: drivers/gpu/drm/imagination/pvr_cccb.c:178 at pvr_cccb_write_command_with_header+0x2c4/0x330 [powervr], CPU#1: kworker/u16:3/47
[ 375.703160] Modules linked in:
[ 375.703571] CPU: 1 UID: 0 PID: 47 Comm: kworker/u16:3 Tainted: G W 7.0.0-rc2-g817eb6b11ad5 #40 PREEMPT
[ 375.703613] Tainted: [W]=WARN
[ 375.703627] Hardware name: Texas Instruments AM625 SK (DT)
[ 375.703645] Workqueue: powervr-sched drm_sched_run_job_work [gpu_sched]
[ 375.703741] pstate: 80000005 (Nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[ 375.703764] pc : pvr_cccb_write_command_with_header+0x2c4/0x330 [powervr]
[ 375.703847] lr : pvr_queue_submit_job_to_cccb+0x578/0xa70 [powervr]
[ 375.703921] sp : ffff800084a97650
[ 375.703934] x29: ffff800084a97740 x28: 0000000000000958 x27: ffff80008565d000
[ 375.703979] x26: 0000000000000030 x25: ffff800084a97680 x24: 0000000000001000
[ 375.704017] x23: ffff800084a97820 x22: 1ffff00010952ecc x21: 0000000000000008
[ 375.704056] x20: 00000000000006a8 x19: ffff00002ff7da88 x18: 0000000000000000
[ 375.704093] x17: 0000000020020000 x16: 0000000000020000 x15: 0000000000000000
[ 375.704132] x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000
[ 375.704168] x11: 000000000000f2f2 x10: 00000000f3000000 x9 : 00000000f3f3f3f3
[ 375.704206] x8 : 00000000f2f2f200 x7 : ffff700010952ecc x6 : 0000000000000008
[ 375.704243] x5 : 0000000000000000 x4 : 1ffff00010acba00 x3 : 0000000000000000
[ 375.704279] x2 : 0000000000000007 x1 : 0000000000000fff x0 : 000000000000002f
[ 375.704317] Call trace:
[ 375.704331] pvr_cccb_write_command_with_header+0x2c4/0x330 [powervr] (P)
[ 375.704411] pvr_queue_submit_job_to_cccb+0x578/0xa70 [powervr]
[ 375.704487] pvr_queue_run_job+0x3a4/0x990 [powervr]
[ 375.704562] drm_sched_run_job_work+0x580/0xd48 [gpu_sched]
[ 375.704623] process_one_work+0x520/0x1288
[ 375.704658] worker_thread+0x3f0/0xb3c
[ 375.704680] kthread+0x334/0x3d8
[ 375.704706] ret_from_fork+0x10/0x20
[ 375.704736] ---[ end trace 0000000000000000 ]---
Fixes: eaf01ee5ba28 ("drm/imagination: Implement job submission and scheduling")
Cc: stable@vger.kernel.org
Signed-off-by: Alessio Belle <alessio.belle@imgtec.com>
Reviewed-by: Brajesh Gupta <brajesh.gupta@imgtec.com>
Link: https://patch.msgid.link/20260330-job-submission-fixes-cleanup-v1-1-7de8c09cef8c@imgtec.com
Signed-off-by: Matt Coster <matt.coster@imgtec.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/imagination/pvr_queue.c | 27 +++++++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
--- a/drivers/gpu/drm/imagination/pvr_queue.c
+++ b/drivers/gpu/drm/imagination/pvr_queue.c
@@ -179,7 +179,7 @@ static const struct dma_fence_ops pvr_qu
/**
* to_pvr_queue_job_fence() - Return a pvr_queue_fence object if the fence is
- * backed by a UFO.
+ * already backed by a UFO.
* @f: The dma_fence to turn into a pvr_queue_fence.
*
* Return:
@@ -356,6 +356,15 @@ static u32 job_cmds_size(struct pvr_job
pvr_cccb_get_size_of_cmd_with_hdr(job->cmd_len);
}
+static bool
+is_paired_job_fence(struct dma_fence *fence, struct pvr_job *job)
+{
+ /* This assumes "fence" is one of "job"'s drm_sched_job::dependencies */
+ return job->type == DRM_PVR_JOB_TYPE_FRAGMENT &&
+ job->paired_job &&
+ &job->paired_job->base.s_fence->scheduled == fence;
+}
+
/**
* job_count_remaining_native_deps() - Count the number of non-signaled native dependencies.
* @job: Job to operate on.
@@ -371,6 +380,17 @@ static unsigned long job_count_remaining
xa_for_each(&job->base.dependencies, index, fence) {
struct pvr_queue_fence *jfence;
+ if (is_paired_job_fence(fence, job)) {
+ /*
+ * A fence between paired jobs won't resolve to a pvr_queue_fence (i.e.
+ * be backed by a UFO) until the jobs have been submitted, together.
+ * The submitting code will insert a partial render fence command for this.
+ */
+ WARN_ON(dma_fence_is_signaled(fence));
+ remaining_count++;
+ continue;
+ }
+
jfence = to_pvr_queue_job_fence(fence);
if (!jfence)
continue;
@@ -630,9 +650,8 @@ static void pvr_queue_submit_job_to_cccb
if (!jfence)
continue;
- /* Skip the partial render fence, we will place it at the end. */
- if (job->type == DRM_PVR_JOB_TYPE_FRAGMENT && job->paired_job &&
- &job->paired_job->base.s_fence->scheduled == fence)
+ /* This fence will be placed last, as partial render fence. */
+ if (is_paired_job_fence(fence, job))
continue;
if (dma_fence_is_signaled(&jfence->base))
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 254/602] drm/bridge: cdns-dsi: Replace deprecated UNIVERSAL_DEV_PM_OPS()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (252 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 253/602] drm/imagination: Count paired job fence as dependency in prepare_job() Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 255/602] drm/dp/mst: fix OOB reads in remote DPCD/I2C sideband reply parsers Greg Kroah-Hartman
` (351 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Tomi Valkeinen, Vitor Soares,
Luca Ceresoli
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vitor Soares <vitor.soares@toradex.com>
commit 2d8b08844c0ecc6f2002fa68711e779aa18c8585 upstream.
The deprecated UNIVERSAL_DEV_PM_OPS() macro uses the provided callbacks
for both runtime PM and system sleep. This causes the DSI clocks to be
disabled twice: once during runtime suspend and again during system
suspend, resulting in a WARN message from the clock framework when
attempting to disable already-disabled clocks.
[ 84.384540] clk:231:5 already disabled
[ 84.388314] WARNING: CPU: 2 PID: 531 at /drivers/clk/clk.c:1181 clk_core_disable+0xa4/0xac
...
[ 84.579183] Call trace:
[ 84.581624] clk_core_disable+0xa4/0xac
[ 84.585457] clk_disable+0x30/0x4c
[ 84.588857] cdns_dsi_suspend+0x20/0x58 [cdns_dsi]
[ 84.593651] pm_generic_suspend+0x2c/0x44
[ 84.597661] ti_sci_pd_suspend+0xbc/0x15c
[ 84.601670] dpm_run_callback+0x8c/0x14c
[ 84.605588] __device_suspend+0x1a0/0x56c
[ 84.609594] dpm_suspend+0x17c/0x21c
[ 84.613165] dpm_suspend_start+0xa0/0xa8
[ 84.617083] suspend_devices_and_enter+0x12c/0x634
[ 84.621872] pm_suspend+0x1fc/0x368
To address this issue, replace UNIVERSAL_DEV_PM_OPS() with
RUNTIME_PM_OPS(). Bridge and panel drivers should only deal with runtime
PM, as the DRM framework manages system-wide power transitions through
the bridge enable() and disable() hooks.
Link: https://lore.kernel.org/all/fbde0659-78f3-46e4-98cf-d832f765a18b@ideasonboard.com/
Cc: stable@vger.kernel.org # 6.1.x
Fixes: e19233955d9e ("drm/bridge: Add Cadence DSI driver")
Reviewed-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Signed-off-by: Vitor Soares <vitor.soares@toradex.com>
Reviewed-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
Link: https://patch.msgid.link/20260505134705.188661-2-ivitro@gmail.com
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -1157,7 +1157,7 @@ static const struct mipi_dsi_host_ops cd
.transfer = cdns_dsi_transfer,
};
-static int __maybe_unused cdns_dsi_resume(struct device *dev)
+static int cdns_dsi_resume(struct device *dev)
{
struct cdns_dsi *dsi = dev_get_drvdata(dev);
@@ -1168,7 +1168,7 @@ static int __maybe_unused cdns_dsi_resum
return 0;
}
-static int __maybe_unused cdns_dsi_suspend(struct device *dev)
+static int cdns_dsi_suspend(struct device *dev)
{
struct cdns_dsi *dsi = dev_get_drvdata(dev);
@@ -1178,8 +1178,9 @@ static int __maybe_unused cdns_dsi_suspe
return 0;
}
-static UNIVERSAL_DEV_PM_OPS(cdns_dsi_pm_ops, cdns_dsi_suspend, cdns_dsi_resume,
- NULL);
+static const struct dev_pm_ops cdns_dsi_pm_ops = {
+ RUNTIME_PM_OPS(cdns_dsi_suspend, cdns_dsi_resume, NULL)
+};
static int cdns_dsi_drm_probe(struct platform_device *pdev)
{
@@ -1326,7 +1327,7 @@ static struct platform_driver cdns_dsi_p
.driver = {
.name = "cdns-dsi",
.of_match_table = cdns_dsi_of_match,
- .pm = &cdns_dsi_pm_ops,
+ .pm = pm_ptr(&cdns_dsi_pm_ops),
},
};
module_platform_driver(cdns_dsi_platform_driver);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 255/602] drm/dp/mst: fix OOB reads in remote DPCD/I2C sideband reply parsers
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (253 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 254/602] drm/bridge: cdns-dsi: Replace deprecated UNIVERSAL_DEV_PM_OPS() Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 256/602] drm/dp/mst: fix buffer overflows in sideband chunk accumulation Greg Kroah-Hartman
` (350 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Ashutosh Desai, Lyude Paul
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ashutosh Desai <ashutoshdesai993@gmail.com>
commit 1a8f537f5a1eeac941f262fe73078d6b08ba83c0 upstream.
drm_dp_sideband_parse_remote_dpcd_read() reads num_bytes from the raw
message and then unconditionally does:
memcpy(bytes, &raw->msg[idx], num_bytes);
without checking that idx + num_bytes <= raw->curlen. raw->msg[] is
256 bytes; if a malicious or misbehaving MST hub sets num_bytes larger
than the remaining payload, the memcpy reads past the received data
into whatever follows in raw->msg[].
drm_dp_sideband_parse_remote_i2c_read_ack() has the same flaw (noted
with a /* TODO check */ comment since the code was introduced).
Fix both functions by using a single combined check
(idx + num_bytes > curlen) before each memcpy. Since num_bytes is u8,
it is always >= 0, so this strictly subsumes the simpler idx > curlen
form and no separate step is needed.
Fixes: ad7f8a1f9ced ("drm/helper: add Displayport multi-stream helper (v0.6)")
Cc: <stable@vger.kernel.org> # v3.17+
Signed-off-by: Ashutosh Desai <ashutoshdesai993@gmail.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
[added missing fixes tag]
Signed-off-by: Lyude Paul <lyude@redhat.com>
Link: https://patch.msgid.link/20260510201733.2882224-1-ashutoshdesai993@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/display/drm_dp_mst_topology.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -862,7 +862,7 @@ static bool drm_dp_sideband_parse_remote
goto fail_len;
repmsg->u.remote_dpcd_read_ack.num_bytes = raw->msg[idx];
idx++;
- if (idx > raw->curlen)
+ if (idx + repmsg->u.remote_dpcd_read_ack.num_bytes > raw->curlen)
goto fail_len;
memcpy(repmsg->u.remote_dpcd_read_ack.bytes, &raw->msg[idx], repmsg->u.remote_dpcd_read_ack.num_bytes);
@@ -898,7 +898,9 @@ static bool drm_dp_sideband_parse_remote
goto fail_len;
repmsg->u.remote_i2c_read_ack.num_bytes = raw->msg[idx];
idx++;
- /* TODO check */
+ if (idx + repmsg->u.remote_i2c_read_ack.num_bytes > raw->curlen)
+ goto fail_len;
+
memcpy(repmsg->u.remote_i2c_read_ack.bytes, &raw->msg[idx], repmsg->u.remote_i2c_read_ack.num_bytes);
return true;
fail_len:
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 256/602] drm/dp/mst: fix buffer overflows in sideband chunk accumulation
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (254 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 255/602] drm/dp/mst: fix OOB reads in remote DPCD/I2C sideband reply parsers Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 257/602] drm/imagination: Fit paired fragment job in the correct CCCB Greg Kroah-Hartman
` (349 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Ashutosh Desai, Lyude Paul
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ashutosh Desai <ashutoshdesai993@gmail.com>
commit 55bd5e685bda455b9b50c835f8c8442d52a344a3 upstream.
drm_dp_sideband_append_payload() has three related bugs when processing
device-provided sideband reply data:
1. Zero-length curchunk_len underflow: msg_len is a 6-bit field taken
directly from the DP sideband header. If a device sends msg_len=0,
curchunk_len is set to zero. The condition (curchunk_idx >= curchunk_len)
is immediately true, and curchunk_len-1 wraps to 255 (u8 underflow).
drm_dp_msg_data_crc4() reads 255 bytes from chunk[48], then memcpy()
writes 255 bytes into msg[], both far out of bounds.
2. chunk[48] overflow: curchunk_len can reach 63 (6-bit field). chunk[] is
only 48 bytes. Multi-iteration payload assembly appends 16-byte blocks
until curchunk_idx reaches curchunk_len, writing up to 15 bytes past
the end of chunk[] into msg[].
3. msg[256] overflow: each chunk contributes (curchunk_len-1) bytes to
msg[]. No check ensures curlen + (curchunk_len-1) stays within msg[256],
so the memcpy can spill into adjacent struct fields.
All three are reachable from any DP MST device that can forge sideband
reply messages on a physical connection.
Fixes: ad7f8a1f9ced ("drm/helper: add Displayport multi-stream helper (v0.6)")
Cc: <stable@vger.kernel.org> # v3.17+
Signed-off-by: Ashutosh Desai <ashutoshdesai993@gmail.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
Signed-off-by: Lyude Paul <lyude@redhat.com>
Link: https://patch.msgid.link/20260410041901.2438960-1-ashutoshdesai993@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/display/drm_dp_mst_topology.c | 9 +++++++++
1 file changed, 9 insertions(+)
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -780,6 +780,12 @@ static bool drm_dp_sideband_append_paylo
{
u8 crc4;
+ /* curchunk_len must be >= 1 (min 1 CRC byte) and fit in chunk[] */
+ if (!msg->curchunk_len ||
+ msg->curchunk_len > ARRAY_SIZE(msg->chunk) ||
+ msg->curchunk_idx + replybuflen > ARRAY_SIZE(msg->chunk))
+ return false;
+
memcpy(&msg->chunk[msg->curchunk_idx], replybuf, replybuflen);
msg->curchunk_idx += replybuflen;
@@ -790,6 +796,9 @@ static bool drm_dp_sideband_append_paylo
print_hex_dump(KERN_DEBUG, "wrong crc",
DUMP_PREFIX_NONE, 16, 1,
msg->chunk, msg->curchunk_len, false);
+ /* Guard against accumulated msg[] overflow */
+ if (msg->curlen + msg->curchunk_len - 1 > ARRAY_SIZE(msg->msg))
+ return false;
/* copy chunk into bigger msg */
memcpy(&msg->msg[msg->curlen], msg->chunk, msg->curchunk_len - 1);
msg->curlen += msg->curchunk_len - 1;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 257/602] drm/imagination: Fit paired fragment job in the correct CCCB
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (255 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 256/602] drm/dp/mst: fix buffer overflows in sideband chunk accumulation Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 258/602] drm/dp/mst: fix OOB reads on 2-byte fields in sideband reply parsers Greg Kroah-Hartman
` (348 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Alessio Belle, Brajesh Gupta,
Matt Coster
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alessio Belle <alessio.belle@imgtec.com>
commit 4baf9e70cb756d78dd56419f8baee2978a72d0c3 upstream.
For geometry jobs with a paired fragment job, at the moment, the
DRM scheduler's prepare_job() callback:
- checks for internal (driver) dependencies for the geometry job;
- calls into pvr_queue_get_paired_frag_job_dep() to check for external
dependencies for the fragment job (the two jobs are submitted together
but the common scheduler code doesn't know about it, so this needs to
be done at this point in time);
- calls into the prepare_job() callback again, but for the fragment job,
to check its internal dependencies as well, passing the fragment job's
drm_sched_job and the geometry job's drm_sched_entity / pvr_queue.
The problem with the last step is that pvr_queue_prepare_job() doesn't
always take the mismatched fragment job and geometry queue into account,
in particular when checking whether there is space for the fragment
command to be submitted, so the code ends up checking for space in the
geometry (i.e. wrong) CCCB.
The rest of the nested prepare_job() callback happens to work fine at
the moment as the other internal dependencies are not relevant for a
paired fragment job.
Move the initialisation of a paired fragment job's done fence and CCCB
fence to pvr_queue_get_paired_frag_job_dep(), inferring the correct
queue from the fragment job itself.
This fixes cases where prepare_job() wrongly assumed that there was
enough space for a paired fragment job in its own CCCB, unblocking
run_job(), which then returned early without writing the full sequence
of commands to the CCCB.
The above lead to kernel warnings such as the following and potentially
job timeouts (depending on waiters on the missing commands):
[ 552.421075] WARNING: drivers/gpu/drm/imagination/pvr_cccb.c:178 at pvr_cccb_write_command_with_header+0x2c4/0x330 [powervr], CPU#2: kworker/u16:5/63
[ 552.421230] Modules linked in:
[ 552.421592] CPU: 2 UID: 0 PID: 63 Comm: kworker/u16:5 Tainted: G W 7.0.0-rc2-gc5d053e4dccb #39 PREEMPT
[ 552.421625] Tainted: [W]=WARN
[ 552.421637] Hardware name: Texas Instruments AM625 SK (DT)
[ 552.421655] Workqueue: powervr-sched drm_sched_run_job_work [gpu_sched]
[ 552.421744] pstate: 80000005 (Nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[ 552.421766] pc : pvr_cccb_write_command_with_header+0x2c4/0x330 [powervr]
[ 552.421850] lr : pvr_queue_submit_job_to_cccb+0x57c/0xa74 [powervr]
[ 552.421923] sp : ffff800084c47650
[ 552.421936] x29: ffff800084c47740 x28: 0000000000000df8 x27: ffff800088a77000
[ 552.421979] x26: 0000000000000030 x25: ffff800084c47680 x24: 0000000000001000
[ 552.422017] x23: ffff800084c47820 x22: 1ffff00010988ecc x21: 0000000000000008
[ 552.422055] x20: 0000000000000208 x19: ffff000006ad5a88 x18: 0000000000000000
[ 552.422093] x17: 0000000020020000 x16: 0000000000020000 x15: 0000000000000000
[ 552.422130] x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000
[ 552.422167] x11: 000000000000f2f2 x10: 00000000f3000000 x9 : 00000000f3f3f3f3
[ 552.422204] x8 : 00000000f2f2f200 x7 : ffff700010988ecc x6 : 0000000000000008
[ 552.422241] x5 : 0000000000000000 x4 : 1ffff0001114ee00 x3 : 0000000000000000
[ 552.422278] x2 : 0000000000000007 x1 : 0000000000000fff x0 : 000000000000002f
[ 552.422316] Call trace:
[ 552.422330] pvr_cccb_write_command_with_header+0x2c4/0x330 [powervr] (P)
[ 552.422411] pvr_queue_submit_job_to_cccb+0x57c/0xa74 [powervr]
[ 552.422486] pvr_queue_run_job+0x3a4/0x990 [powervr]
[ 552.422562] drm_sched_run_job_work+0x580/0xd48 [gpu_sched]
[ 552.422623] process_one_work+0x520/0x1288
[ 552.422657] worker_thread+0x3f0/0xb3c
[ 552.422679] kthread+0x334/0x3d8
[ 552.422706] ret_from_fork+0x10/0x20
Fixes: eaf01ee5ba28 ("drm/imagination: Implement job submission and scheduling")
Cc: stable@vger.kernel.org
Signed-off-by: Alessio Belle <alessio.belle@imgtec.com>
Reviewed-by: Brajesh Gupta <brajesh.gupta@imgtec.com>
Link: https://patch.msgid.link/20260330-job-submission-fixes-cleanup-v1-2-7de8c09cef8c@imgtec.com
Signed-off-by: Matt Coster <matt.coster@imgtec.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/imagination/pvr_queue.c | 32 ++++++++++++++------------------
1 file changed, 14 insertions(+), 18 deletions(-)
--- a/drivers/gpu/drm/imagination/pvr_queue.c
+++ b/drivers/gpu/drm/imagination/pvr_queue.c
@@ -488,10 +488,11 @@ pvr_queue_get_job_kccb_fence(struct pvr_
}
static struct dma_fence *
-pvr_queue_get_paired_frag_job_dep(struct pvr_queue *queue, struct pvr_job *job)
+pvr_queue_get_paired_frag_job_dep(struct pvr_job *job)
{
struct pvr_job *frag_job = job->type == DRM_PVR_JOB_TYPE_GEOMETRY ?
job->paired_job : NULL;
+ struct pvr_queue *frag_queue = frag_job ? frag_job->ctx->queues.fragment : NULL;
struct dma_fence *f;
unsigned long index;
@@ -510,7 +511,10 @@ pvr_queue_get_paired_frag_job_dep(struct
return dma_fence_get(f);
}
- return frag_job->base.sched->ops->prepare_job(&frag_job->base, &queue->entity);
+ /* Initialize the paired fragment job's done_fence, so we can signal it. */
+ pvr_queue_job_fence_init(frag_job->done_fence, frag_queue);
+
+ return pvr_queue_get_job_cccb_fence(frag_queue, frag_job);
}
/**
@@ -529,11 +533,6 @@ pvr_queue_prepare_job(struct drm_sched_j
struct pvr_queue *queue = container_of(s_entity, struct pvr_queue, entity);
struct dma_fence *internal_dep = NULL;
- /*
- * Initialize the done_fence, so we can signal it. This must be done
- * here because otherwise by the time of run_job() the job will end up
- * in the pending list without a valid fence.
- */
if (job->type == DRM_PVR_JOB_TYPE_FRAGMENT && job->paired_job) {
/*
* This will be called on a paired fragment job after being
@@ -543,18 +542,15 @@ pvr_queue_prepare_job(struct drm_sched_j
*/
if (job->paired_job->has_pm_ref)
return NULL;
-
- /*
- * In this case we need to use the job's own ctx to initialise
- * the done_fence. The other steps are done in the ctx of the
- * paired geometry job.
- */
- pvr_queue_job_fence_init(job->done_fence,
- job->ctx->queues.fragment);
- } else {
- pvr_queue_job_fence_init(job->done_fence, queue);
}
+ /*
+ * Initialize the done_fence, so we can signal it. This must be done
+ * here because otherwise by the time of run_job() the job will end up
+ * in the pending list without a valid fence.
+ */
+ pvr_queue_job_fence_init(job->done_fence, queue);
+
/* CCCB fence is used to make sure we have enough space in the CCCB to
* submit our commands.
*/
@@ -575,7 +571,7 @@ pvr_queue_prepare_job(struct drm_sched_j
/* The paired job fence should come last, when everything else is ready. */
if (!internal_dep)
- internal_dep = pvr_queue_get_paired_frag_job_dep(queue, job);
+ internal_dep = pvr_queue_get_paired_frag_job_dep(job);
return internal_dep;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 258/602] drm/dp/mst: fix OOB reads on 2-byte fields in sideband reply parsers
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (256 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 257/602] drm/imagination: Fit paired fragment job in the correct CCCB Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 259/602] drm/amdgpu/uvd: Fix forcing MSG, FB BOs into VCPU segment when it isnt at 0 (v2) Greg Kroah-Hartman
` (347 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Ashutosh Desai, Lyude Paul
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ashutosh Desai <ashutoshdesai993@gmail.com>
commit 6b89ba3dba2f583626fb693e47e951ffb8bf591f upstream.
Three sideband reply parsers read 16-bit fields as:
val = (raw->msg[idx] << 8) | (raw->msg[idx+1]);
and check bounds only after the fact. When idx == raw->curlen,
raw->msg[idx+1] reads one byte past the received message data into
the following struct fields (curchunk_len, curchunk_idx, curlen).
Affected functions:
- drm_dp_sideband_parse_enum_path_resources_ack()
full_payload_bw_number and avail_payload_bw_number fields
- drm_dp_sideband_parse_allocate_payload_ack()
allocated_pbn field
- drm_dp_sideband_parse_query_payload_ack()
allocated_pbn field
Fix by using a single combined check (idx + 2 > curlen) before each
2-byte read. Since the check is strictly tighter than idx > curlen,
no separate step is needed.
Fixes: ad7f8a1f9ced ("drm/helper: add Displayport multi-stream helper (v0.6)")
Cc: <stable@vger.kernel.org> # v3.17+
Signed-off-by: Ashutosh Desai <ashutoshdesai993@gmail.com>
Reviewed-by: Lyude Paul <lyude@redhat.com>
[added fixes tag]
Signed-off-by: Lyude Paul <lyude@redhat.com>
Link: https://patch.msgid.link/20260510203128.2884846-1-ashutoshdesai993@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/display/drm_dp_mst_topology.c | 17 ++++-------------
1 file changed, 4 insertions(+), 13 deletions(-)
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -925,16 +925,13 @@ static bool drm_dp_sideband_parse_enum_p
repmsg->u.path_resources.port_number = (raw->msg[idx] >> 4) & 0xf;
repmsg->u.path_resources.fec_capable = raw->msg[idx] & 0x1;
idx++;
- if (idx > raw->curlen)
+ if (idx + 2 > raw->curlen)
goto fail_len;
repmsg->u.path_resources.full_payload_bw_number = (raw->msg[idx] << 8) | (raw->msg[idx+1]);
idx += 2;
- if (idx > raw->curlen)
+ if (idx + 2 > raw->curlen)
goto fail_len;
repmsg->u.path_resources.avail_payload_bw_number = (raw->msg[idx] << 8) | (raw->msg[idx+1]);
- idx += 2;
- if (idx > raw->curlen)
- goto fail_len;
return true;
fail_len:
DRM_DEBUG_KMS("enum resource parse length fail %d %d\n", idx, raw->curlen);
@@ -952,12 +949,9 @@ static bool drm_dp_sideband_parse_alloca
goto fail_len;
repmsg->u.allocate_payload.vcpi = raw->msg[idx];
idx++;
- if (idx > raw->curlen)
+ if (idx + 2 > raw->curlen)
goto fail_len;
repmsg->u.allocate_payload.allocated_pbn = (raw->msg[idx] << 8) | (raw->msg[idx+1]);
- idx += 2;
- if (idx > raw->curlen)
- goto fail_len;
return true;
fail_len:
DRM_DEBUG_KMS("allocate payload parse length fail %d %d\n", idx, raw->curlen);
@@ -971,12 +965,9 @@ static bool drm_dp_sideband_parse_query_
repmsg->u.query_payload.port_number = (raw->msg[idx] >> 4) & 0xf;
idx++;
- if (idx > raw->curlen)
+ if (idx + 2 > raw->curlen)
goto fail_len;
repmsg->u.query_payload.allocated_pbn = (raw->msg[idx] << 8) | (raw->msg[idx + 1]);
- idx += 2;
- if (idx > raw->curlen)
- goto fail_len;
return true;
fail_len:
DRM_DEBUG_KMS("query payload parse length fail %d %d\n", idx, raw->curlen);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 259/602] drm/amdgpu/uvd: Fix forcing MSG, FB BOs into VCPU segment when it isnt at 0 (v2)
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (257 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 258/602] drm/dp/mst: fix OOB reads on 2-byte fields in sideband reply parsers Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 260/602] drm/amdgpu/uvd: Place VCPU BO only in VRAM for UVD 4.x and older Greg Kroah-Hartman
` (346 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Christian König,
Timur Kristóf, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf <timur.kristof@gmail.com>
commit 32bd35f068a3507a1b3922cd12ea2985fc58c85b upstream.
UVD 4.x and older can only access MSG, FEEDBACK buffers from a
specific 256M VRAM segment that the VCPU BO is also located in.
We already modify all placements of the given BO to ensure
the BO is placed within this segment.
Previously, it always assumed that the VCPU segment is
the first 256M of VRAM, even though under some conditions
the VCPU BO could be allocated outside this segment,
which made UVD non-functional as the BOs were
not inside the same segment as the UVD VCPU BO.
Solve that by using the segment where the VCPU BO actually is.
This fixes an issue with UVD failing to initialize on SI/CIK
when resizable BAR is enabled and the VCPU BO is allocated
in a different segment.
v2:
- For other BOs, keep using the same UVD segment as before.
Closes: https://gitlab.freedesktop.org/drm/amd/-/work_items/3851
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit cbfd4d3fc2061a1ec8e9d36e65973ac3e813358a)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 33 +++++++++++++++++++++++---------
1 file changed, 24 insertions(+), 9 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -135,7 +135,7 @@ MODULE_FIRMWARE(FIRMWARE_VEGA12);
MODULE_FIRMWARE(FIRMWARE_VEGA20);
static void amdgpu_uvd_idle_work_handler(struct work_struct *work);
-static void amdgpu_uvd_force_into_uvd_segment(struct amdgpu_bo *abo);
+static void amdgpu_uvd_force_into_vcpu_segment(struct amdgpu_bo *abo);
static int amdgpu_uvd_create_msg_bo_helper(struct amdgpu_device *adev,
uint32_t size,
@@ -158,7 +158,7 @@ static int amdgpu_uvd_create_msg_bo_help
amdgpu_bo_kunmap(bo);
amdgpu_bo_unpin(bo);
amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_VRAM);
- amdgpu_uvd_force_into_uvd_segment(bo);
+ amdgpu_uvd_force_into_vcpu_segment(bo);
r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
if (r)
goto err;
@@ -544,6 +544,24 @@ void amdgpu_uvd_free_handles(struct amdg
}
}
+static void amdgpu_uvd_force_into_vcpu_segment(struct amdgpu_bo *bo)
+{
+ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
+ struct amdgpu_bo *vcpu_bo = adev->uvd.inst[0].vcpu_bo;
+ struct amdgpu_res_cursor vcpu_cur;
+
+ amdgpu_res_first(vcpu_bo->tbo.resource, 0,
+ amdgpu_bo_size(vcpu_bo), &vcpu_cur);
+
+ bo->placement.num_placement = 1;
+ bo->placement.placement = &bo->placements[0];
+ bo->placements[0].fpfn = ALIGN_DOWN(vcpu_cur.start, SZ_256M) >> PAGE_SHIFT;
+ bo->placements[0].lpfn = bo->placements[0].fpfn + (SZ_256M >> PAGE_SHIFT);
+ bo->placements[0].mem_type = vcpu_bo->tbo.resource->mem_type;
+ if (bo->placements[0].mem_type == TTM_PL_VRAM)
+ bo->placements[0].flags |= TTM_PL_FLAG_CONTIGUOUS;
+}
+
static void amdgpu_uvd_force_into_uvd_segment(struct amdgpu_bo *abo)
{
int i;
@@ -594,13 +612,10 @@ static int amdgpu_uvd_cs_pass1(struct am
if (!ctx->parser->adev->uvd.address_64_bit) {
/* check if it's a message or feedback command */
cmd = amdgpu_ib_get_value(ctx->ib, ctx->idx) >> 1;
- if (cmd == 0x0 || cmd == 0x3) {
- /* yes, force it into VRAM */
- uint32_t domain = AMDGPU_GEM_DOMAIN_VRAM;
-
- amdgpu_bo_placement_from_domain(bo, domain);
- }
- amdgpu_uvd_force_into_uvd_segment(bo);
+ if (cmd == 0x0 || cmd == 0x3)
+ amdgpu_uvd_force_into_vcpu_segment(bo);
+ else
+ amdgpu_uvd_force_into_uvd_segment(bo);
r = ttm_bo_validate(&bo->tbo, &bo->placement, &tctx);
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 260/602] drm/amdgpu/uvd: Place VCPU BO only in VRAM for UVD 4.x and older
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (258 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 259/602] drm/amdgpu/uvd: Fix forcing MSG, FB BOs into VCPU segment when it isnt at 0 (v2) Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 261/602] drm/amdgpu: Fix amdgpu_bo_move() when old_mem and new_mem are both GTT Greg Kroah-Hartman
` (345 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Timur Kristóf,
Christian König, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf <timur.kristof@gmail.com>
commit 8002b744ad70055ef11ff7d0a7d685bfe8ffe6e4 upstream.
These UVD versions don't fully support GPUVM and are only
validated to work when their VCPU BO is placed in VRAM.
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 01b8dfc0660db5d6cdd62c22dc20f774a26ce853)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -188,6 +188,7 @@ int amdgpu_uvd_sw_init(struct amdgpu_dev
const struct common_firmware_header *hdr;
unsigned int family_id;
int i, j, r;
+ u32 vcpu_bo_domain;
INIT_DELAYED_WORK(&adev->uvd.idle_work, amdgpu_uvd_idle_work_handler);
@@ -319,12 +320,20 @@ int amdgpu_uvd_sw_init(struct amdgpu_dev
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
+ /* UVD 5.0 and newer HW can use 64 bit addressing. */
+ adev->uvd.address_64_bit =
+ !amdgpu_device_ip_block_version_cmp(adev, AMD_IP_BLOCK_TYPE_UVD, 5, 0);
+
+ vcpu_bo_domain = AMDGPU_GEM_DOMAIN_VRAM;
+ if (adev->uvd.address_64_bit)
+ vcpu_bo_domain |= AMDGPU_GEM_DOMAIN_GTT;
+
for (j = 0; j < adev->uvd.num_uvd_inst; j++) {
if (adev->uvd.harvest_config & (1 << j))
continue;
+
r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,
- AMDGPU_GEM_DOMAIN_VRAM |
- AMDGPU_GEM_DOMAIN_GTT,
+ vcpu_bo_domain,
&adev->uvd.inst[j].vcpu_bo,
&adev->uvd.inst[j].gpu_addr,
&adev->uvd.inst[j].cpu_addr);
@@ -339,10 +348,6 @@ int amdgpu_uvd_sw_init(struct amdgpu_dev
adev->uvd.filp[i] = NULL;
}
- /* from uvd v5.0 HW addressing capacity increased to 64 bits */
- if (!amdgpu_device_ip_block_version_cmp(adev, AMD_IP_BLOCK_TYPE_UVD, 5, 0))
- adev->uvd.address_64_bit = true;
-
r = amdgpu_uvd_create_msg_bo_helper(adev, 128 << 10, &adev->uvd.ib_bo);
if (r)
return r;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 261/602] drm/amdgpu: Fix amdgpu_bo_move() when old_mem and new_mem are both GTT
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (259 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 260/602] drm/amdgpu/uvd: Place VCPU BO only in VRAM for UVD 4.x and older Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 262/602] drm/amdgpu: validate CP_GFX_SHADOW chunk size in CS pass1 Greg Kroah-Hartman
` (344 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Timur Kristóf,
Christian König, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf <timur.kristof@gmail.com>
commit ee94a65f192c05c543b4d3ad7137cd696b5c18fc upstream.
The UVD code relies on GTT to GTT moves in order to ensure
that its BOs don't cross 256M segments.
Fixes: bfe5e585b44f ("drm/ttm: move last binding into the drivers.")
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 21fd45e5e2628d00b478590bcc3d14d3de5d45b6)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -501,6 +501,15 @@ static int amdgpu_bo_move(struct ttm_buf
if (new_mem->mem_type == TTM_PL_TT ||
new_mem->mem_type == AMDGPU_PL_PREEMPT) {
+ if (old_mem && (old_mem->mem_type == TTM_PL_TT ||
+ old_mem->mem_type == AMDGPU_PL_PREEMPT)) {
+ r = ttm_bo_wait_ctx(bo, ctx);
+ if (r)
+ return r;
+
+ amdgpu_ttm_backend_unbind(bo->bdev, bo->ttm);
+ }
+
r = amdgpu_ttm_backend_bind(bo->bdev, bo->ttm, new_mem);
if (r)
return r;
@@ -533,6 +542,15 @@ static int amdgpu_bo_move(struct ttm_buf
amdgpu_bo_move_notify(bo, evict, new_mem);
ttm_resource_free(bo, &bo->resource);
ttm_bo_assign_mem(bo, new_mem);
+ return 0;
+ }
+ if ((old_mem->mem_type == TTM_PL_TT ||
+ old_mem->mem_type == AMDGPU_PL_PREEMPT) &&
+ (new_mem->mem_type == TTM_PL_TT ||
+ new_mem->mem_type == AMDGPU_PL_PREEMPT)) {
+ amdgpu_bo_move_notify(bo, evict, new_mem);
+ ttm_resource_free(bo, &bo->resource);
+ ttm_bo_assign_mem(bo, new_mem);
return 0;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 262/602] drm/amdgpu: validate CP_GFX_SHADOW chunk size in CS pass1
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (260 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 261/602] drm/amdgpu: Fix amdgpu_bo_move() when old_mem and new_mem are both GTT Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 263/602] drm/nouveau: fix reversed error cleanup order in ucopy functions Greg Kroah-Hartman
` (343 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Alex Deucher, Mario Limonciello
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello <mario.limonciello@amd.com>
commit 84c4c36acd5c4b2558b5069f869a165b2c655c84 upstream.
Add a minimum-length check for the AMDGPU_CHUNK_ID_CP_GFX_SHADOW chunk in
amdgpu_cs_pass1(), matching the gate already present for the IB, FENCE and
BO_HANDLES chunk types.
The CP_GFX_SHADOW case previously shared a bare break with the dependency
and syncobj chunk types, which do not dereference a fixed-size struct. When
userspace submits this chunk with length_dw == 0, vmemdup_array_user() is
called with size 0 and returns ZERO_SIZE_PTR, which passes the IS_ERR()
check. amdgpu_cs_p2_shadow() then dereferences chunk->kdata as a struct
drm_amdgpu_cs_chunk_cp_gfx_shadow (reading shadow->flags), faulting on the
ZERO_SIZE_PTR and causing a NULL-pointer dereference.
This is reachable by an unprivileged process in the render group. Reject
undersized chunks with -EINVAL during pass1 so the bad submission is
rejected before pass2 ever dereferences the data.
Fixes: ac9287055ff1 ("drm/amdgpu: add gfx shadow CS IOCTL support")
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 7f61b2eef7415eccdb40850aca0de94211948657)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -272,13 +272,17 @@ static int amdgpu_cs_pass1(struct amdgpu
goto free_partial_kdata;
break;
+ case AMDGPU_CHUNK_ID_CP_GFX_SHADOW:
+ if (size < sizeof(struct drm_amdgpu_cs_chunk_cp_gfx_shadow))
+ goto free_partial_kdata;
+ break;
+
case AMDGPU_CHUNK_ID_DEPENDENCIES:
case AMDGPU_CHUNK_ID_SYNCOBJ_IN:
case AMDGPU_CHUNK_ID_SYNCOBJ_OUT:
case AMDGPU_CHUNK_ID_SCHEDULED_DEPENDENCIES:
case AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_WAIT:
case AMDGPU_CHUNK_ID_SYNCOBJ_TIMELINE_SIGNAL:
- case AMDGPU_CHUNK_ID_CP_GFX_SHADOW:
break;
default:
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 263/602] drm/nouveau: fix reversed error cleanup order in ucopy functions
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (261 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 262/602] drm/amdgpu: validate CP_GFX_SHADOW chunk size in CS pass1 Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 264/602] drm/displayid: fix Tiled Display Topology ID size Greg Kroah-Hartman
` (342 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yuhao Jiang, Junrui Luo,
Danilo Krummrich
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Junrui Luo <moonafterrain@outlook.com>
commit ab99ead646b1b833ecd57fe577a2816f2e848167 upstream.
nouveau_uvmm_vm_bind_ucopy() and nouveau_exec_ucopy() place their error
cleanup labels in allocation order rather than reverse allocation order.
On a u_memcpya() failure for in_sync.s, the goto to err_free_ops (or
err_free_pushs) frees the first allocation and then falls through to
err_free_ins, which calls u_free() on args->in_sync.s.
Since args->in_sync.s still holds the ERR_PTR returned by the failed
u_memcpya(), and ERR_PTR values are not caught by ZERO_OR_NULL_PTR(),
kvfree() proceeds to dereference it, which can result in a kernel oops.
A failure for out_sync.s instead jumps to err_free_ins and skips freeing
the first allocation, leading to a memory leak.
Fix by swapping the cleanup label order so resources are freed in the
correct reverse allocation sequence.
Fixes: b88baab82871 ("drm/nouveau: implement new VM_BIND uAPI")
Reported-by: Yuhao Jiang <danisjiang@gmail.com>
Cc: stable@vger.kernel.org
Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
Link: https://patch.msgid.link/SYBPR01MB7881484D91A6F80271415F71AF1A2@SYBPR01MB7881.ausprd01.prod.outlook.com
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/nouveau/nouveau_exec.c | 4 ++--
drivers/gpu/drm/nouveau/nouveau_uvmm.c | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
--- a/drivers/gpu/drm/nouveau/nouveau_exec.c
+++ b/drivers/gpu/drm/nouveau/nouveau_exec.c
@@ -327,10 +327,10 @@ nouveau_exec_ucopy(struct nouveau_exec_j
return 0;
-err_free_pushs:
- u_free(args->push.s);
err_free_ins:
u_free(args->in_sync.s);
+err_free_pushs:
+ u_free(args->push.s);
return ret;
}
--- a/drivers/gpu/drm/nouveau/nouveau_uvmm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_uvmm.c
@@ -1708,10 +1708,10 @@ nouveau_uvmm_vm_bind_ucopy(struct nouvea
return 0;
-err_free_ops:
- u_free(args->op.s);
err_free_ins:
u_free(args->in_sync.s);
+err_free_ops:
+ u_free(args->op.s);
return ret;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 264/602] drm/displayid: fix Tiled Display Topology ID size
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (262 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 263/602] drm/nouveau: fix reversed error cleanup order in ucopy functions Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 265/602] drm/i915/gem: Add missing nospec on parallel submit slot Greg Kroah-Hartman
` (341 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Dave Airlie, Jani Nikula
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jani Nikula <jani.nikula@intel.com>
commit 90c0486a82e27393f9eaf3bb350f51a0bd38cb6b upstream.
The Tiled Display Topology ID of a DisplayID Tiled Display Topology Data
Block consists of three fields:
- Tiled Display Manufacturer/Vendor ID Field (3 bytes)
- Tiled Display Product ID Code Field (2 bytes)
- Tiled Display Serial Number Field (4 bytes)
i.e. a total of 9 bytes, not 8.
The DisplayID Tiled Display Topology ID is used as the tile group
identifier.
Update both struct displayid_tiled_block topology_id member and struct
drm_tile_group group_data member to full 9 bytes.
The group data was missing the last byte of the serial number. I don't
know whether there are known bug reports that might be linked to this,
but it's plausible the last byte could be the differentiating part for
the tile groups, and fewer tile groups might have been created than
intended.
Fixes: b49b55bd4fba ("drm/displayid: add displayid defines and edid extension (v2)")
Fixes: 138f9ebb9755 ("drm: add tile_group support. (v3)")
Cc: Dave Airlie <airlied@redhat.com>
Cc: stable@vger.kernel.org # v3.19+
Reviewed-by: Dave Airlie <airlied@redhat.com>
Link: https://patch.msgid.link/20260610141549.555605-1-jani.nikula@intel.com
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/drm_connector.c | 12 ++++++------
drivers/gpu/drm/drm_displayid_internal.h | 2 +-
include/drm/drm_connector.h | 6 +++---
3 files changed, 10 insertions(+), 10 deletions(-)
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -3393,7 +3393,7 @@ EXPORT_SYMBOL(drm_mode_put_tile_group);
/**
* drm_mode_get_tile_group - get a reference to an existing tile group
* @dev: DRM device
- * @topology: 8-bytes unique per monitor.
+ * @topology_id: 9-byte unique ID per monitor.
*
* Use the unique bytes to get a reference to an existing tile group.
*
@@ -3401,14 +3401,14 @@ EXPORT_SYMBOL(drm_mode_put_tile_group);
* tile group or NULL if not found.
*/
struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
- const char topology[8])
+ const char topology_id[9])
{
struct drm_tile_group *tg;
int id;
mutex_lock(&dev->mode_config.idr_mutex);
idr_for_each_entry(&dev->mode_config.tile_idr, tg, id) {
- if (!memcmp(tg->group_data, topology, 8)) {
+ if (!memcmp(tg->group_data, topology_id, sizeof(tg->group_data))) {
if (!kref_get_unless_zero(&tg->refcount))
tg = NULL;
mutex_unlock(&dev->mode_config.idr_mutex);
@@ -3423,7 +3423,7 @@ EXPORT_SYMBOL(drm_mode_get_tile_group);
/**
* drm_mode_create_tile_group - create a tile group from a displayid description
* @dev: DRM device
- * @topology: 8-bytes unique per monitor.
+ * @topology_id: 9-byte unique ID per monitor.
*
* Create a tile group for the unique monitor, and get a unique
* identifier for the tile group.
@@ -3432,7 +3432,7 @@ EXPORT_SYMBOL(drm_mode_get_tile_group);
* new tile group or NULL.
*/
struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
- const char topology[8])
+ const char topology_id[9])
{
struct drm_tile_group *tg;
int ret;
@@ -3442,7 +3442,7 @@ struct drm_tile_group *drm_mode_create_t
return NULL;
kref_init(&tg->refcount);
- memcpy(tg->group_data, topology, 8);
+ memcpy(tg->group_data, topology_id, sizeof(tg->group_data));
tg->dev = dev;
mutex_lock(&dev->mode_config.idr_mutex);
--- a/drivers/gpu/drm/drm_displayid_internal.h
+++ b/drivers/gpu/drm/drm_displayid_internal.h
@@ -108,7 +108,7 @@ struct displayid_tiled_block {
u8 topo[3];
u8 tile_size[4];
u8 tile_pixel_bezel[5];
- u8 topology_id[8];
+ u8 topology_id[9];
} __packed;
struct displayid_detailed_timings_1 {
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -2312,13 +2312,13 @@ struct drm_tile_group {
struct kref refcount;
struct drm_device *dev;
int id;
- u8 group_data[8];
+ u8 group_data[9];
};
struct drm_tile_group *drm_mode_create_tile_group(struct drm_device *dev,
- const char topology[8]);
+ const char topology_id[9]);
struct drm_tile_group *drm_mode_get_tile_group(struct drm_device *dev,
- const char topology[8]);
+ const char topology_id[9]);
void drm_mode_put_tile_group(struct drm_device *dev,
struct drm_tile_group *tg);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 265/602] drm/i915/gem: Add missing nospec on parallel submit slot
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (263 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 264/602] drm/displayid: fix Tiled Display Topology ID size Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 266/602] drm/nouveau/acr: fix missing nvkm_done() in error path of nvkm_acr_oneinit() Greg Kroah-Hartman
` (340 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Martin Hodo, Matthew Brost,
Tvrtko Ursulin, Joonas Lahtinen, Tvrtko Ursulin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
commit 914a76a9f08366434bf595700f62026b7a19a9cc upstream.
Add missing Spectre mitigation for userspace controlled parallel
submission slot.
Discovered using AI-assisted static analysis confirmed by Intel
Product Security.
Reported-by: Martin Hodo <martin.hodo@intel.com>
Fixes: e5e32171a2cf ("drm/i915/guc: Connect UAPI to GuC multi-lrc interface")
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Tvrtko Ursulin <tursulin@ursulin.net>
Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: <stable@vger.kernel.org> # v5.16+
Link: https://patch.msgid.link/20260622132539.165558-1-joonas.lahtinen@linux.intel.com
(cherry picked from commit 15b9353deff3cf72331c387780de3cf9c316b643)
Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/i915/gem/i915_gem_context.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -613,6 +613,7 @@ set_proto_ctx_engines_parallel_submit(st
return -EINVAL;
}
+ slot = array_index_nospec(slot, set->num_engines);
if (set->engines[slot].type != I915_GEM_ENGINE_TYPE_INVALID) {
drm_dbg(&i915->drm,
"Invalid placement[%d], already occupied\n", slot);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 266/602] drm/nouveau/acr: fix missing nvkm_done() in error path of nvkm_acr_oneinit()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (264 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 265/602] drm/i915/gem: Add missing nospec on parallel submit slot Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 267/602] drm/radeon: fix r100_copy_blit for large BOs Greg Kroah-Hartman
` (339 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Wentao Liang, Danilo Krummrich
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wentao Liang <vulab@iscas.ac.cn>
commit c3027973f692077a1b66a9fb26d6a7c46c0dc72c upstream.
In nvkm_acr_oneinit(), nvkm_kmap(acr->wpr) is invoked unconditionally
at line 309 to obtain a mapping reference. Additionally, when both
acr->wpr_fw and acr->wpr_comp are present, a second nvkm_kmap() is
called inside the conditional block. Both mappings are expected to be
released by nvkm_done(acr->wpr) at line 320 before the function returns
successfully.
However, when a mismatch is detected during the loop within the
conditional block, the function returns -EINVAL at line 318 without
calling nvkm_done(). This results in a leak of the kmap reference(s)
acquired earlier.
Fix the issue by invoking nvkm_done(acr->wpr) prior to the early return
to ensure proper release of the mapping references.
Fixes: 22dcda45a3d1 ("drm/nouveau/acr: implement new subdev to replace "secure boot"")
Cc: stable@vger.kernel.org
Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
Link: https://patch.msgid.link/20260606155606.77593-1-vulab@iscas.ac.cn
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
@@ -315,6 +315,7 @@ nvkm_acr_oneinit(struct nvkm_subdev *sub
i, us, fw);
}
}
+ nvkm_done(acr->wpr);
return -EINVAL;
}
nvkm_done(acr->wpr);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 267/602] drm/radeon: fix r100_copy_blit for large BOs
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (265 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 266/602] drm/nouveau/acr: fix missing nvkm_done() in error path of nvkm_acr_oneinit() Greg Kroah-Hartman
@ 2026-07-30 14:10 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 268/602] drm/xe: Fix PTE index in xe_vm_populate_pgtable() for chunked binds Greg Kroah-Hartman
` (338 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:10 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Christian König,
Pavel Ondračka, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pavel Ondračka <pavel.ondracka@gmail.com>
commit f896e86273dbbebb5eac966b4a201b5c62a02e9a upstream.
r100_copy_blit() copies BOs as 1024-pixel-wide ARGB8888 blits, so one
GPU page becomes one blit row. Large copies are split into chunks of at
most 8191 rows.
The kernel register header names the packet coordinate dwords SRC_Y_X
and DST_Y_X. In the BITBLT_MULTI description in
R5xx_Acceleration_v1.5.pdf docs, these correspond to [SRC_X1 | SRC_Y1]
and [DST_X1 | DST_Y1], which are signed 13-bit coordinates in the
-8192..8191 range. The old code kept SRC/DST_PITCH_OFFSET at the BO base
and used SRC_Y_X/DST_Y_X as the chunk address, so large BO moves could
exceed that coordinate range.
Compute per-chunk SRC/DST_PITCH_OFFSET bases and emit zero source and
destination coordinates. r100_copy_blit() already packs
SRC/DST_PITCH_OFFSET as pitch plus base offset, so large chunk addresses
belong there rather than in the coordinate fields.
This fixes Prison Architect corruption with 4096x4096 mipped textures
after they are evicted to GTT under memory pressure on RV530.
Closes: https://gitlab.freedesktop.org/mesa/mesa/-/work_items/6716
Acked-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Pavel Ondračka <pavel.ondracka@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 87be26aee76239c6da03e599f238a426897f78ad)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/radeon/r100.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -906,6 +906,7 @@ struct radeon_fence *r100_copy_blit(stru
{
struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
struct radeon_fence *fence;
+ uint64_t cur_src_offset, cur_dst_offset;
uint32_t cur_pages;
uint32_t stride_bytes = RADEON_GPU_PAGE_SIZE;
uint32_t pitch;
@@ -934,6 +935,10 @@ struct radeon_fence *r100_copy_blit(stru
cur_pages = 8191;
}
num_gpu_pages -= cur_pages;
+ cur_src_offset = src_offset +
+ (uint64_t)num_gpu_pages * RADEON_GPU_PAGE_SIZE;
+ cur_dst_offset = dst_offset +
+ (uint64_t)num_gpu_pages * RADEON_GPU_PAGE_SIZE;
/* pages are in Y direction - height
page width in X direction - width */
@@ -950,13 +955,13 @@ struct radeon_fence *r100_copy_blit(stru
RADEON_DP_SRC_SOURCE_MEMORY |
RADEON_GMC_CLR_CMP_CNTL_DIS |
RADEON_GMC_WR_MSK_DIS);
- radeon_ring_write(ring, (pitch << 22) | (src_offset >> 10));
- radeon_ring_write(ring, (pitch << 22) | (dst_offset >> 10));
+ radeon_ring_write(ring, (pitch << 22) | (cur_src_offset >> 10));
+ radeon_ring_write(ring, (pitch << 22) | (cur_dst_offset >> 10));
radeon_ring_write(ring, (0x1fff) | (0x1fff << 16));
radeon_ring_write(ring, 0);
radeon_ring_write(ring, (0x1fff) | (0x1fff << 16));
- radeon_ring_write(ring, num_gpu_pages);
- radeon_ring_write(ring, num_gpu_pages);
+ radeon_ring_write(ring, 0);
+ radeon_ring_write(ring, 0);
radeon_ring_write(ring, cur_pages | (stride_pixels << 16));
}
radeon_ring_write(ring, PACKET0(RADEON_DSTCACHE_CTLSTAT, 0));
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 268/602] drm/xe: Fix PTE index in xe_vm_populate_pgtable() for chunked binds
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (266 preceding siblings ...)
2026-07-30 14:10 ` [PATCH 6.12 267/602] drm/radeon: fix r100_copy_blit for large BOs Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 269/602] drm/imagination: Fix double call to drm_sched_entity_fini() Greg Kroah-Hartman
` (337 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Matthew Brost, Matthew Auld,
Thomas Hellström
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Brost <matthew.brost@intel.com>
commit 34a4dd45cf210c04fee773b0dbc350aec285f03c upstream.
xe_vm_populate_pgtable() indexed the source PTE array (update->pt_entries)
by the per-call loop counter, assuming each call starts at the first entry
of the update. That holds for the CPU bind path
(xe_migrate_update_pgtables_cpu), which populates a whole update in a single
call, but not for the GPU bind path: write_pgtable() splits an update into
MAX_PTE_PER_SDI (510) sized MI_STORE_DATA_IMM chunks, invoking the populate
callback once per chunk with an advancing qword_ofs but a fresh command-
buffer destination pointer.
As a result, every chunk after the first re-read pt_entries from index 0
instead of from its true offset, so PTEs beyond the first 510 entries of a
single update were programmed with the wrong physical pages, shifting the
mapping by exactly MAX_PTE_PER_SDI pages.
This stayed latent because a single update only exceeds 510 qwords when a
large (e.g. 2M) region is bound as individual 4K PTEs rather than a single
huge-page entry, which happens when the backing store is sufficiently
fragmented. It was surfaced by the BO defrag path, which deliberately
rebinds such fragmented ranges via the GPU bind path, producing
deterministic data corruption offset by 510 pages.
Index pt_entries by the chunk's absolute offset relative to update->ofs so
both the CPU and GPU paths pick the correct entries.
Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs")
Cc: stable@vger.kernel.org
Assisted-by: GitHub_Copilot:claude-opus-4.8
Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
Link: https://patch.msgid.link/20260702012434.3861171-1-matthew.brost@intel.com
(cherry picked from commit e6f2d0b757c4fb577a513c577140109d1d292a9a)
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/xe/xe_pt.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -868,12 +868,22 @@ xe_vm_populate_pgtable(struct xe_migrate
u64 *ptr = data;
u32 i;
+ /*
+ * @qword_ofs is the absolute entry offset within the page table, while
+ * @ptes is indexed relative to @update->ofs (its first entry). The GPU
+ * path (write_pgtable) splits a single update into MAX_PTE_PER_SDI-sized
+ * chunks, calling this with an advancing @qword_ofs but a fresh @data
+ * pointer per chunk, so translate back into a @ptes index rather than
+ * assuming the chunk starts at ptes[0].
+ */
for (i = 0; i < num_qwords; i++) {
+ u32 idx = qword_ofs - update->ofs + i;
+
if (map)
xe_map_wr(tile_to_xe(tile), map, (qword_ofs + i) *
- sizeof(u64), u64, ptes[i].pte);
+ sizeof(u64), u64, ptes[idx].pte);
else
- ptr[i] = ptes[i].pte;
+ ptr[i] = ptes[idx].pte;
}
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 269/602] drm/imagination: Fix double call to drm_sched_entity_fini()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (267 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 268/602] drm/xe: Fix PTE index in xe_vm_populate_pgtable() for chunked binds Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 270/602] drm/imagination: Fix user array stride in pvr_set_uobj_array() Greg Kroah-Hartman
` (336 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Brajesh Gupta, Alessio Belle
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Brajesh Gupta <brajesh.gupta@imgtec.com>
commit 4af24c27a39ba147a613a09e10b9e0f7294524c0 upstream.
Call sequence of double call:
pvr_context_destroy
pvr_context_kill_queues
pvr_queue_kill
drm_sched_entity_destroy
drm_sched_entity_fini // here
pvr_context_put
kref_put(..., pvr_context_release)
pvr_context_destroy_queues
pvr_queue_destroy
drm_sched_entity_fini // here
Call to drm_sched_entity_destroy() from pvr_context_kill_queues() calls
drm_sched_entity_flush() + drm_sched_entity_fini().
drm_sched_entity_flush() ensures all pending jobs are completed and
drm_sched_entity_fini() ensures no further submission is allowed as
per expectation from pvr_context_kill_queues(). Double call to
drm_sched_entity_fini() is misuse of the API so keep call only in
pvr_context_create() failure path.
Stack trace for issue with addition of refcounting for DRM entity
stats in commit fd177135f0e6 ("drm/sched: Account entity GPU time"):
[ 789.490527] ------------[ cut here ]------------
[ 789.490559] refcount_t: underflow; use-after-free.
[ 789.490657] WARNING: lib/refcount.c:28 at refcount_warn_saturate+0xf4/0x144, CPU#0: kworker/u16:1/440
[ 789.490695] Modules linked in: powervr drm_gpuvm drm_exec gpu_sched drm_shmem_helper xhci_plat_hcd xhci_hcd dwc3 usbcore usb_common snd_soc_simple_card snd_soc_simple_card_utils sa2ul sha512 sha256 dwc3_am62 sha1 authenc rti_wdt libsha512 at24 sch_fq_codel fuse dm_mod ipv6
[ 789.490798] CPU: 0 UID: 0 PID: 440 Comm: kworker/u16:1 Not tainted 7.0.0-rc7-02049-g5e2c0700091b #22 PREEMPT
[ 789.490809] Hardware name: Texas Instruments AM625 SK (DT)
[ 789.490815] Workqueue: powervr-sched pvr_queue_fence_release_work [powervr]
[ 789.490868] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[ 789.490876] pc : refcount_warn_saturate+0xf4/0x144
[ 789.490884] lr : refcount_warn_saturate+0xf4/0x144
[ 789.490892] sp : ffff8000822cbcc0
[ 789.490895] x29: ffff8000822cbcc0 x28: 0000000000000000 x27: 0000000000000000
[ 789.490909] x26: 0000000000000000 x25: ffff800081b1e338 x24: ffff000004541405
[ 789.490922] x23: ffff000004bea950 x22: ffff00000042e400 x21: ffff000007123e30
[ 789.490935] x20: ffff000007123000 x19: ffff000007a80d50 x18: fffffffffffe7768
[ 789.490948] x17: 74736574202c6e6f x16: 697461746e656d65 x15: ffff800081b269f0
[ 789.490962] x14: 0000000000000030 x13: ffff800081b26a70 x12: 0000000000000211
[ 789.490975] x11: 00000000000000c0 x10: 0000000000000b50 x9 : ffff8000822cbb30
[ 789.490988] x8 : ffff0000014e7bb0 x7 : ffff00007725e780 x6 : 0000000372a05f49
[ 789.491001] x5 : 0000000000000000 x4 : 0000000000000001 x3 : 0000000000000010
[ 789.491013] x2 : 0000000000000000 x1 : 0000000000000000 x0 : ffff0000014e7000
[ 789.491027] Call trace:
[ 789.491032] refcount_warn_saturate+0xf4/0x144 (P)
[ 789.491043] drm_sched_entity_fini+0x164/0x18c [gpu_sched]
[ 789.491081] pvr_queue_destroy+0x64/0x134 [powervr]
[ 789.491110] pvr_context_destroy_queues+0x34/0x64 [powervr]
[ 789.491138] pvr_context_release+0x70/0xac [powervr]
[ 789.491166] pvr_context_put.part.0+0x5c/0x7c [powervr]
[ 789.491193] pvr_context_put+0x14/0x24 [powervr]
[ 789.491221] pvr_queue_fence_release_work+0x20/0x38 [powervr]
[ 789.491249] process_one_work+0x160/0x4c4
[ 789.491264] worker_thread+0x188/0x310
[ 789.491276] kthread+0x130/0x13c
[ 789.491287] ret_from_fork+0x10/0x20
[ 789.491300] ---[ end trace 0000000000000000 ]---
Fixes: eaf01ee5ba28 ("drm/imagination: Implement job submission and scheduling")
Cc: stable@vger.kernel.org
Signed-off-by: Brajesh Gupta <brajesh.gupta@imgtec.com>
Reviewed-by: Alessio Belle <alessio.belle@imgtec.com>
Link: https://patch.msgid.link/20260630-b4-sched_fix-v7-1-71aa39c62627@imgtec.com
Signed-off-by: Alessio Belle <alessio.belle@imgtec.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/imagination/pvr_context.c | 18 ++++++++++--------
drivers/gpu/drm/imagination/pvr_queue.c | 6 ++++--
drivers/gpu/drm/imagination/pvr_queue.h | 2 +-
3 files changed, 15 insertions(+), 11 deletions(-)
--- a/drivers/gpu/drm/imagination/pvr_context.c
+++ b/drivers/gpu/drm/imagination/pvr_context.c
@@ -173,22 +173,24 @@ ctx_fw_data_init(void *cpu_ptr, void *pr
/**
* pvr_context_destroy_queues() - Destroy all queues attached to a context.
* @ctx: Context to destroy queues on.
+ * @cleanup_queue_entity: Whether to cleanup the queue entity e.g. context
+ * creation failure path.
*
* Should be called when the last reference to a context object is dropped.
* It releases all resources attached to the queues bound to this context.
*/
-static void pvr_context_destroy_queues(struct pvr_context *ctx)
+static void pvr_context_destroy_queues(struct pvr_context *ctx, bool cleanup_queue_entity)
{
switch (ctx->type) {
case DRM_PVR_CTX_TYPE_RENDER:
- pvr_queue_destroy(ctx->queues.fragment);
- pvr_queue_destroy(ctx->queues.geometry);
+ pvr_queue_destroy(ctx->queues.fragment, cleanup_queue_entity);
+ pvr_queue_destroy(ctx->queues.geometry, cleanup_queue_entity);
break;
case DRM_PVR_CTX_TYPE_COMPUTE:
- pvr_queue_destroy(ctx->queues.compute);
+ pvr_queue_destroy(ctx->queues.compute, cleanup_queue_entity);
break;
case DRM_PVR_CTX_TYPE_TRANSFER_FRAG:
- pvr_queue_destroy(ctx->queues.transfer);
+ pvr_queue_destroy(ctx->queues.transfer, cleanup_queue_entity);
break;
}
}
@@ -252,7 +254,7 @@ static int pvr_context_create_queues(str
return -EINVAL;
err_destroy_queues:
- pvr_context_destroy_queues(ctx);
+ pvr_context_destroy_queues(ctx, true);
return err;
}
@@ -368,7 +370,7 @@ err_destroy_fw_obj:
pvr_fw_object_destroy(ctx->fw_obj);
err_destroy_queues:
- pvr_context_destroy_queues(ctx);
+ pvr_context_destroy_queues(ctx, true);
err_free_ctx_data:
kfree(ctx->data);
@@ -394,7 +396,7 @@ pvr_context_release(struct kref *ref_cou
spin_unlock(&pvr_dev->ctx_list_lock);
xa_erase(&pvr_dev->ctx_ids, ctx->ctx_id);
- pvr_context_destroy_queues(ctx);
+ pvr_context_destroy_queues(ctx, false);
pvr_fw_object_destroy(ctx->fw_obj);
kfree(ctx->data);
pvr_vm_context_put(ctx->vm_ctx);
--- a/drivers/gpu/drm/imagination/pvr_queue.c
+++ b/drivers/gpu/drm/imagination/pvr_queue.c
@@ -1394,11 +1394,12 @@ void pvr_queue_kill(struct pvr_queue *qu
/**
* pvr_queue_destroy() - Destroy a queue.
* @queue: The queue to destroy.
+ * @cleanup_queue_entity: Whether to cleanup the queue entity.
*
* Cleanup the queue and free the resources attached to it. Should be
* called from the context release function.
*/
-void pvr_queue_destroy(struct pvr_queue *queue)
+void pvr_queue_destroy(struct pvr_queue *queue, bool cleanup_queue_entity)
{
if (!queue)
return;
@@ -1408,7 +1409,8 @@ void pvr_queue_destroy(struct pvr_queue
mutex_unlock(&queue->ctx->pvr_dev->queues.lock);
drm_sched_fini(&queue->scheduler);
- drm_sched_entity_fini(&queue->entity);
+ if (cleanup_queue_entity)
+ drm_sched_entity_fini(&queue->entity);
if (WARN_ON(queue->last_queued_job_scheduled_fence))
dma_fence_put(queue->last_queued_job_scheduled_fence);
--- a/drivers/gpu/drm/imagination/pvr_queue.h
+++ b/drivers/gpu/drm/imagination/pvr_queue.h
@@ -158,7 +158,7 @@ struct pvr_queue *pvr_queue_create(struc
void pvr_queue_kill(struct pvr_queue *queue);
-void pvr_queue_destroy(struct pvr_queue *queue);
+void pvr_queue_destroy(struct pvr_queue *queue, bool cleanup_queue_entity);
void pvr_queue_process(struct pvr_queue *queue);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 270/602] drm/imagination: Fix user array stride in pvr_set_uobj_array()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (268 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 269/602] drm/imagination: Fix double call to drm_sched_entity_fini() Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 271/602] drm/imagination: fix error checking of pvr_vm_context_lookup() Greg Kroah-Hartman
` (335 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Alessio Belle, Shuvam Pandey
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shuvam Pandey <shuvampandey1@gmail.com>
commit 8dc8f3f4c2382fb7d1b1986ba8f33a2466cd3d7a upstream.
pvr_set_uobj_array() copies an array of kernel objects to a userspace
array whose element size is described by out->stride. When out->stride
is different from the kernel object size, the slow path advances the
userspace pointer by the kernel object size and the kernel pointer by the
userspace stride.
This reverses the intended layout. For larger userspace strides, later
copies read from the wrong kernel addresses. For smaller userspace
strides, later copies are written at the wrong userspace offsets. The
padding clear is also done only for the first element instead of the
padding area for each element.
Advance the userspace pointer by out->stride and the kernel pointer by
obj_size, and clear per-element padding while the current userspace
pointer is still available.
Fixes: f99f5f3ea7ef ("drm/imagination: Add GPU ID parsing and firmware loading")
Cc: stable@vger.kernel.org # v6.8+
Reviewed-by: Alessio Belle <alessio.belle@imgtec.com>
Signed-off-by: Shuvam Pandey <shuvampandey1@gmail.com>
Link: https://patch.msgid.link/6a456012.eb165e5c.113c2a.b71d@mx.google.com
Signed-off-by: Alessio Belle <alessio.belle@imgtec.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/imagination/pvr_drv.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
--- a/drivers/gpu/drm/imagination/pvr_drv.c
+++ b/drivers/gpu/drm/imagination/pvr_drv.c
@@ -1251,14 +1251,13 @@ pvr_set_uobj_array(const struct drm_pvr_
if (copy_to_user(out_ptr, in_ptr, cpy_elem_size))
return -EFAULT;
- out_ptr += obj_size;
- in_ptr += out->stride;
- }
+ if (out->stride > obj_size &&
+ clear_user(out_ptr + cpy_elem_size, out->stride - obj_size)) {
+ return -EFAULT;
+ }
- if (out->stride > obj_size &&
- clear_user(u64_to_user_ptr(out->array + obj_size),
- out->stride - obj_size)) {
- return -EFAULT;
+ out_ptr += out->stride;
+ in_ptr += obj_size;
}
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 271/602] drm/imagination: fix error checking of pvr_vm_context_lookup()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (269 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 270/602] drm/imagination: Fix user array stride in pvr_set_uobj_array() Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 272/602] drm/imagination: acquire vm_ctx->lock before mapping memory to GPU VM Greg Kroah-Hartman
` (334 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Luigi Santivetti, Alessio Belle
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luigi Santivetti <luigi.santivetti@imgtec.com>
commit cf385cf6e713eba0720651174dac0b2d2f5bb8f8 upstream.
Since pvr_vm_context_lookup() returns either NULL or a pointer, then stop
using IS_ERR() for checking the return value.
Using IS_ERR() leads to the kernel oops reported below. It can be
reproduced by passing an invalid VM context handle from userspace to the
DRM_IOCTL_PVR_CREATE_CONTEXT ioctl.
[ 92.733119] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000148
[ 92.742042] Mem abort info:
[ 92.744890] ESR = 0x0000000096000004
[ 92.748686] EC = 0x25: DABT (current EL), IL = 32 bits
[ 92.754020] SET = 0, FnV = 0
[ 92.757154] EA = 0, S1PTW = 0
[ 92.760337] FSC = 0x04: level 0 translation fault
[ 92.765243] Data abort info:
[ 92.768129] ISV = 0, ISS = 0x00000004, ISS2 = 0x00000000
[ 92.773626] CM = 0, WnR = 0, TnD = 0, TagAccess = 0
[ 92.778763] GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
[ 92.784098] user pgtable: 4k pages, 48-bit VAs, pgdp=000000088ed23000
[ 92.790550] [0000000000000148] pgd=0000000000000000, p4d=0000000000000000
[ 92.797381] Internal error: Oops: 0000000096000004 [#1] SMP
[ 92.803027] Modules linked in: powervr
[ 92.852533] CPU: 0 UID: 0 PID: 409 Comm: triangle Not tainted 7.1.0-rc5-g98b46e693b91 #1 PREEMPT
[ 92.861385] Hardware name: Texas Instruments AM68 SK (DT)
[ 92.866766] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[ 92.873709] pc : pvr_vm_get_fw_mem_context+0x0/0xc [powervr]
[ 92.879376] lr : pvr_queue_create+0x26c/0x440 [powervr]
[ 92.884595] sp : ffff8000837fbb00
[ 92.887895] x29: ffff8000837fbb60 x28: 0000000000000000 x27: ffff8000837fbce8
[ 92.895015] x26: ffff000807f61a40 x25: ffff000807f61a00 x24: ffff000807f64400
[ 92.902135] x23: ffff00080a5ab000 x22: ffff800079b24730 x21: ffff000807f61800
[ 92.909254] x20: ffff00080999e680 x19: 0000000000000000 x18: 0000000000000000
[ 92.916373] x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000001
[ 92.923492] x14: 0000000000000000 x13: 0000000000000002 x12: ffff80008145b298
[ 92.930611] x11: ffff8000844e5000 x10: ffff80008165a130 x9 : 0000000000000100
[ 92.937730] x8 : 0000000000000001 x7 : ffff0008076b27e0 x6 : ffff00080ec43b7c
[ 92.944850] x5 : ffff00080ec43b78 x4 : 0000000000000000 x3 : ffff00080999e680
[ 92.951968] x2 : 0000000000000000 x1 : 0000000000000000 x0 : 0000000000000000
[ 92.959088] Call trace:
[ 92.961521] pvr_vm_get_fw_mem_context+0x0/0xc [powervr] (P)
[ 92.967173] pvr_context_create+0x190/0x410 [powervr]
[ 92.972218] pvr_ioctl_create_context+0x44/0x8c [powervr]
[ 92.977608] drm_ioctl_kernel+0xbc/0x124 [drm]
[ 92.982127] drm_ioctl+0x1f8/0x4dc [drm]
[ 92.986098] __arm64_sys_ioctl+0xac/0x104
[ 92.990102] invoke_syscall+0x54/0x10c
[ 92.993842] el0_svc_common.constprop.0+0x40/0xe0
[ 92.998532] do_el0_svc+0x1c/0x28
[ 93.001835] el0_svc+0x38/0x11c
[ 93.004969] el0t_64_sync_handler+0xa0/0xe4
[ 93.009139] el0t_64_sync+0x198/0x19c
[ 93.012792] Code: aa1703e0 d2800014 95cb0ba4 17ffffe8 (f940a400)
[ 93.018869] ---[ end trace 0000000000000000 ]---
Fixes: d2d79d29bb98 ("drm/imagination: Implement context creation/destruction ioctls")
Cc: stable@vger.kernel.org
Signed-off-by: Luigi Santivetti <luigi.santivetti@imgtec.com>
Reviewed-by: Alessio Belle <alessio.belle@imgtec.com>
Link: https://patch.msgid.link/20260707-staging-ddkopsrc-2435-v1-1-24e160d44476@imgtec.com
Signed-off-by: Alessio Belle <alessio.belle@imgtec.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/imagination/pvr_context.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/gpu/drm/imagination/pvr_context.c
+++ b/drivers/gpu/drm/imagination/pvr_context.c
@@ -321,8 +321,8 @@ int pvr_context_create(struct pvr_file *
goto err_free_ctx;
ctx->vm_ctx = pvr_vm_context_lookup(pvr_file, args->vm_context_handle);
- if (IS_ERR(ctx->vm_ctx)) {
- err = PTR_ERR(ctx->vm_ctx);
+ if (!ctx->vm_ctx) {
+ err = -EINVAL;
goto err_free_ctx;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 272/602] drm/imagination: acquire vm_ctx->lock before mapping memory to GPU VM
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (270 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 271/602] drm/imagination: fix error checking of pvr_vm_context_lookup() Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 273/602] drm/amdkfd: Use kvcalloc to allocate arrays Greg Kroah-Hartman
` (333 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Icenowy Zheng, Alessio Belle
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Icenowy Zheng <zhengxingda@iscas.ac.cn>
commit 17e2030f37600994440f875dc410615d5c66ee6d upstream.
The drm gpuvm code doesn't protect find operation against map operation,
and the driver needs to ensure a map operation shouldn't happen when a
find operation is in progress.
In some cases a find operation will be in progress when doing map/unmap
operations, and the find operation will do a NULL pointer dereference.
An example of the stack trace of such NULL dereference is shown below:
```
Unable to handle kernel access to user memory without uaccess routines at
virtual address 0000000000000010
[<ffffffff01e989d4>] drm_gpuva_find+0x28/0x6c [drm_gpuvm]
[<ffffffff01ed3a40>] pvr_vm_unmap+0x34/0x68 [powervr]
[<ffffffff01ec69da>] pvr_ioctl_vm_unmap+0x2e/0x50 [powervr]
[<ffffffff8080ce0a>] drm_ioctl_kernel+0x8e/0xdc
[<ffffffff8080d016>] drm_ioctl+0x1be/0x3e0
[<ffffffff802bec3e>] __riscv_sys_ioctl+0xba/0xc4
[<ffffffff80d858b2>] do_trap_ecall_u+0x23e/0x3f4
[<ffffffff80d92288>] handle_exception+0x168/0x174
```
As all occurences of drm_gpuva_find*() are already guarded by
vm_ctx->lock, make pvr_vm_map() to acquire this lock to prevent
disturbing any find operation. This fixes the NULL deference problem in
drm_gpuva_find*().
Cc: stable@vger.kernel.org
Fixes: ff5f643de0bf ("drm/imagination: Add GEM and VM related code")
Fixes: 4bc736f890ce ("drm/imagination: vm: make use of GPUVM's drm_exec helper")
Signed-off-by: Icenowy Zheng <zhengxingda@iscas.ac.cn>
Reviewed-by: Alessio Belle <alessio.belle@imgtec.com>
Link: https://patch.msgid.link/20260714073641.1935075-1-zhengxingda@iscas.ac.cn
Signed-off-by: Alessio Belle <alessio.belle@imgtec.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/imagination/pvr_vm.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/gpu/drm/imagination/pvr_vm.c
+++ b/drivers/gpu/drm/imagination/pvr_vm.c
@@ -741,6 +741,7 @@ pvr_vm_map(struct pvr_vm_context *vm_ctx
pvr_gem_object_get(pvr_obj);
+ mutex_lock(&vm_ctx->lock);
err = drm_gpuvm_exec_lock(&vm_exec);
if (err)
goto err_cleanup;
@@ -750,6 +751,7 @@ pvr_vm_map(struct pvr_vm_context *vm_ctx
drm_gpuvm_exec_unlock(&vm_exec);
err_cleanup:
+ mutex_unlock(&vm_ctx->lock);
pvr_vm_bind_op_fini(&bind_op);
return err;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 273/602] drm/amdkfd: Use kvcalloc to allocate arrays
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (271 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 272/602] drm/imagination: acquire vm_ctx->lock before mapping memory to GPU VM Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 274/602] drm/amdkfd: Check bounds in allocate_event_notification_slot Greg Kroah-Hartman
` (332 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, David Francis, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Francis <David.Francis@amd.com>
commit 9c8b85f95c1d4736b967e17b8eb4a463c055bea3 upstream.
There were a few instances in kfd_chardev.c of kvzalloc being
used to allocate memory for an array.
Switch those to kvcalloc, which
- is the standard way of allocating a zero-initialized array
- does a check for the mul overflowing
Signed-off-by: David Francis <David.Francis@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 60b048c93f7a3add39757ad65fe2bb6e58eeae23)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -1795,13 +1795,13 @@ static int criu_checkpoint_devices(struc
struct kfd_criu_device_bucket *device_buckets = NULL;
int ret = 0, i;
- device_buckets = kvzalloc(num_devices * sizeof(*device_buckets), GFP_KERNEL);
+ device_buckets = kvcalloc(num_devices, sizeof(*device_buckets), GFP_KERNEL);
if (!device_buckets) {
ret = -ENOMEM;
goto exit;
}
- device_priv = kvzalloc(num_devices * sizeof(*device_priv), GFP_KERNEL);
+ device_priv = kvcalloc(num_devices, sizeof(*device_priv), GFP_KERNEL);
if (!device_priv) {
ret = -ENOMEM;
goto exit;
@@ -1921,17 +1921,17 @@ static int criu_checkpoint_bos(struct kf
int ret = 0, pdd_index, bo_index = 0, id;
void *mem;
- bo_buckets = kvzalloc(num_bos * sizeof(*bo_buckets), GFP_KERNEL);
+ bo_buckets = kvcalloc(num_bos, sizeof(*bo_buckets), GFP_KERNEL);
if (!bo_buckets)
return -ENOMEM;
- bo_privs = kvzalloc(num_bos * sizeof(*bo_privs), GFP_KERNEL);
+ bo_privs = kvcalloc(num_bos, sizeof(*bo_privs), GFP_KERNEL);
if (!bo_privs) {
ret = -ENOMEM;
goto exit;
}
- files = kvzalloc(num_bos * sizeof(struct file *), GFP_KERNEL);
+ files = kvcalloc(num_bos, sizeof(struct file *), GFP_KERNEL);
if (!files) {
ret = -ENOMEM;
goto exit;
@@ -2470,7 +2470,7 @@ static int criu_restore_bos(struct kfd_p
if (!bo_buckets)
return -ENOMEM;
- files = kvzalloc(args->num_bos * sizeof(struct file *), GFP_KERNEL);
+ files = kvcalloc(args->num_bos, sizeof(struct file *), GFP_KERNEL);
if (!files) {
ret = -ENOMEM;
goto exit;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 274/602] drm/amdkfd: Check bounds in allocate_event_notification_slot
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (272 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 273/602] drm/amdkfd: Use kvcalloc to allocate arrays Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 275/602] drm/amdkfd: fix 32-bit overflow in CWSR total size calculation Greg Kroah-Hartman
` (331 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Francis, David Yat Sin,
Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Francis <David.Francis@amd.com>
commit bb52249fbbe948875155ccd45cd8d74bf4ae747b upstream.
The valid event ids go from 0 to KFD_SIGNAL_EVENT_LIMIT
allocate_event_notification_slot has an option to specify
an event id to allocate at, used by CRIU. We weren't checking
the bounds on that value.
Check them.
v2: Lower bounds check is unecessary because of idr_alloc
already rejecting negative numbers. Upper bounds check should
be KFD_SIGNAL_EVENT_LIMIT since the signal mode mappings might
not yet exist
Signed-off-by: David Francis <David.Francis@amd.com>
Reviewed-by: David Yat Sin <david.yatsin@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 6853f1f6cbbeb3f53ebbbd7286536aeb2c5d5f50)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdkfd/kfd_events.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c
@@ -107,6 +107,9 @@ static int allocate_event_notification_s
}
if (restore_id) {
+ if (*restore_id >= KFD_SIGNAL_EVENT_LIMIT)
+ return -EINVAL;
+
id = idr_alloc(&p->event_idr, ev, *restore_id, *restore_id + 1,
GFP_KERNEL);
} else {
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 275/602] drm/amdkfd: fix 32-bit overflow in CWSR total size calculation
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (273 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 274/602] drm/amdkfd: Check bounds in allocate_event_notification_slot Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 276/602] drm/amd/display: Handle struct drm_plane_state.ignore_damage_clips Greg Kroah-Hartman
` (330 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yongqiang Sun, Philip Yang,
Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yongqiang Sun <Yongqiang.Sun@amd.com>
commit 2b0386d4293920e690c0e017708f999b93cc729b upstream.
total_cwsr_size was computed in 32-bit before being used as a BO/SVM
allocation size.
With large ctx_save_restore_area_size and debug_memory_size
multiplied by the XCC count, the product can wrap,
yielding an undersized CWSR save area that firmware later overruns.
Promote total_cwsr_size to u64 and use check_add_overflow()/
check_mul_overflow() in both kfd_queue_acquire_buffers() and
kfd_queue_release_buffers().
Signed-off-by: Yongqiang Sun <Yongqiang.Sun@amd.com>
Reviewed-by: Philip Yang <philip.yang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 319f7e13423ae3f486b9aea82f9ad2d6af0ee608)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdkfd/kfd_queue.c | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
--- a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
@@ -23,6 +23,7 @@
*/
#include <linux/slab.h>
+#include <linux/overflow.h>
#include "kfd_priv.h"
#include "kfd_topology.h"
#include "kfd_svm.h"
@@ -235,7 +236,7 @@ int kfd_queue_acquire_buffers(struct kfd
struct kfd_topology_device *topo_dev;
u64 expected_queue_size;
struct amdgpu_vm *vm;
- u32 total_cwsr_size;
+ u64 total_cwsr_size;
int err;
topo_dev = kfd_topology_device_by_id(pdd->dev->id);
@@ -305,8 +306,14 @@ int kfd_queue_acquire_buffers(struct kfd
goto out_err_unreserve;
}
- total_cwsr_size = (properties->ctx_save_restore_area_size +
- topo_dev->node_props.debug_memory_size) * NUM_XCC(pdd->dev->xcc_mask);
+ total_cwsr_size = (u64)properties->ctx_save_restore_area_size +
+ topo_dev->node_props.debug_memory_size;
+ if (check_mul_overflow(total_cwsr_size,
+ NUM_XCC(pdd->dev->xcc_mask),
+ &total_cwsr_size)) {
+ err = -EINVAL;
+ goto out_err_unreserve;
+ }
total_cwsr_size = ALIGN(total_cwsr_size, PAGE_SIZE);
err = kfd_queue_buffer_get(vm, (void *)properties->ctx_save_restore_area_address,
@@ -341,7 +348,7 @@ out_err_release:
int kfd_queue_release_buffers(struct kfd_process_device *pdd, struct queue_properties *properties)
{
struct kfd_topology_device *topo_dev;
- u32 total_cwsr_size;
+ u64 total_cwsr_size;
kfd_queue_buffer_put(&properties->wptr_bo);
kfd_queue_buffer_put(&properties->rptr_bo);
@@ -352,8 +359,12 @@ int kfd_queue_release_buffers(struct kfd
topo_dev = kfd_topology_device_by_id(pdd->dev->id);
if (!topo_dev)
return -EINVAL;
- total_cwsr_size = (properties->ctx_save_restore_area_size +
- topo_dev->node_props.debug_memory_size) * NUM_XCC(pdd->dev->xcc_mask);
+ total_cwsr_size = (u64)properties->ctx_save_restore_area_size +
+ topo_dev->node_props.debug_memory_size;
+ if (check_mul_overflow(total_cwsr_size,
+ NUM_XCC(pdd->dev->xcc_mask),
+ &total_cwsr_size))
+ return -EINVAL;
total_cwsr_size = ALIGN(total_cwsr_size, PAGE_SIZE);
kfd_queue_buffer_svm_put(pdd, properties->ctx_save_restore_area_address, total_cwsr_size);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 276/602] drm/amd/display: Handle struct drm_plane_state.ignore_damage_clips
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (274 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 275/602] drm/amdkfd: fix 32-bit overflow in CWSR total size calculation Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 277/602] drm/amd/display: detect_link_and_local_sink: DP alt mode timeout path leaks prev_sink reference Greg Kroah-Hartman
` (329 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Thomas Zimmermann,
Javier Martinez Canillas, Zack Rusin, dri-devel, Harry Wentland,
Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Zimmermann <tzimmermann@suse.de>
commit ac11060c6d4959e2d4ceada037d2e1e1bfcf6645 upstream.
The mode-setting pipeline can disabled damage clippings for a commit
by setting ignore_damage_clips in struct drm_plane_state. The commit
will then do a full display update.
Test the flag in DCN code and do a full update in DCN code if it has
been set.
Commit 35ed38d58257 ("drm: Allow drivers to indicate the damage helpers
to ignore damage clips") introduced ignore_damage_clips to selectively
ignore damage clipping in certain framebuffer changes. This driver does
not do that, but DRM's damage iterator will soon rely on the flag.
Therefore supporting it here as well make sense for consistency.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Fixes: 35ed38d58257 ("drm: Allow drivers to indicate the damage helpers to ignore damage clips")
Cc: Javier Martinez Canillas <javierm@redhat.com>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Zack Rusin <zackr@vmware.com>
Cc: dri-devel@lists.freedesktop.org
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit a24019f6480fad5c077b5956eed942c8960323d6)
Cc: <stable@vger.kernel.org> # v6.8+
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -5826,8 +5826,8 @@ static void fill_dc_dirty_rects(struct d
{
struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(crtc_state);
struct rect *dirty_rects = flip_addrs->dirty_rects;
- u32 num_clips;
- struct drm_mode_rect *clips;
+ u32 num_clips = 0;
+ struct drm_mode_rect *clips = NULL;
bool bb_changed;
bool fb_changed;
u32 i = 0;
@@ -5843,8 +5843,10 @@ static void fill_dc_dirty_rects(struct d
if (new_plane_state->rotation != DRM_MODE_ROTATE_0)
goto ffu;
- num_clips = drm_plane_get_damage_clips_count(new_plane_state);
- clips = drm_plane_get_damage_clips(new_plane_state);
+ if (!new_plane_state->ignore_damage_clips) {
+ num_clips = drm_plane_get_damage_clips_count(new_plane_state);
+ clips = drm_plane_get_damage_clips(new_plane_state);
+ }
if (num_clips && (!amdgpu_damage_clips || (amdgpu_damage_clips < 0 &&
is_psr_su)))
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 277/602] drm/amd/display: detect_link_and_local_sink: DP alt mode timeout path leaks prev_sink reference
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (275 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 276/602] drm/amd/display: Handle struct drm_plane_state.ignore_damage_clips Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 278/602] drm/virtio: bound EDID block reads to the response buffer Greg Kroah-Hartman
` (328 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, WenTao Liang,
Mario Limonciello (AMD), Mario Limonciello, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: WenTao Liang <vulab@iscas.ac.cn>
commit a6e14b976be48eebd8769cb5b883a6af7fc5ade1 upstream.
prev_sink is unconditionally retained via dc_sink_retain at function
entry, but the DP alt mode timeout path inside SIGNAL_TYPE_DISPLAY_PORT
returns false without releasing prev_sink. All other return paths in the
function correctly call dc_sink_release(prev_sink), making this the only
missing cleanup.
Fixes: 54618888d1ea ("drm/amd/display: break down dc_link.c")
Signed-off-by: WenTao Liang <vulab@iscas.ac.cn>
Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
Link: https://patch.msgid.link/20260626124555.36910-1-vulab@iscas.ac.cn
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 45510cf662dcf46b5d8926d454f338809f107b9d)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/display/dc/link/link_detection.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c
@@ -961,8 +961,11 @@ static bool detect_link_and_local_sink(s
link->link_enc->features.flags.bits.DP_IS_USB_C == 1) {
/* if alt mode times out, return false */
- if (!wait_for_entering_dp_alt_mode(link))
+ if (!wait_for_entering_dp_alt_mode(link)) {
+ if (prev_sink)
+ dc_sink_release(prev_sink);
return false;
+ }
}
if (!detect_dp(link, &sink_caps, reason)) {
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 278/602] drm/virtio: bound EDID block reads to the response buffer
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (276 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 277/602] drm/amd/display: detect_link_and_local_sink: DP alt mode timeout path leaks prev_sink reference Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 279/602] drm/amdgpu/sdma7.0: replace BUG_ON() with WARN_ON() Greg Kroah-Hartman
` (327 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Bryam Vargas, Dmitry Osipenko
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <hexlabsecurity@proton.me>
commit 4e1a53892ba7f8a3e1da6bfc53c83ae7c812dccd upstream.
virtio_get_edid_block() validates the read offset only against the
device-supplied resp->size field, never against the fixed-size resp->edid
array. The EDID block index is driven by the device-supplied extension
count, so a malicious virtio-gpu backend can advertise a large size
together with a high block count and read far past the array into adjacent
kernel memory, which is then surfaced in the parsed EDID (an out-of-bounds
read / info leak).
Also reject any read whose end exceeds the size of the edid array.
Conforming EDID responses stay within the array and are unaffected.
Fixes: b4b01b4995fb ("drm/virtio: add edid support")
Cc: stable@vger.kernel.org
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Link: https://patch.msgid.link/20260620-b4-disp-22bba7bf-v1-1-b95924cee742@proton.me
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/virtio/virtgpu_vq.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -723,7 +723,8 @@ static int virtio_get_edid_block(void *d
struct virtio_gpu_resp_edid *resp = data;
size_t start = block * EDID_LENGTH;
- if (start + len > le32_to_cpu(resp->size))
+ if (start + len > le32_to_cpu(resp->size) ||
+ start + len > sizeof(resp->edid))
return -EINVAL;
memcpy(buf, resp->edid + start, len);
return 0;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 279/602] drm/amdgpu/sdma7.0: replace BUG_ON() with WARN_ON()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (277 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 278/602] drm/virtio: bound EDID block reads to the response buffer Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 280/602] drm/amdgpu/sdma6.0: " Greg Kroah-Hartman
` (326 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Vitaly Prosyak, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <alexander.deucher@amd.com>
commit e80e28f398f5d9f6e361ffb56382d2e74fc87556 upstream.
There's no need to crash the kernel for these cases.
Reviewed-by: Vitaly Prosyak <vitaly.prosyak@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 9723a8bed3aa251a26bee4583bac9d8fb064dd44)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
@@ -389,7 +389,7 @@ static void sdma_v7_0_ring_emit_fence(st
amdgpu_ring_write(ring, SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_FENCE) |
SDMA_PKT_FENCE_HEADER_MTYPE(0x3)); /* Ucached(UC) */
/* zero in first two bits */
- BUG_ON(addr & 0x3);
+ WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -400,7 +400,7 @@ static void sdma_v7_0_ring_emit_fence(st
amdgpu_ring_write(ring, SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_FENCE) |
SDMA_PKT_FENCE_HEADER_MTYPE(0x3));
/* zero in first two bits */
- BUG_ON(addr & 0x3);
+ WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(seq));
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 280/602] drm/amdgpu/sdma6.0: replace BUG_ON() with WARN_ON()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (278 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 279/602] drm/amdgpu/sdma7.0: replace BUG_ON() with WARN_ON() Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 281/602] drm/amdgpu/sdma5.2: " Greg Kroah-Hartman
` (325 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Vitaly Prosyak, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <alexander.deucher@amd.com>
commit ec42c96c322e5cc48099ab5e67b5cbe236cb1949 upstream.
There's no need to crash the kernel for these cases.
Reviewed-by: Vitaly Prosyak <vitaly.prosyak@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit c17a508a7d652da3728f8bbc481bfffe96d65a87)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
@@ -357,7 +357,7 @@ static void sdma_v6_0_ring_emit_fence(st
amdgpu_ring_write(ring, SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_FENCE) |
SDMA_PKT_FENCE_HEADER_MTYPE(0x3)); /* Ucached(UC) */
/* zero in first two bits */
- BUG_ON(addr & 0x3);
+ WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -368,7 +368,7 @@ static void sdma_v6_0_ring_emit_fence(st
amdgpu_ring_write(ring, SDMA_PKT_COPY_LINEAR_HEADER_OP(SDMA_OP_FENCE) |
SDMA_PKT_FENCE_HEADER_MTYPE(0x3));
/* zero in first two bits */
- BUG_ON(addr & 0x3);
+ WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(seq));
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 281/602] drm/amdgpu/sdma5.2: replace BUG_ON() with WARN_ON()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (279 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 280/602] drm/amdgpu/sdma6.0: " Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 282/602] drm/amdgpu/sdma5.0: " Greg Kroah-Hartman
` (324 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Vitaly Prosyak, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <alexander.deucher@amd.com>
commit b9dd618a635d39fbb211454b6e8837b2a7f10fb0 upstream.
There's no need to crash the kernel for these cases.
Reviewed-by: Vitaly Prosyak <vitaly.prosyak@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit ae658afc7f47f6147371ec42cc6b1a793dfdb5af)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
@@ -376,7 +376,7 @@ static void sdma_v5_2_ring_emit_fence(st
amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE) |
SDMA_PKT_FENCE_HEADER_MTYPE(0x3)); /* Ucached(UC) */
/* zero in first two bits */
- BUG_ON(addr & 0x3);
+ WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -387,7 +387,7 @@ static void sdma_v5_2_ring_emit_fence(st
amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE) |
SDMA_PKT_FENCE_HEADER_MTYPE(0x3));
/* zero in first two bits */
- BUG_ON(addr & 0x3);
+ WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(seq));
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 282/602] drm/amdgpu/sdma5.0: replace BUG_ON() with WARN_ON()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (280 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 281/602] drm/amdgpu/sdma5.2: " Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 283/602] drm/i915: Return NULL on error in active_instance Greg Kroah-Hartman
` (323 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Vitaly Prosyak, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <alexander.deucher@amd.com>
commit 9e98ed3113943257ad6e5c1e6beddbdb482a70ad upstream.
There's no need to crash the kernel for these cases.
Reviewed-by: Vitaly Prosyak <vitaly.prosyak@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 8d144a0eb09537055841af48c9e7c2d4cd48e84d)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
@@ -557,7 +557,7 @@ static void sdma_v5_0_ring_emit_fence(st
amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE) |
SDMA_PKT_FENCE_HEADER_MTYPE(0x3)); /* Ucached(UC) */
/* zero in first two bits */
- BUG_ON(addr & 0x3);
+ WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -568,7 +568,7 @@ static void sdma_v5_0_ring_emit_fence(st
amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE) |
SDMA_PKT_FENCE_HEADER_MTYPE(0x3));
/* zero in first two bits */
- BUG_ON(addr & 0x3);
+ WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(seq));
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 283/602] drm/i915: Return NULL on error in active_instance
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (281 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 282/602] drm/amdgpu/sdma5.0: " Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 284/602] drm/i915/bios: range check LFP Data Block panel_type2 Greg Kroah-Hartman
` (322 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Martin Hodo, Maarten Lankhorst,
Thomas Hellström, Simona Vetter, Joonas Lahtinen,
Sebastian Brzezinka
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
commit 1e33f0de5fdcd09e51fdec1e5822448970b6420f upstream.
Avoid returning &node->base when node is NULL due to OOM
during GFP_ATOMIC allocation.
Discovered using AI-assisted static analysis confirmed by
Intel Product Security.
Reported-by: Martin Hodo <martin.hodo@intel.com>
Fixes: bfaae47db3c0 ("drm/i915: make lockdep slightly happier about execbuf.")
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Cc: Simona Vetter <simona.vetter@ffwll.ch>
Cc: <stable@vger.kernel.org> # v5.13+
Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Reviewed-by: Sebastian Brzezinka <sebastian.brzezinka@intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patch.msgid.link/20260624090940.74840-1-joonas.lahtinen@linux.intel.com
(cherry picked from commit 6029bc064f0b1bac184203a50fbaaf070fa18832)
Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/i915/i915_active.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/i915/i915_active.c
+++ b/drivers/gpu/drm/i915/i915_active.c
@@ -319,7 +319,7 @@ active_instance(struct i915_active *ref,
*/
node = kmem_cache_alloc(slab_cache, GFP_ATOMIC);
if (!node)
- goto out;
+ goto err;
__i915_active_fence_init(&node->base, NULL, node_retire);
node->ref = ref;
@@ -333,6 +333,11 @@ out:
spin_unlock_irq(&ref->tree_lock);
return &node->base;
+
+err:
+ spin_unlock_irq(&ref->tree_lock);
+
+ return NULL;
}
void __i915_active_init(struct i915_active *ref,
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 284/602] drm/i915/bios: range check LFP Data Block panel_type2
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (282 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 283/602] drm/i915: Return NULL on error in active_instance Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 285/602] drm/amdgpu: fix lifetime issue of amdgpu_vm_get_task_info_pasid() Greg Kroah-Hartman
` (321 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Martin Hodo, Animesh Manna,
Ville Syrjälä, Ville Syrjälä, Jani Nikula,
Joonas Lahtinen, Michał Grzelak
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jani Nikula <jani.nikula@intel.com>
commit 2084503f2d087bf956198e7f6eb25b03a7049cb2 upstream.
While the panel_type from LFP Data Block is range checked, panel_type2
is not. Add a few helpers for range checking, and use them to not only
check panel_type2, but also improve clarity and correctness in the panel
type selection.
Discovered using AI-assisted static analysis confirmed by Intel Product
Security.
v2:
- Fix commit message typo (Michał)
- Add is_panel_type_pnp() (Ville)
Reported-by: Martin Hodo <martin.hodo@intel.com>
Fixes: 6434cf630086 ("drm/i915/bios: calculate panel type as per child device index in VBT")
Cc: stable@vger.kernel.org # v6.0+
Cc: Animesh Manna <animesh.manna@intel.com>
Cc: Ville Syrjälä <ville.syrjala@intel.com>
Reviewed-by: Michał Grzelak <michal.grzelak@intel.com> # v1
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patch.msgid.link/20260626140155.1389655-1-jani.nikula@intel.com
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
(cherry picked from commit c9ebe5d2f25729d6cfbbb1235d640bf67f9275df)
Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/i915/display/intel_bios.c | 36 +++++++++++++++++++++++-------
1 file changed, 28 insertions(+), 8 deletions(-)
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -620,6 +620,21 @@ get_lfp_data_tail(const struct bdb_lfp_d
return NULL;
}
+static bool is_panel_type_valid(int panel_type)
+{
+ return panel_type >= 0 && panel_type < 16;
+}
+
+static bool is_panel_type_pnp(int panel_type)
+{
+ return panel_type == 0xff;
+}
+
+static bool is_panel_type_valid_or_pnp(int panel_type)
+{
+ return is_panel_type_valid(panel_type) || is_panel_type_pnp(panel_type);
+}
+
static int opregion_get_panel_type(struct intel_display *display,
const struct intel_bios_encoder_data *devdata,
const struct drm_edid *drm_edid, bool use_fallback)
@@ -637,15 +652,21 @@ static int vbt_get_panel_type(struct int
if (!lfp_options)
return -1;
- if (lfp_options->panel_type > 0xf &&
- lfp_options->panel_type != 0xff) {
+ if (!is_panel_type_valid_or_pnp(lfp_options->panel_type)) {
drm_dbg_kms(display->drm, "Invalid VBT panel type 0x%x\n",
lfp_options->panel_type);
return -1;
}
- if (devdata && devdata->child.handle == DEVICE_HANDLE_LFP2)
+ if (devdata && devdata->child.handle == DEVICE_HANDLE_LFP2) {
+ if (!is_panel_type_valid_or_pnp(lfp_options->panel_type2)) {
+ drm_dbg_kms(display->drm, "Invalid VBT panel type 2 0x%x\n",
+ lfp_options->panel_type2);
+ return -1;
+ }
+
return lfp_options->panel_type2;
+ }
drm_WARN_ON(display->drm,
devdata && devdata->child.handle != DEVICE_HANDLE_LFP1);
@@ -759,13 +780,12 @@ static int get_panel_type(struct intel_d
panel_types[i].name, panel_types[i].panel_type);
}
- if (panel_types[PANEL_TYPE_OPREGION].panel_type >= 0)
+ if (is_panel_type_valid(panel_types[PANEL_TYPE_OPREGION].panel_type))
i = PANEL_TYPE_OPREGION;
- else if (panel_types[PANEL_TYPE_VBT].panel_type == 0xff &&
- panel_types[PANEL_TYPE_PNPID].panel_type >= 0)
+ else if (is_panel_type_pnp(panel_types[PANEL_TYPE_VBT].panel_type) &&
+ is_panel_type_valid(panel_types[PANEL_TYPE_PNPID].panel_type))
i = PANEL_TYPE_PNPID;
- else if (panel_types[PANEL_TYPE_VBT].panel_type != 0xff &&
- panel_types[PANEL_TYPE_VBT].panel_type >= 0)
+ else if (is_panel_type_valid(panel_types[PANEL_TYPE_VBT].panel_type))
i = PANEL_TYPE_VBT;
else
i = PANEL_TYPE_FALLBACK;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 285/602] drm/amdgpu: fix lifetime issue of amdgpu_vm_get_task_info_pasid()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (283 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 284/602] drm/i915/bios: range check LFP Data Block panel_type2 Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 286/602] drm/i915/gem: Do not leak siblings[] on proto context error Greg Kroah-Hartman
` (320 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Shahyan Soltani,
Christian König, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shahyan Soltani <shahyan.soltani@amd.com>
commit 04cc4aa3617b0ed67e859f91f09de5d896a46f3a upstream.
The vm pointer returned from amdgpu_vm_get_vm_from_pasid() is only
valid while the lock is still being held. Once xa_unlock_irqrestore is
called and returned, the pointer is no longer under lock and is subject
to modification. Since, the caller still dereferences vm->task_info in
amdgpu_vm_get_task_info_vm() after the lock is removed, this causes a
use after unlock problem.
Remove the lifetime issue present in amdgpu_vm_get_task_info_pasid()
through removing the amdgpu_vm_get_vm_from_pasid() function from
amdgpu_vm.c and making the relevant code inline to hold the lock while
it is still in use.
Signed-off-by: Shahyan Soltani <shahyan.soltani@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 9d01579f3f868b333acc901815972685989092c7)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 25 ++++++++++---------------
1 file changed, 10 insertions(+), 15 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -2308,19 +2308,6 @@ static void amdgpu_vm_destroy_task_info(
kfree(ti);
}
-static inline struct amdgpu_vm *
-amdgpu_vm_get_vm_from_pasid(struct amdgpu_device *adev, u32 pasid)
-{
- struct amdgpu_vm *vm;
- unsigned long flags;
-
- xa_lock_irqsave(&adev->vm_manager.pasids, flags);
- vm = xa_load(&adev->vm_manager.pasids, pasid);
- xa_unlock_irqrestore(&adev->vm_manager.pasids, flags);
-
- return vm;
-}
-
/**
* amdgpu_vm_put_task_info - reference down the vm task_info ptr
*
@@ -2366,8 +2353,16 @@ amdgpu_vm_get_task_info_vm(struct amdgpu
struct amdgpu_task_info *
amdgpu_vm_get_task_info_pasid(struct amdgpu_device *adev, u32 pasid)
{
- return amdgpu_vm_get_task_info_vm(
- amdgpu_vm_get_vm_from_pasid(adev, pasid));
+ struct amdgpu_task_info *ti;
+ struct amdgpu_vm *vm;
+ unsigned long flags;
+
+ xa_lock_irqsave(&adev->vm_manager.pasids, flags);
+ vm = xa_load(&adev->vm_manager.pasids, pasid);
+ ti = amdgpu_vm_get_task_info_vm(vm);
+ xa_unlock_irqrestore(&adev->vm_manager.pasids, flags);
+
+ return ti;
}
static int amdgpu_vm_create_task_info(struct amdgpu_vm *vm)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 286/602] drm/i915/gem: Do not leak siblings[] on proto context error
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (284 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 285/602] drm/amdgpu: fix lifetime issue of amdgpu_vm_get_task_info_pasid() Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 287/602] drm/i915/gem: Fix NULL deref in I915_CONTEXT_PARAM_SSEU Greg Kroah-Hartman
` (319 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Martin Hodo, Faith Ekstrand,
Simona Vetter, Tvrtko Ursulin, Maarten Lankhorst, Joonas Lahtinen,
Tvrtko Ursulin, Rodrigo Vivi
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
commit eed3de2acf6aa5154d49098b026710b646db67ee upstream.
After a successful BALANCE/PARALLEL_SUBMIT extension on context
creation, error during processing of next user extension leaks
the siblings[] array. Fix that.
Discovered using AI-assisted static analysis confirmed by
Intel Product Security.
Reported-by: Martin Hodo <martin.hodo@intel.com>
Fixes: d4433c7600f7 ("drm/i915/gem: Use the proto-context to handle create parameters (v5)")
Cc: Faith Ekstrand <faith.ekstrand@collabora.com>
Cc: Simona Vetter <simona.vetter@ffwll.ch>
Cc: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: <stable@vger.kernel.org> # v5.15+
Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Signed-off-by: Tvrtko Ursulin <tursulin@ursulin.net>
Link: https://lore.kernel.org/r/20260701073030.44850-1-joonas.lahtinen@linux.intel.com
(cherry picked from commit aa65e0a4b51b3b54b53e4142aaa2d997aa1061ff)
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/i915/gem/i915_gem_context.c | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -771,8 +771,8 @@ static int set_proto_ctx_engines(struct
struct intel_engine_cs *engine;
if (copy_from_user(&ci, &user->engines[n], sizeof(ci))) {
- kfree(set.engines);
- return -EFAULT;
+ err = -EFAULT;
+ goto err;
}
memset(&set.engines[n], 0, sizeof(set.engines[n]));
@@ -788,8 +788,8 @@ static int set_proto_ctx_engines(struct
drm_dbg(&i915->drm,
"Invalid engine[%d]: { class:%d, instance:%d }\n",
n, ci.engine_class, ci.engine_instance);
- kfree(set.engines);
- return -ENOENT;
+ err = -ENOENT;
+ goto err;
}
set.engines[n].type = I915_GEM_ENGINE_TYPE_PHYSICAL;
@@ -802,15 +802,21 @@ static int set_proto_ctx_engines(struct
set_proto_ctx_engines_extensions,
ARRAY_SIZE(set_proto_ctx_engines_extensions),
&set);
- if (err) {
- kfree(set.engines);
- return err;
- }
+ if (err)
+ goto err_extensions;
pc->num_user_engines = set.num_engines;
pc->user_engines = set.engines;
return 0;
+
+err_extensions:
+ for (n = 0; n < set.num_engines; n++)
+ kfree(set.engines[n].siblings);
+err:
+ kfree(set.engines);
+
+ return err;
}
static int set_proto_ctx_sseu(struct drm_i915_file_private *fpriv,
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 287/602] drm/i915/gem: Fix NULL deref in I915_CONTEXT_PARAM_SSEU
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (285 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 286/602] drm/i915/gem: Do not leak siblings[] on proto context error Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 288/602] drm/amd/pm: fix smu14 power limit range calculation Greg Kroah-Hartman
` (318 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Martin Hodo, Faith Ekstrand,
Simona Vetter, Tvrtko Ursulin, Maarten Lankhorst, Joonas Lahtinen,
Andi Shyti, Rodrigo Vivi
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
commit 2b56757a9a7456825eb668fde92299e01c5e2721 upstream.
Setting context engine slot N into I915_ENGINE_CLASS_INVALID /
I915_ENGINE_CLASS_INVALID_NONE and attempting to apply
I915_CONTEXT_PARAM_SSEU to the same slot N will deref NULL.
Fix that.
Discovered using AI-assisted static analysis confirmed by
Intel Product Security.
Reported-by: Martin Hodo <martin.hodo@intel.com>
Fixes: d4433c7600f7 ("drm/i915/gem: Use the proto-context to handle create parameters (v5)")
Cc: Faith Ekstrand <faith.ekstrand@collabora.com>
Cc: Simona Vetter <simona.vetter@ffwll.ch>
Cc: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: <stable@vger.kernel.org> # v5.15+
Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Reviewed-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Reviewed-by: Andi Shyti <andi.shyti@linux.intel.com>
Link: https://patch.msgid.link/20260701075555.52142-1-joonas.lahtinen@linux.intel.com
(cherry picked from commit 36eda5b5c2d40da41cc0a5403c26986237cf9e87)
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/i915/gem/i915_gem_context.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -858,7 +858,7 @@ static int set_proto_ctx_sseu(struct drm
pe = &pc->user_engines[idx];
/* Only render engine supports RPCS configuration. */
- if (pe->engine->class != RENDER_CLASS)
+ if (!pe->engine || pe->engine->class != RENDER_CLASS)
return -EINVAL;
sseu = &pe->sseu;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 288/602] drm/amd/pm: fix smu14 power limit range calculation
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (286 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 287/602] drm/i915/gem: Fix NULL deref in I915_CONTEXT_PARAM_SSEU Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 289/602] drm/gfx10: Program DB_RING_CONTROL Greg Kroah-Hartman
` (317 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Yang Wang, Kenneth Feng,
Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yang Wang <kevinyang.wang@amd.com>
commit e987eabc02646920cd13ab75902693e99735eca0 upstream.
SMU14 derives the default PPT limit from SocketPowerLimitAc/Dc, but
MsgLimits.Power may expose a different firmware limit for the same PPT0
throttler. Using those values independently as fixed min/max bases can
report an incorrect configurable power range.
Keep the socket power limit as the default value and as the fallback for
current-limit queries. Calculate the reported range from both firmware
values instead, using the lower value as the minimum base and the higher
value as the maximum base before applying OD percentages.
Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Kenneth Feng <kenneth.feng@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit c936b8126b444401318fcbeb1828488cc5312dee)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c | 28 ++++++++++---------
1 file changed, 16 insertions(+), 12 deletions(-)
--- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
@@ -1672,19 +1672,23 @@ static int smu_v14_0_2_get_power_limit(s
table_context->power_play_table;
PPTable_t *pptable = table_context->driver_pptable;
CustomSkuTable_t *skutable = &pptable->CustomSkuTable;
- int16_t od_percent_upper = 0, od_percent_lower = 0;
+ uint32_t pp_limit = smu->adev->pm.ac_power ?
+ skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
+ skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
uint32_t msg_limit = pptable->SkuTable.MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
- uint32_t power_limit;
+ uint32_t min_limit = min_t(uint32_t, pp_limit, msg_limit);
+ uint32_t max_limit = max_t(uint32_t, pp_limit, msg_limit);
+ int16_t od_percent_upper = 0, od_percent_lower = 0;
+ int ret;
- if (smu_v14_0_get_current_power_limit(smu, &power_limit))
- power_limit = smu->adev->pm.ac_power ?
- skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
- skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
+ if (current_power_limit) {
+ ret = smu_v14_0_get_current_power_limit(smu, current_power_limit);
+ if (ret)
+ *current_power_limit = pp_limit;
+ }
- if (current_power_limit)
- *current_power_limit = power_limit;
if (default_power_limit)
- *default_power_limit = power_limit;
+ *default_power_limit = pp_limit;
if (powerplay_table) {
if (smu->od_enabled &&
@@ -1698,15 +1702,15 @@ static int smu_v14_0_2_get_power_limit(s
}
dev_dbg(smu->adev->dev, "od percent upper:%d, od percent lower:%d (default power: %d)\n",
- od_percent_upper, od_percent_lower, power_limit);
+ od_percent_upper, od_percent_lower, pp_limit);
if (max_power_limit) {
- *max_power_limit = msg_limit * (100 + od_percent_upper);
+ *max_power_limit = max_limit * (100 + od_percent_upper);
*max_power_limit /= 100;
}
if (min_power_limit) {
- *min_power_limit = power_limit * (100 + od_percent_lower);
+ *min_power_limit = min_limit * (100 + od_percent_lower);
*min_power_limit /= 100;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 289/602] drm/gfx10: Program DB_RING_CONTROL
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (287 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 288/602] drm/amd/pm: fix smu14 power limit range calculation Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 290/602] drm/panthor: return error on truncated firmware Greg Kroah-Hartman
` (316 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Timur Kristóf, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <alexander.deucher@amd.com>
commit f0262c3a3f14d60140f6b826d40d44edf62c36d6 upstream.
This is needed to allocate occlusion counters across
both gfx pipes.
Fixes: b7a1a0ef12b8 ("drm/amd/amdgpu: add pipe1 hardware support")
Reviewed-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 6807352cbabb74b61ba42888769283af72191f66)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 9 +++++++++
1 file changed, 9 insertions(+)
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
@@ -5195,6 +5195,15 @@ static void gfx_v10_0_constants_init(str
gfx_v10_0_get_tcc_info(adev);
adev->gfx.config.pa_sc_tile_steering_override =
gfx_v10_0_init_pa_sc_tile_steering_override(adev);
+ /* Program DB_RING_CONTROL for multiple GFX pipes
+ * Default power up value is 1.
+ * Possible values:
+ * 0 - split occlusion counters between gfx pipes
+ * 1 - all occlusion counters to pipe 0
+ * 2 - all occlusion counters to pipe 1
+ */
+ WREG32_FIELD15(GC, 0, DB_RING_CONTROL, COUNTER_CONTROL,
+ (adev->gfx.me.num_pipe_per_me > 1) ? 0 : 1);
/* XXX SH_MEM regs */
/* where to put LDS, scratch, GPUVM in FSA64 space */
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 290/602] drm/panthor: return error on truncated firmware
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (288 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 289/602] drm/gfx10: Program DB_RING_CONTROL Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 291/602] drm/amdgpu: Fix VFCT bus number matching with soft filter Greg Kroah-Hartman
` (315 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Osama Abdelkader, Liviu Dudau,
Boris Brezillon
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Osama Abdelkader <osama.abdelkader@gmail.com>
commit 4a2c8cbe9bcba170706fdf08b1c84b6cbcf5b044 upstream.
panthor_fw_load() detects truncated firmware images, but jumps to the
common cleanup path without setting ret. If no previous error was recorded,
the function can return 0 and treat the invalid firmware as successfully
loaded.
Set ret to -EINVAL before leaving the truncated-image path.
Fixes: 2718d91816ee ("drm/panthor: Add the FW logical block")
Cc: stable@vger.kernel.org
Signed-off-by: Osama Abdelkader <osama.abdelkader@gmail.com>
Reviewed-by: Liviu Dudau <liviu.dudau@arm.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Link: https://patch.msgid.link/20260714163056.22329-1-osama.abdelkader@gmail.com
Signed-off-by: Liviu Dudau <liviu.dudau@arm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/panthor/panthor_fw.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/gpu/drm/panthor/panthor_fw.c
+++ b/drivers/gpu/drm/panthor/panthor_fw.c
@@ -732,6 +732,7 @@ static int panthor_fw_load(struct pantho
}
if (hdr.size > iter.size) {
+ ret = -EINVAL;
drm_err(&ptdev->base, "Firmware image is truncated\n");
goto out;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 291/602] drm/amdgpu: Fix VFCT bus number matching with soft filter
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (289 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 290/602] drm/panthor: return error on truncated firmware Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 292/602] drm/amd/pm/ci: Dont disable MCLK DPM on Bonaire 0x6658 (R7 260X) Greg Kroah-Hartman
` (314 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Oz Tiram, Alex Deucher,
Mario Limonciello
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello <mario.limonciello@amd.com>
commit db7e8108809a2245f0a17ba323f027cac0941ffb upstream.
On systems where PCI bus renumbering occurs (e.g. pci=realloc,
resource conflicts), the runtime bus number may differ from the
BIOS POST bus number recorded in the VFCT table. This causes
amdgpu_acpi_vfct_bios() to fail finding the VBIOS even though
the correct device entry exists.
Introduce amdgpu_acpi_vfct_match() which treats the bus number
as a soft filter: vendor/device/function identity is the hard
requirement, while exact bus match is the preferred path. When
bus numbers disagree but device identity matches, accept the
VFCT entry and log a dev_notice for diagnostics.
Reported-by: Oz Tiram <oz@shift-computing.de>
Closes: https://lore.kernel.org/amd-gfx/20260621173211.28443-1-oz@shift-computing.de/
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Link: https://patch.msgid.link/20260708193518.702584-2-mario.limonciello@amd.com
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 11c141672045ffc0187aa604f2c0f597bc334fb2)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 45 +++++++++++++++++++++++++++----
1 file changed, 40 insertions(+), 5 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
@@ -345,6 +345,45 @@ static bool amdgpu_read_disabled_bios(st
}
#ifdef CONFIG_ACPI
+/**
+ * amdgpu_acpi_vfct_match() - Check if a VFCT entry matches the device
+ * @adev: AMDGPU device
+ * @vhdr: VFCT image header to check
+ *
+ * VFCT entries contain the PCI bus number as recorded during BIOS POST.
+ * On systems where the kernel renumbers PCI buses (e.g. pci=realloc or
+ * resource conflicts), the runtime bus number may differ from the POST
+ * value. Match by device identity (vendor + device + function) and use
+ * the bus number as a preference: exact bus match is preferred, but when
+ * the bus numbers disagree we accept the entry if the device identity
+ * matches.
+ *
+ * Returns: 0 on match, -ENODEV on no match
+ */
+static int amdgpu_acpi_vfct_match(struct amdgpu_device *adev,
+ VFCT_IMAGE_HEADER *vhdr)
+{
+ /* Vendor and device IDs must always match */
+ if (vhdr->VendorID != adev->pdev->vendor ||
+ vhdr->DeviceID != adev->pdev->device)
+ return -ENODEV;
+
+ if (vhdr->PCIDevice != PCI_SLOT(adev->pdev->devfn) ||
+ vhdr->PCIFunction != PCI_FUNC(adev->pdev->devfn))
+ return -ENODEV;
+
+ /* Exact bus number match - preferred */
+ if (vhdr->PCIBus == adev->pdev->bus->number)
+ return 0;
+
+ /* Bus mismatch but device identity matches (PCI renumbering case) */
+ dev_notice(adev->dev,
+ "VFCT bus number mismatch: table %u != runtime %u, matching by device identity (vendor 0x%04x device 0x%04x)\n",
+ vhdr->PCIBus, adev->pdev->bus->number,
+ adev->pdev->vendor, adev->pdev->device);
+ return 0;
+}
+
static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
{
struct acpi_table_header *hdr;
@@ -380,11 +419,7 @@ static bool amdgpu_acpi_vfct_bios(struct
}
if (vhdr->ImageLength &&
- vhdr->PCIBus == adev->pdev->bus->number &&
- vhdr->PCIDevice == PCI_SLOT(adev->pdev->devfn) &&
- vhdr->PCIFunction == PCI_FUNC(adev->pdev->devfn) &&
- vhdr->VendorID == adev->pdev->vendor &&
- vhdr->DeviceID == adev->pdev->device) {
+ !amdgpu_acpi_vfct_match(adev, vhdr)) {
adev->bios = kmemdup(&vbios->VbiosContent,
vhdr->ImageLength,
GFP_KERNEL);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 292/602] drm/amd/pm/ci: Dont disable MCLK DPM on Bonaire 0x6658 (R7 260X)
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (290 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 291/602] drm/amdgpu: Fix VFCT bus number matching with soft filter Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 293/602] drm/amd/display: set new_stream to NULL after release Greg Kroah-Hartman
` (313 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Timur Kristóf, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf <timur.kristof@gmail.com>
commit 85371c5ef502d10add72eab38711e191dccea981 upstream.
The old radeon driver has a documented workaround in ci_dpm.c
which claims that Bonaire 0x6658 with old memory controller
firmware is unstable with MCLK DPM, so as a precaution I
disabled MCLK DPM on this ASIC in amdgpu.
Note that the old MC firmware is not actually used with
amdgpu, but in theory it's possible that the VBIOS sets
up the ASIC with an old MC firmware that is already running
when amdgpu initializes (in which case amdgpu doesn't
load its own firmware).
What I expected to happen is that the GPU would simply use
its maximum memory clock, and indeed this is what seemed
to happen according to amdgpu_pm_info which reads the
current MCLK value from the SMU.
However, some users reported a huge perf regression
and upon a closer look it seems that the GPU seems to
not actually use the highest MCLK value, despite the SMU
reporting that it does.
Let's not disable MCLK DPM on Bonaire 0x6658 (R7 260X).
Keep MCLK DPM disabled on R9 M380 in the 2015 iMac
because that still hangs if we enable it.
Fixes: 9851f29cb06c ("drm/amd/pm/ci: Disable MCLK DPM on problematic CI ASICs")
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit d34acad064ee7d82bd18f5d87592c422d4d323ac)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c
@@ -106,11 +106,8 @@ int hwmgr_early_init(struct pp_hwmgr *hw
hwmgr->od_enabled = false;
switch (hwmgr->chip_id) {
case CHIP_BONAIRE:
- /* R9 M380 in iMac 2015: SMU hangs when enabling MCLK DPM
- * R7 260X cards with old MC ucode: MCLK DPM is unstable
- */
- if (adev->pdev->subsystem_vendor == 0x106B ||
- adev->pdev->device == 0x6658) {
+ /* R9 M380 in iMac 2015: SMU hangs when enabling MCLK DPM */
+ if (adev->pdev->subsystem_vendor == 0x106B) {
dev_info(adev->dev, "disabling MCLK DPM on quirky ASIC");
adev->pm.pp_feature &= ~PP_MCLK_DPM_MASK;
hwmgr->feature_mask &= ~PP_MCLK_DPM_MASK;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 293/602] drm/amd/display: set new_stream to NULL after release
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (291 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 292/602] drm/amd/pm/ci: Dont disable MCLK DPM on Bonaire 0x6658 (R7 260X) Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 294/602] drm/amd/display: dce100: skip non-DP stream encoders for DP MST Greg Kroah-Hartman
` (312 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, WenTao Liang, George Zhang,
Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: WenTao Liang <vulab@iscas.ac.cn>
commit 9fa26b9eed6195bf840f39ac183b9a6237548755 upstream.
In dm_update_crtc_state(), the skip_modeset path releases new_stream
via dc_stream_release() but does not set the pointer to NULL.
If a later error (e.g., color management failure) triggers the fail
label, the error path calls dc_stream_release() again on the same
dangling pointer, causing a double release and potential use-after-free.
Fix this by setting new_stream to NULL after the initial release.
Fixes: 9b690ef3c704 ("drm/amd/display: Avoid full modeset when not required")
Signed-off-by: WenTao Liang <vulab@iscas.ac.cn>
Reviewed-by: George Zhang <george.zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 99f3af19073b3ddbfd96e789124cce12c4277b28)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -10836,6 +10836,7 @@ skip_modeset:
/* Release extra reference */
if (new_stream)
dc_stream_release(new_stream);
+ new_stream = NULL;
/*
* We want to do dc stream updates that do not require a
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 294/602] drm/amd/display: dce100: skip non-DP stream encoders for DP MST
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (292 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 293/602] drm/amd/display: set new_stream to NULL after release Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 295/602] drm/amdgpu: Disable PCIe dynamic speed switching on Ryzen Pinnacle Ridge Greg Kroah-Hartman
` (311 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Andriy Korud, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andriy Korud <a.korud@gmail.com>
commit d340cba0df4cf327c7e89c7c1a4e79d4771d7dd5 upstream.
On DCE8-class ASICs (e.g. Bonaire), the resource pool contains digital
DIG stream encoders plus one analog DAC encoder. When assigning a stream
encoder for a second DisplayPort MST stream, if the preferred digital
encoder is already acquired, dce100_find_first_free_match_stream_enc_for_link()
falls back to the first free pool entry. That entry may be the analog
encoder, whose funcs table lacks DP hooks such as dp_set_stream_attribute.
The subsequent atomic commit then dereferences NULL function pointers in
link_set_dpms_on() and crashes.
Skip encoders without dp_set_stream_attribute when the stream uses a DP
signal (including MST). Use dc_is_dp_signal(stream->signal) for the MST
fallback path instead of checking only the link connector signal.
Tested on:
- GPU: AMD Radeon R7 260X (Bonaire / DCE8)
- Board: Supermicro C9X299-PG300
- Setup: DP MST daisy chain, hotplug second monitor or have it connected on boot
- Kernel: 7.1.3 (issue observed since 6.19)
- Result: kernel oops without patch; dual monitors stable with patch
Signed-off-by: Andriy Korud <a.korud@gmail.com>
Closes: https://gitlab.freedesktop.org/drm/amd/-/work_items/5162
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 28ec64943e3ee4d9b8d30cea61e380f1429953a8)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c
@@ -939,6 +939,11 @@ struct stream_encoder *dce100_find_first
for (i = 0; i < pool->stream_enc_count; i++) {
if (!res_ctx->is_stream_enc_acquired[i] &&
pool->stream_enc[i]) {
+ /* DP/MST needs a digital encoder; skip analog/no-DP encoders */
+ if (dc_is_dp_signal(stream->signal) &&
+ (!pool->stream_enc[i]->funcs ||
+ !pool->stream_enc[i]->funcs->dp_set_stream_attribute))
+ continue;
/* Store first available for MST second display
* in daisy chain use case
*/
@@ -962,7 +967,7 @@ struct stream_encoder *dce100_find_first
* required for non DP connectors.
*/
- if (j >= 0 && link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT)
+ if (j >= 0 && dc_is_dp_signal(stream->signal))
return pool->stream_enc[j];
return NULL;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 295/602] drm/amdgpu: Disable PCIe dynamic speed switching on Ryzen Pinnacle Ridge
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (293 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 294/602] drm/amd/display: dce100: skip non-DP stream encoders for DP MST Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 296/602] drm/amdgpu: fix bo->pin leaking in amdgpu_bo_create_reserved Greg Kroah-Hartman
` (310 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Lijo Lazar, Mario Limonciello,
Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello <mario.limonciello@amd.com>
commit 0148ac33547b9af1c5a7f3bb6e5baffcb6e9fac2 upstream.
AMD Ryzen Pinnacle Ridge (Zen+, family 0x17 model 0x08) CPUs have
PCI controllers that don't support PCIe dynamic speed switching,
causing system freezes during GPU initialization when enabled.
Disable dynamic speed switching when this CPU is detected.
Assisted-by: Claude:sonnet
Fixes: 466a7d115326 ("drm/amd: Use the first non-dGPU PCI device for BW limits")
Closes: https://gitlab.freedesktop.org/drm/amd/-/work_items/5436
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Link: https://patch.msgid.link/20260709031520.841611-1-mario.limonciello@amd.com
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 9ceb4e034a327a04155f32f1cd1a5031dfa5fe02)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 9 +++++++++
1 file changed, 9 insertions(+)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -1757,6 +1757,15 @@ static bool amdgpu_device_pcie_dynamic_s
if (c->x86_vendor == X86_VENDOR_INTEL)
return false;
+
+ /*
+ * AMD Ryzen Pinnacle Ridge (Zen+, family 0x17 model 0x08) CPUs don't
+ * support PCIe dynamic speed switching.
+ * https://gitlab.freedesktop.org/drm/amd/-/work_items/5436
+ */
+ if (c->x86_vendor == X86_VENDOR_AMD && c->x86 == 0x17 &&
+ c->x86_model == 0x08)
+ return false;
#endif
return true;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 296/602] drm/amdgpu: fix bo->pin leaking in amdgpu_bo_create_reserved
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (294 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 295/602] drm/amdgpu: Disable PCIe dynamic speed switching on Ryzen Pinnacle Ridge Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 297/602] drm/vmwgfx: Validate vmw_surface_metadata::array_size Greg Kroah-Hartman
` (309 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Zhu Lingshan, Alex Deucher,
Christian König
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhu Lingshan <lingshan.zhu@amd.com>
commit a2f895f3c852063258d62e9f74b081de07ca95df upstream.
amdgpu_bo_create_reserved() only allocates a new BO when
*bo_ptr (struct amdgpu_bo **bo_ptr as input parameter) is
NULL, it simply skips creation when *bo_ptr is non-NULL.
But it unconditionally reserves, pins, gart allocates
and maps the BO afterwards.
When the same non-NULL BO pointer is passed in again,
for example firmware buffers that live in adev and are
re-loaded on every resume / cp_resume / start
under AMDGPU_FW_LOAD_DIRECT, amdgpu_bo_pin() just increases
pin_count unconditionally, however the matching teardown only unpins
once, so pin_count never drops to zero, so TTM is not able
to move, swap or evict a BO, causing BO leaks.
This commit fixes this issue by only pinning the bo
once at creation, and repeated calls no longer
take additional pin references.
Signed-off-by: Zhu Lingshan <lingshan.zhu@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 3ddc0ae76202c447b6aec61e907b852bc94671cf)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -273,10 +273,12 @@ int amdgpu_bo_create_reserved(struct amd
goto error_free;
}
- r = amdgpu_bo_pin(*bo_ptr, domain);
- if (r) {
- dev_err(adev->dev, "(%d) kernel bo pin failed\n", r);
- goto error_unreserve;
+ if (free) {
+ r = amdgpu_bo_pin(*bo_ptr, domain);
+ if (r) {
+ dev_err(adev->dev, "(%d) kernel bo pin failed\n", r);
+ goto error_unreserve;
+ }
}
r = amdgpu_ttm_alloc_gart(&(*bo_ptr)->tbo);
@@ -299,7 +301,8 @@ int amdgpu_bo_create_reserved(struct amd
return 0;
error_unpin:
- amdgpu_bo_unpin(*bo_ptr);
+ if (free)
+ amdgpu_bo_unpin(*bo_ptr);
error_unreserve:
amdgpu_bo_unreserve(*bo_ptr);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 297/602] drm/vmwgfx: Validate vmw_surface_metadata::array_size
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (295 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 296/602] drm/amdgpu: fix bo->pin leaking in amdgpu_bo_create_reserved Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 298/602] drm/vc4: Prevent shader BO mappings from becoming writable Greg Kroah-Hartman
` (308 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Zero Day Initiative, Ian Forbes,
Maaz Mombasawala, Zack Rusin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Forbes <ian.forbes@broadcom.com>
commit a4f55260f7f7d4dc4d0ee55063dfb0c457b77991 upstream.
This field comes from userspace and should be validated against specific
limits depending on which Shader Model (SM) is available.
Fixes: 504901dbb0b5 ("drm/vmwgfx: Refactor surface_define to use vmw_surface_metadata")
Reported-by: Zero Day Initiative <zdi-disclosures@trendmicro.com>
Cc: stable@vger.kernel.org
Signed-off-by: Ian Forbes <ian.forbes@broadcom.com>
Reviewed-by: Maaz Mombasawala <maaz.mombasawala@broadcom.com>
Signed-off-by: Zack Rusin <zack.rusin@broadcom.com>
Link: https://patch.msgid.link/20260623193314.506257-1-ian.forbes@broadcom.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
@@ -96,7 +96,7 @@ static int vmw_gb_surface_unbind(struct
static int vmw_gb_surface_destroy(struct vmw_resource *res);
static int
vmw_gb_surface_define_internal(struct drm_device *dev,
- struct drm_vmw_gb_surface_create_ext_req *req,
+ const struct drm_vmw_gb_surface_create_ext_req *req,
struct drm_vmw_gb_surface_create_rep *rep,
struct drm_file *file_priv);
static int
@@ -1538,7 +1538,7 @@ int vmw_gb_surface_reference_ext_ioctl(s
*/
static int
vmw_gb_surface_define_internal(struct drm_device *dev,
- struct drm_vmw_gb_surface_create_ext_req *req,
+ const struct drm_vmw_gb_surface_create_ext_req *req,
struct drm_vmw_gb_surface_create_rep *rep,
struct drm_file *file_priv)
{
@@ -1556,9 +1556,21 @@ vmw_gb_surface_define_internal(struct dr
req->base.svga3d_flags);
/* array_size must be null for non-GL3 host. */
- if (req->base.array_size > 0 && !has_sm4_context(dev_priv)) {
- VMW_DEBUG_USER("SM4 surface not supported.\n");
- return -EINVAL;
+ if (req->base.array_size > 0) {
+ if (has_sm5_context(dev_priv)) {
+ if (req->base.array_size > SVGA3D_SM5_MAX_SURFACE_ARRAYSIZE) {
+ VMW_DEBUG_USER("Invalid Surface Array Size.\n");
+ return -EINVAL;
+ }
+ } else if (has_sm4_context(dev_priv)) {
+ if (req->base.array_size > SVGA3D_SM4_MAX_SURFACE_ARRAYSIZE) {
+ VMW_DEBUG_USER("Invalid Surface Array Size.\n");
+ return -EINVAL;
+ }
+ } else {
+ VMW_DEBUG_USER("SM4+ surface not supported.\n");
+ return -EINVAL;
+ }
}
if (!has_sm4_1_context(dev_priv)) {
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 298/602] drm/vc4: Prevent shader BO mappings from becoming writable
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (296 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 297/602] drm/vmwgfx: Validate vmw_surface_metadata::array_size Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 299/602] media: airspy: Return queued buffers on start_streaming() failure Greg Kroah-Hartman
` (307 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Sashiko, Linmao Li, Maíra Canal
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linmao Li <lilinmao@kylinos.cn>
commit 0c9e6367639548307d3f578f6943ce72c9d39087 upstream.
vc4_gem_object_mmap() rejects a writable mapping of a validated shader
BO, but leaves VM_MAYWRITE set. Userspace can map the BO read-only and
then turn it writable with mprotect().
Validated shader BOs must stay read-only: the validator checks the
instructions once and the GPU trusts them afterwards. A writable
mapping lets userspace rewrite the code after validation, bypassing the
validator.
Clear VM_MAYWRITE on the read-only path so the mapping cannot be
upgraded, as i915 already does for its read-only objects.
Fixes: 463873d57014 ("drm/vc4: Add an API for creating GPU shaders in GEM BOs.")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/dri-devel/20260720085554.B0AF01F000E9@smtp.kernel.org/
Signed-off-by: Linmao Li <lilinmao@kylinos.cn>
Link: https://patch.msgid.link/20260721011558.1672477-1-lilinmao@kylinos.cn
Reviewed-by: Maíra Canal <mcanal@igalia.com>
Signed-off-by: Maíra Canal <mcanal@igalia.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/vc4/vc4_bo.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
--- a/drivers/gpu/drm/vc4/vc4_bo.c
+++ b/drivers/gpu/drm/vc4/vc4_bo.c
@@ -733,9 +733,13 @@ static int vc4_gem_object_mmap(struct dr
{
struct vc4_bo *bo = to_vc4_bo(obj);
- if (bo->validated_shader && (vma->vm_flags & VM_WRITE)) {
- DRM_DEBUG("mmapping of shader BOs for writing not allowed.\n");
- return -EINVAL;
+ if (bo->validated_shader) {
+ if (vma->vm_flags & VM_WRITE) {
+ DRM_DEBUG("mmapping of shader BOs for writing not allowed.\n");
+ return -EINVAL;
+ }
+
+ vm_flags_clear(vma, VM_MAYWRITE);
}
mutex_lock(&bo->madv_lock);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 299/602] media: airspy: Return queued buffers on start_streaming() failure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (297 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 298/602] drm/vc4: Prevent shader BO mappings from becoming writable Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 300/602] media: aspeed: fix missing of_reserved_mem_device_release() on probe failure Greg Kroah-Hartman
` (306 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Valery Borovsky, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Valery Borovsky <vebohr@gmail.com>
commit 04344d0b4929caa94c0df72f767752aa0935ef5d upstream.
The vb2 framework hands buffers to the driver via buf_queue() before
calling start_streaming(). If start_streaming() returns an error
without first returning those buffers via vb2_buffer_done(),
vb2_start_streaming() fires WARN_ON(owned_by_drv_count) and the queued
buffers leak.
airspy_start_streaming() returned -ENODEV early when the USB device had
been disconnected (s->udev == NULL) without returning any buffers that
buf_queue() had already accepted. Take v4l2_lock first and jump to the
existing err_clear_bit label, which already drains s->queued_bufs via
vb2_buffer_done(..., VB2_BUF_STATE_QUEUED) before unlocking.
This mirrors the uvcvideo fix in commit 4cf3b6fd54eb ("media: uvcvideo:
Return queued buffers on start_streaming() failure").
Fixes: 634fe5033951 ("[media] airspy: AirSpy SDR driver")
Cc: stable@vger.kernel.org
Signed-off-by: Valery Borovsky <vebohr@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/usb/airspy/airspy.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
--- a/drivers/media/usb/airspy/airspy.c
+++ b/drivers/media/usb/airspy/airspy.c
@@ -522,11 +522,13 @@ static int airspy_start_streaming(struct
dev_dbg(s->dev, "\n");
- if (!s->udev)
- return -ENODEV;
-
mutex_lock(&s->v4l2_lock);
+ if (!s->udev) {
+ ret = -ENODEV;
+ goto err_clear_bit;
+ }
+
s->sequence = 0;
set_bit(POWER_ON, &s->flags);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 300/602] media: aspeed: fix missing of_reserved_mem_device_release() on probe failure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (298 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 299/602] media: airspy: Return queued buffers on start_streaming() failure Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 301/602] media: cec: seco: unregister adapter on IR " Greg Kroah-Hartman
` (305 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, David Carlier, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Carlier <devnexen@gmail.com>
commit 253c8ef7d57da0c74db251f385324faaa5ae2257 upstream.
aspeed_video_init() calls of_reserved_mem_device_init() to associate
reserved memory regions with the device. When aspeed_video_setup_video()
subsequently fails in aspeed_video_probe(), the error path frees the
JPEG buffer and unprepares the clocks but does not release the reserved
memory association, leaking the rmem_assigned_device entry on the global
list.
The normal remove path already calls of_reserved_mem_device_release()
correctly; only the probe error path was missing it.
Add the missing of_reserved_mem_device_release() call to the
aspeed_video_setup_video() failure cleanup.
Fixes: d2b4387f3bdf ("media: platform: Add Aspeed Video Engine driver")
Cc: stable@vger.kernel.org
Signed-off-by: David Carlier <devnexen@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/platform/aspeed/aspeed-video.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/media/platform/aspeed/aspeed-video.c
+++ b/drivers/media/platform/aspeed/aspeed-video.c
@@ -2186,6 +2186,7 @@ static int aspeed_video_probe(struct pla
rc = aspeed_video_setup_video(video);
if (rc) {
aspeed_video_free_buf(video, &video->jpeg);
+ of_reserved_mem_device_release(&pdev->dev);
clk_unprepare(video->vclk);
clk_unprepare(video->eclk);
return rc;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 301/602] media: cec: seco: unregister adapter on IR probe failure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (299 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 300/602] media: aspeed: fix missing of_reserved_mem_device_release() on probe failure Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 302/602] media: cedrus: clean up media device on " Greg Kroah-Hartman
` (304 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Myeonghun Pak, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Myeonghun Pak <mhun512@gmail.com>
commit c3a78691be8245e52ced489f268e413f18061ac2 upstream.
If secocec_ir_probe() fails after cec_register_adapter() succeeds,
probe returns an error and the driver remove callback is not called.
The current unwind path unregisters the notifier and then falls through
to cec_delete_adapter(), which violates the CEC adapter lifetime rules
after a successful registration.
Add a registered-adapter unwind path that unregisters the notifier and
the adapter instead.
Fixes: daef95769b3a ("media: seco-cec: add Consumer-IR support")
Cc: stable@vger.kernel.org
Signed-off-by: Myeonghun Pak <mhun512@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/cec/platform/seco/seco-cec.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--- a/drivers/media/cec/platform/seco/seco-cec.c
+++ b/drivers/media/cec/platform/seco/seco-cec.c
@@ -649,7 +649,7 @@ static int secocec_probe(struct platform
ret = secocec_ir_probe(secocec);
if (ret)
- goto err_notifier;
+ goto err_unregister_adapter;
platform_set_drvdata(pdev, secocec);
@@ -657,6 +657,10 @@ static int secocec_probe(struct platform
return ret;
+err_unregister_adapter:
+ cec_notifier_cec_adap_unregister(secocec->notifier, secocec->cec_adap);
+ cec_unregister_adapter(secocec->cec_adap);
+ goto err;
err_notifier:
cec_notifier_cec_adap_unregister(secocec->notifier, secocec->cec_adap);
err_delete_adapter:
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 302/602] media: cedrus: clean up media device on probe failure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (300 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 301/602] media: cec: seco: unregister adapter on IR " Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 303/602] media: cedrus: Fix missing cleanup in error path Greg Kroah-Hartman
` (303 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Paul Kocialkowski, Ijae Kim,
Myeonghun Pak, Nicolas Dufresne, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Myeonghun Pak <mhun512@gmail.com>
commit 2c869b6969f3061cbbdab587f4c0a88bd7fc3cc9 upstream.
cedrus_probe() initializes the media device before registering the video
device, the media controller, and the media device. If any of those later
steps fails, probe returns without calling media_device_cleanup(), so the
media device internals initialized by media_device_init() are left behind.
Add a media-device cleanup label to the probe unwind path and route video
registration failures through it as well.
Fixes: 50e761516f2b8c ("media: platform: Add Cedrus VPU decoder driver")
Cc: stable@vger.kernel.org
Reviewed-by: Paul Kocialkowski <paulk@sys-base.io>
Co-developed-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Myeonghun Pak <mhun512@gmail.com>
Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/staging/media/sunxi/cedrus/cedrus.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
@@ -509,7 +509,7 @@ static int cedrus_probe(struct platform_
ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0);
if (ret) {
v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
- goto err_m2m;
+ goto err_media;
}
v4l2_info(&dev->v4l2_dev,
@@ -535,7 +535,8 @@ err_m2m_mc:
v4l2_m2m_unregister_media_controller(dev->m2m_dev);
err_video:
video_unregister_device(&dev->vfd);
-err_m2m:
+err_media:
+ media_device_cleanup(&dev->mdev);
v4l2_m2m_release(dev->m2m_dev);
err_v4l2:
v4l2_device_unregister(&dev->v4l2_dev);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 303/602] media: cedrus: Fix missing cleanup in error path
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (301 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 302/602] media: cedrus: clean up media device on " Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 304/602] media: cedrus: skip invalid H.264 reference list entries Greg Kroah-Hartman
` (302 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Samuel Holland, Andrey Skvortsov,
Paul Kocialkowski, Nicolas Dufresne, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Samuel Holland <samuel@sholland.org>
commit d99732334aaf33b9f93926b70b6a11c2cef3de39 upstream.
According to the documentation struct v4l2_fh has to be cleaned up with
v4l2_fh_exit() before being freed. [1]
Currently there is no actual bug here, when v4l2_fh_exit() isn't called.
v4l2_fh_exit() in this case only destroys internal mutex. But it may
change in the future, when v4l2_fh_init/v4l2_fh_exit will be enhanced.
1. https://docs.kernel.org/driver-api/media/v4l2-fh.html
Signed-off-by: Samuel Holland <samuel@sholland.org>
Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
Fixes: 50e761516f2b ("media: platform: Add Cedrus VPU decoder driver")
Cc: stable@vger.kernel.org
Acked-by: Paul Kocialkowski <paulk@sys-base.io>
Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/staging/media/sunxi/cedrus/cedrus.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
@@ -392,6 +392,7 @@ static int cedrus_open(struct file *file
err_m2m_release:
v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
err_free:
+ v4l2_fh_exit(&ctx->fh);
kfree(ctx);
mutex_unlock(&dev->dev_mutex);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 304/602] media: cedrus: skip invalid H.264 reference list entries
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (302 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 303/602] media: cedrus: Fix missing cleanup in error path Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 305/602] media: chips-media: wave5: Move src_buf Removal to finish_encode Greg Kroah-Hartman
` (301 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Pengpeng Hou, Nicolas Dufresne,
Jernej Skrabec, Chen-Yu Tsai, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <pengpeng@iscas.ac.cn>
commit 10358ea986c3c85516d1c8206486464f79d36e76 upstream.
Cedrus consumes H.264 ref_pic_list0/ref_pic_list1 entries from the
stateless slice control and later uses their indices to look up
decode->dpb[] in _cedrus_write_ref_list().
Rejecting such controls in cedrus_try_ctrl() would break existing
userspace, since stateless H.264 reference lists may legitimately carry
out-of-range indices for missing references. Instead, guard the actual
DPB lookup in Cedrus and skip entries whose indices do not fit the fixed
V4L2_H264_NUM_DPB_ENTRIES array.
This keeps the fix local to the driver use site and avoids out-of-bounds
reads from malformed or unsupported reference list entries.
Fixes: e000e1fa4bdbd ("media: uapi: h264: Update reference lists")
Cc: stable@vger.kernel.org
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Tested-by: Chen-Yu Tsai <wens@kernel.org>
Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/staging/media/sunxi/cedrus/cedrus_h264.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus_h264.c
@@ -210,6 +210,9 @@ static void _cedrus_write_ref_list(struc
u8 dpb_idx;
dpb_idx = ref_list[i].index;
+ if (dpb_idx >= V4L2_H264_NUM_DPB_ENTRIES)
+ continue;
+
dpb = &decode->dpb[dpb_idx];
if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 305/602] media: chips-media: wave5: Move src_buf Removal to finish_encode
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (303 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 304/602] media: cedrus: skip invalid H.264 reference list entries Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 306/602] media: cx231xx: fix devres lifetime Greg Kroah-Hartman
` (300 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Brandon Brnich, Jackson Lee,
Nicolas Dufresne, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Brandon Brnich <b-brnich@ti.com>
commit b20157147089a9c16a38c7810e2fe6f2df8e3277 upstream.
During encoder processing, there is a case where the IRQ response could
return the buffer back to userspace via v4l2_m2m_buf_done call. In this
time, userspace could queue up this same buffer before start_encode removes
the index from the ready queue. This would then lead to a case where the
buffer in the ready queue could be a self loop due to the
WRITE_ONCE(prev->next, new) call in __list_add.
When __list_del is finally called, the loop is already made so nothing
points back to ready queue list head and pointers are poisoned.
A buffer should not be marked as DONE before the buffer is removed from
m2m ready queue. Move removal entirely to finish_encode.
Fixes: 9707a6254a8a6 ("media: chips-media: wave5: Add the v4l2 layer")
Cc: stable@vger.kernel.org
Signed-off-by: Brandon Brnich <b-brnich@ti.com>
Tested-by: Jackson Lee <jackson.lee@chipsnmedia.com>
Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c | 29 ++-------------
1 file changed, 4 insertions(+), 25 deletions(-)
--- a/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c
+++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-enc.c
@@ -233,13 +233,6 @@ static int start_encode(struct vpu_insta
} else {
dev_dbg(inst->dev->dev, "%s: wave5_vpu_enc_start_one_frame success\n",
__func__);
- /*
- * Remove the source buffer from the ready-queue now and finish
- * it in the videobuf2 framework once the index is returned by the
- * firmware in finish_encode
- */
- if (src_buf)
- v4l2_m2m_src_buf_remove_by_idx(m2m_ctx, src_buf->vb2_buf.index);
}
return 0;
@@ -266,27 +259,13 @@ static void wave5_vpu_enc_finish_encode(
__func__, enc_output_info.pic_type, enc_output_info.recon_frame_index,
enc_output_info.enc_src_idx, enc_output_info.enc_pic_byte, enc_output_info.pts);
- /*
- * The source buffer will not be found in the ready-queue as it has been
- * dropped after sending of the encode firmware command, locate it in
- * the videobuf2 queue directly
- */
if (enc_output_info.enc_src_idx >= 0) {
- struct vb2_buffer *vb = vb2_get_buffer(v4l2_m2m_get_src_vq(m2m_ctx),
- enc_output_info.enc_src_idx);
- if (vb->state != VB2_BUF_STATE_ACTIVE)
- dev_warn(inst->dev->dev,
- "%s: encoded buffer (%d) was not in ready queue %i.",
- __func__, enc_output_info.enc_src_idx, vb->state);
- else
- src_buf = to_vb2_v4l2_buffer(vb);
-
- if (src_buf) {
+ src_buf = v4l2_m2m_src_buf_remove_by_idx(m2m_ctx, enc_output_info.enc_src_idx);
+ if (!src_buf) {
+ dev_warn(inst->dev->dev, "%s: no source buffer found\n", __func__);
+ } else {
inst->timestamp = src_buf->vb2_buf.timestamp;
v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
- } else {
- dev_warn(inst->dev->dev, "%s: no source buffer with index: %d found\n",
- __func__, enc_output_info.enc_src_idx);
}
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 306/602] media: cx231xx: fix devres lifetime
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (304 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 305/602] media: chips-media: wave5: Move src_buf Removal to finish_encode Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 307/602] media: cx23885: add ioremap return check and cleanup Greg Kroah-Hartman
` (299 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Johan Hovold, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <johan@kernel.org>
commit 7d6358ab02866e5b7ed8d3a00805297617bbb0ec upstream.
USB drivers bind to USB interfaces and any device managed resources
should have their lifetime tied to the interface rather than parent USB
device. This avoids issues like memory leaks when drivers are unbound
without their devices being physically disconnected (e.g. on probe
deferral or configuration changes).
Fix the driver state lifetime so that it is released on driver unbind.
Fixes: 184a82784d50 ("[media] cx231xx: use devm_ functions to allocate memory")
Cc: stable@vger.kernel.org # 3.17
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/usb/cx231xx/cx231xx-cards.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
--- a/drivers/media/usb/cx231xx/cx231xx-cards.c
+++ b/drivers/media/usb/cx231xx/cx231xx-cards.c
@@ -1577,7 +1577,8 @@ static int cx231xx_init_v4l2(struct cx23
dev->video_mode.end_point_addr,
dev->video_mode.num_alt);
- dev->video_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->video_mode.num_alt, GFP_KERNEL);
+ dev->video_mode.alt_max_pkt_size = devm_kmalloc_array(&interface->dev, 32,
+ dev->video_mode.num_alt, GFP_KERNEL);
if (dev->video_mode.alt_max_pkt_size == NULL)
return -ENOMEM;
@@ -1618,7 +1619,8 @@ static int cx231xx_init_v4l2(struct cx23
dev->vbi_mode.num_alt);
/* compute alternate max packet sizes for vbi */
- dev->vbi_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->vbi_mode.num_alt, GFP_KERNEL);
+ dev->vbi_mode.alt_max_pkt_size = devm_kmalloc_array(&interface->dev, 32,
+ dev->vbi_mode.num_alt, GFP_KERNEL);
if (dev->vbi_mode.alt_max_pkt_size == NULL)
return -ENOMEM;
@@ -1660,7 +1662,9 @@ static int cx231xx_init_v4l2(struct cx23
"sliced CC EndPoint Addr 0x%x, Alternate settings: %i\n",
dev->sliced_cc_mode.end_point_addr,
dev->sliced_cc_mode.num_alt);
- dev->sliced_cc_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->sliced_cc_mode.num_alt, GFP_KERNEL);
+ dev->sliced_cc_mode.alt_max_pkt_size = devm_kmalloc_array(&interface->dev, 32,
+ dev->sliced_cc_mode.num_alt,
+ GFP_KERNEL);
if (dev->sliced_cc_mode.alt_max_pkt_size == NULL)
return -ENOMEM;
@@ -1724,7 +1728,7 @@ static int cx231xx_usb_probe(struct usb_
udev = usb_get_dev(interface_to_usbdev(interface));
/* allocate memory for our device state and initialize it */
- dev = devm_kzalloc(&udev->dev, sizeof(*dev), GFP_KERNEL);
+ dev = devm_kzalloc(&interface->dev, sizeof(*dev), GFP_KERNEL);
if (dev == NULL) {
retval = -ENOMEM;
goto err_if;
@@ -1854,7 +1858,9 @@ static int cx231xx_usb_probe(struct usb_
dev->ts1_mode.end_point_addr,
dev->ts1_mode.num_alt);
- dev->ts1_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->ts1_mode.num_alt, GFP_KERNEL);
+ dev->ts1_mode.alt_max_pkt_size = devm_kmalloc_array(&interface->dev, 32,
+ dev->ts1_mode.num_alt,
+ GFP_KERNEL);
if (dev->ts1_mode.alt_max_pkt_size == NULL) {
retval = -ENOMEM;
goto err_video_alt;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 307/602] media: cx23885: add ioremap return check and cleanup
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (305 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 306/602] media: cx231xx: fix devres lifetime Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 308/602] media: i2c: alvium: fix critical pointer access in alvium_ctrl_init Greg Kroah-Hartman
` (298 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Wang Jun, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wang Jun <1742789905@qq.com>
commit a0701e387b46e2481c05b47f1235b954bfc2af3e upstream.
Add a check for the return value of pci_ioremap_bar()
in cx23885_dev_setup().
If ioremap for BAR0 fails, release the already allocated
PCI memory region,
decrement the device count, and return -ENODEV.
This prevents a potential null pointer dereference and
ensures proper cleanup
on memory mapping failure.
Fixes: d19770e5178a ("V4L/DVB (6150): Add CX23885/CX23887 PCIe bridge driver")
Cc: stable@vger.kernel.org
Signed-off-by: Wang Jun <1742789905@qq.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/pci/cx23885/cx23885-core.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
--- a/drivers/media/pci/cx23885/cx23885-core.c
+++ b/drivers/media/pci/cx23885/cx23885-core.c
@@ -990,8 +990,12 @@ static int cx23885_dev_setup(struct cx23
}
/* PCIe stuff */
- dev->lmmio = ioremap(pci_resource_start(dev->pci, 0),
- pci_resource_len(dev->pci, 0));
+ dev->lmmio = pci_ioremap_bar(dev->pci, 0);
+ if (!dev->lmmio) {
+ dev_err(&dev->pci->dev, "CORE %s: can't ioremap MMIO memory\n",
+ dev->name);
+ goto err_release_region;
+ }
dev->bmmio = (u8 __iomem *)dev->lmmio;
@@ -1096,6 +1100,12 @@ static int cx23885_dev_setup(struct cx23
}
return 0;
+
+err_release_region:
+ release_mem_region(pci_resource_start(dev->pci, 0),
+ pci_resource_len(dev->pci, 0));
+ cx23885_devcount--;
+ return -ENODEV;
}
static void cx23885_dev_unregister(struct cx23885_dev *dev)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 308/602] media: i2c: alvium: fix critical pointer access in alvium_ctrl_init
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (306 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 307/602] media: cx23885: add ioremap return check and cleanup Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 309/602] media: intel/ipu6: Improve DWC PHY HSFREQRANGE band selection for overlapping ranges Greg Kroah-Hartman
` (297 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Martin Hecht, Sakari Ailus
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Martin Hecht <mhecht73@gmail.com>
commit 4f6f28ff24709710c08557c127b3e4c3fb1b4159 upstream.
The current implementation of alvium_ctrl_init creates several controls in
function alvium_ctrl_init and uses the returned pointer without check. That
can cause write access over NULL-pointer for several controls. The reworked
code checks the pointers before adding flags.
Fixes: 0a7af872915e ("media: i2c: Add support for alvium camera")
Cc: stable@vger.kernel.org
Signed-off-by: Martin Hecht <mhecht73@gmail.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/i2c/alvium-csi2.c | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
--- a/drivers/media/i2c/alvium-csi2.c
+++ b/drivers/media/i2c/alvium-csi2.c
@@ -2102,20 +2102,21 @@ static int alvium_ctrl_init(struct alviu
V4L2_CID_PIXEL_RATE, 0,
ALVIUM_DEFAULT_PIXEL_RATE_MHZ, 1,
ALVIUM_DEFAULT_PIXEL_RATE_MHZ);
- ctrls->pixel_rate->flags |= V4L2_CTRL_FLAG_READ_ONLY;
/* Link freq is fixed */
ctrls->link_freq = v4l2_ctrl_new_int_menu(hdl, ops,
V4L2_CID_LINK_FREQ,
0, 0, &alvium->link_freq);
- ctrls->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+ if (ctrls->link_freq)
+ ctrls->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
/* Auto/manual white balance */
if (alvium->avail_ft.auto_whiteb) {
ctrls->auto_wb = v4l2_ctrl_new_std(hdl, ops,
V4L2_CID_AUTO_WHITE_BALANCE,
0, 1, 1, 1);
- v4l2_ctrl_auto_cluster(3, &ctrls->auto_wb, 0, false);
+ if (ctrls->auto_wb)
+ v4l2_ctrl_auto_cluster(3, &ctrls->auto_wb, 0, false);
}
ctrls->blue_balance = v4l2_ctrl_new_std(hdl, ops,
@@ -2124,6 +2125,7 @@ static int alvium_ctrl_init(struct alviu
alvium->max_bbalance,
alvium->inc_bbalance,
alvium->dft_bbalance);
+
ctrls->red_balance = v4l2_ctrl_new_std(hdl, ops,
V4L2_CID_RED_BALANCE,
alvium->min_rbalance,
@@ -2138,7 +2140,9 @@ static int alvium_ctrl_init(struct alviu
V4L2_CID_EXPOSURE_AUTO,
V4L2_EXPOSURE_MANUAL, 0,
V4L2_EXPOSURE_AUTO);
- v4l2_ctrl_auto_cluster(2, &ctrls->auto_exp, 1, true);
+ if (ctrls->auto_exp)
+ v4l2_ctrl_auto_cluster(2, &ctrls->auto_exp,
+ V4L2_EXPOSURE_MANUAL, true);
}
ctrls->exposure = v4l2_ctrl_new_std(hdl, ops,
@@ -2147,14 +2151,16 @@ static int alvium_ctrl_init(struct alviu
alvium->max_exp,
alvium->inc_exp,
alvium->dft_exp);
- ctrls->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;
+ if (ctrls->exposure)
+ ctrls->exposure->flags |= V4L2_CTRL_FLAG_VOLATILE;
/* Auto/manual gain */
if (alvium->avail_ft.auto_gain) {
ctrls->auto_gain = v4l2_ctrl_new_std(hdl, ops,
V4L2_CID_AUTOGAIN,
0, 1, 1, 1);
- v4l2_ctrl_auto_cluster(2, &ctrls->auto_gain, 0, true);
+ if (ctrls->auto_gain)
+ v4l2_ctrl_auto_cluster(2, &ctrls->auto_gain, 0, true);
}
if (alvium->avail_ft.gain) {
@@ -2164,7 +2170,8 @@ static int alvium_ctrl_init(struct alviu
alvium->max_gain,
alvium->inc_gain,
alvium->dft_gain);
- ctrls->gain->flags |= V4L2_CTRL_FLAG_VOLATILE;
+ if (ctrls->gain)
+ ctrls->gain->flags |= V4L2_CTRL_FLAG_VOLATILE;
}
if (alvium->avail_ft.sat)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 309/602] media: intel/ipu6: Improve DWC PHY HSFREQRANGE band selection for overlapping ranges
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (307 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 308/602] media: i2c: alvium: fix critical pointer access in alvium_ctrl_init Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 310/602] media: marvell-cam: fix missing pci_disable_device() on remove Greg Kroah-Hartman
` (296 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Marco Nenciarini, Sakari Ailus
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marco Nenciarini <mnencia@kcore.it>
commit 477620dccf3e9481ed6ae67cb5c747f25751c531 upstream.
The get_hsfreq_by_mbps() function searches the freqranges[] table
backward (from highest to lowest index). Because adjacent frequency
bands overlap, a data rate that falls in the overlap region always
lands on the higher-indexed band.
For data rates up to 1500 Mbps (index 42) every band uses
osc_freq_target 335. Starting at index 43 (1461-1640 Mbps) the
osc_freq_target drops to 208. A sensor running at 1498 Mbps sits in
the overlap between index 42 (1414-1588, osc 335) and index 43
(1461-1640, osc 208). The backward search picks index 43, programming
the lower osc_freq_target of 208 instead of the optimal 335.
This causes DDL lock instability and CSI-2 CRC errors on affected
configurations, such as the OmniVision OV08X40 sensor on Intel Arrow
Lake platforms (Dell Pro Max 16).
Rewrite get_hsfreq_by_mbps() to select the optimal band:
1. Among bands whose min/max range covers the data rate, prefer
the one with the higher osc_freq_target.
2. If osc_freq_target is equal, prefer the band whose default_mbps
is closest to the requested rate.
Since the frequency ranges are monotonically increasing, the loop
exits early once min exceeds the requested rate.
For 1498 Mbps this now correctly selects index 42 (osc_freq_target
335, range 1414-1588) instead of index 43 (osc_freq_target 208,
range 1461-1640).
Fixes: 1e7eeb301696 ("media: intel/ipu6: add the CSI2 DPHY implementation")
Cc: stable@vger.kernel.org
Signed-off-by: Marco Nenciarini <mnencia@kcore.it>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/pci/intel/ipu6/ipu6-isys-dwc-phy.c | 24 +++++++++++++++++------
1 file changed, 18 insertions(+), 6 deletions(-)
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-dwc-phy.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-dwc-phy.c
@@ -288,15 +288,27 @@ static const struct dwc_dphy_freq_range
static u16 get_hsfreq_by_mbps(u32 mbps)
{
- unsigned int i = DPHY_FREQ_RANGE_NUM;
+ u16 best = DPHY_FREQ_RANGE_INVALID_INDEX;
+ unsigned int i;
- while (i--) {
- if (freqranges[i].default_mbps == mbps ||
- (mbps >= freqranges[i].min && mbps <= freqranges[i].max))
- return i;
+ for (i = 0; i < DPHY_FREQ_RANGE_NUM; i++) {
+ if (mbps > freqranges[i].max)
+ continue;
+
+ if (mbps < freqranges[i].min)
+ break;
+
+ if (best == DPHY_FREQ_RANGE_INVALID_INDEX ||
+ freqranges[i].osc_freq_target >
+ freqranges[best].osc_freq_target ||
+ (freqranges[i].osc_freq_target ==
+ freqranges[best].osc_freq_target &&
+ abs((int)mbps - (int)freqranges[i].default_mbps) <
+ abs((int)mbps - (int)freqranges[best].default_mbps)))
+ best = i;
}
- return DPHY_FREQ_RANGE_INVALID_INDEX;
+ return best;
}
static int ipu6_isys_dwc_phy_config(struct ipu6_isys *isys,
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 310/602] media: marvell-cam: fix missing pci_disable_device() on remove
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (308 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 309/602] media: intel/ipu6: Improve DWC PHY HSFREQRANGE band selection for overlapping ranges Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 311/602] media: meson: vdec: Fix memory leak in error path of vdec_open Greg Kroah-Hartman
` (295 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Guangshuo Li, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <lgs201920130244@gmail.com>
commit 033ff0420e4c9c240ae5523fff39770298efa964 upstream.
During manual code audit, we found that cafe_pci_probe() enables the
PCI device with pci_enable_device(), and its probe error path properly
calls pci_disable_device() on failure.
However, cafe_pci_remove() tears down the controller and frees the
driver data without disabling the PCI device, leaving the remove path
inconsistent with probe cleanup.
Add the missing pci_disable_device() call to cafe_pci_remove().
Fixes: abfa3df36c01 ("[media] marvell-cam: Separate out the Marvell camera core")
Cc: stable@vger.kernel.org
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/platform/marvell/cafe-driver.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/media/platform/marvell/cafe-driver.c
+++ b/drivers/media/platform/marvell/cafe-driver.c
@@ -609,6 +609,7 @@ static void cafe_pci_remove(struct pci_d
return;
}
cafe_shutdown(cam);
+ pci_disable_device(pdev);
kfree(cam);
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 311/602] media: meson: vdec: Fix memory leak in error path of vdec_open
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (309 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 310/602] media: marvell-cam: fix missing pci_disable_device() on remove Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 312/602] media: msi2500: Return queued buffers on start_streaming() failure Greg Kroah-Hartman
` (294 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Anand Moon, Nicolas Dufresne,
Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Anand Moon <linux.amoon@gmail.com>
commit 940f161f734b25f175a95d2684c2021f6323693a upstream.
The vdec_open() function previously jumped directly to
err_m2m_release when vdec_init_ctrls() failed, skipping
release of the m2m context. This caused a resource leak.
Fix it by introducing a proper err_m2m_ctx_release label
that calls v4l2_m2m_ctx_release(sess->m2m_ctx) before
releasing the m2m device.
This was identified via kmemleak:
unreferenced object 0xffff0000205d6878 (size 8):
comm "v4l_id", pid 5289, jiffies 4294938580
hex dump (first 8 bytes):
40 d2 49 18 00 00 ff ff @.I.....
backtrace (crc d3204599):
kmemleak_alloc+0xc8/0xf0
__kvmalloc_node_noprof+0x60c/0x850
v4l2_ctrl_handler_init_class+0x1b4/0x2e8 [videodev]
vdec_open+0x1f4/0x788 [meson_vdec]
v4l2_open+0x144/0x460 [videodev]
chrdev_open+0x1ac/0x500
do_dentry_open+0x3f0/0xfe8
vfs_open+0x68/0x320
do_open+0x2d8/0x9a8
path_openat+0x1d0/0x4f0
do_filp_open+0x190/0x380
do_sys_openat2+0xf8/0x1b0
__arm64_sys_openat+0x13c/0x1e8
invoke_syscall+0xdc/0x268
el0_svc_common.constprop.0+0x178/0x258
do_el0_svc+0x4c/0x70
Fixes: 3e7f51bd9607 ("media: meson: add v4l2 m2m video decoder driver")
Cc: stable@vger.kernel.org
Signed-off-by: Anand Moon <linux.amoon@gmail.com>
Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/staging/media/meson/vdec/vdec.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/staging/media/meson/vdec/vdec.c
+++ b/drivers/staging/media/meson/vdec/vdec.c
@@ -898,7 +898,7 @@ static int vdec_open(struct file *file)
ret = vdec_init_ctrls(sess);
if (ret)
- goto err_m2m_release;
+ goto err_m2m_ctx_release;
sess->pixfmt_cap = formats[0].pixfmts_cap[0];
sess->fmt_out = &formats[0];
@@ -923,6 +923,8 @@ static int vdec_open(struct file *file)
return 0;
+err_m2m_ctx_release:
+ v4l2_m2m_ctx_release(sess->m2m_ctx);
err_m2m_release:
v4l2_m2m_release(sess->m2m_dev);
err_free_sess:
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 312/602] media: msi2500: Return queued buffers on start_streaming() failure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (310 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 311/602] media: meson: vdec: Fix memory leak in error path of vdec_open Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 313/602] media: nuvoton: npcm-video: fix error handling in npcm_video_init() Greg Kroah-Hartman
` (293 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Valery Borovsky, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Valery Borovsky <vebohr@gmail.com>
commit 7201c17786a498497bca57752883b90914d405ac upstream.
The vb2 framework hands buffers to the driver via buf_queue() before
calling start_streaming(). If start_streaming() returns an error
without first returning those buffers via vb2_buffer_done(),
vb2_start_streaming() fires WARN_ON(owned_by_drv_count) and the queued
buffers leak.
msi2500_start_streaming() had five error paths that all hit this trap
and were further tangled by ret-overwriting between calls:
- -ENODEV when the USB device was already disconnected
- -ERESTARTSYS when mutex_lock_interruptible() was interrupted
- msi2500_set_usb_adc() failure: ret was silently overwritten by
the next call (msi2500_isoc_init), so the error was lost entirely
- msi2500_isoc_init() failure: cleanup_queued_bufs was called, but
the function then fell through to msi2500_ctrl_msg() and again
masked the original error by overwriting ret
- msi2500_ctrl_msg(CMD_START_STREAMING) failure: no cleanup at all,
leaving isoc URBs submitted with no way for the driver to consume
them
Consolidate the error paths into a small goto chain. Every failure
now stops the function, drains the queued-buffer list, and returns
the real error code. The ctrl_msg failure path also rolls back the
preceding msi2500_isoc_init() via msi2500_isoc_cleanup() before
unlocking and draining.
The cleanup helper takes a vb2_buffer_state argument so that the
start_streaming error paths can pass VB2_BUF_STATE_QUEUED (as
expected by userspace on start_streaming failure) while stop_streaming
keeps its existing VB2_BUF_STATE_ERROR semantics.
This mirrors the uvcvideo fix in commit 4cf3b6fd54eb ("media: uvcvideo:
Return queued buffers on start_streaming() failure").
Fixes: 977e444f59ad ("[media] Mirics MSi3101 SDR Dongle driver")
Cc: stable@vger.kernel.org
Signed-off-by: Valery Borovsky <vebohr@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/usb/msi2500/msi2500.c | 32 ++++++++++++++++++++++++--------
1 file changed, 24 insertions(+), 8 deletions(-)
--- a/drivers/media/usb/msi2500/msi2500.c
+++ b/drivers/media/usb/msi2500/msi2500.c
@@ -541,7 +541,8 @@ static int msi2500_isoc_init(struct msi2
}
/* Must be called with vb_queue_lock hold */
-static void msi2500_cleanup_queued_bufs(struct msi2500_dev *dev)
+static void msi2500_cleanup_queued_bufs(struct msi2500_dev *dev,
+ enum vb2_buffer_state state)
{
unsigned long flags;
@@ -554,7 +555,7 @@ static void msi2500_cleanup_queued_bufs(
buf = list_entry(dev->queued_bufs.next,
struct msi2500_frame_buf, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, state);
}
spin_unlock_irqrestore(&dev->queued_bufs_lock, flags);
}
@@ -830,25 +831,40 @@ static int msi2500_start_streaming(struc
dev_dbg(dev->dev, "\n");
- if (!dev->udev)
- return -ENODEV;
+ if (!dev->udev) {
+ ret = -ENODEV;
+ goto err_cleanup;
+ }
- if (mutex_lock_interruptible(&dev->v4l2_lock))
- return -ERESTARTSYS;
+ if (mutex_lock_interruptible(&dev->v4l2_lock)) {
+ ret = -ERESTARTSYS;
+ goto err_cleanup;
+ }
/* wake-up tuner */
v4l2_subdev_call(dev->v4l2_subdev, core, s_power, 1);
ret = msi2500_set_usb_adc(dev);
+ if (ret)
+ goto err_unlock_cleanup;
ret = msi2500_isoc_init(dev);
if (ret)
- msi2500_cleanup_queued_bufs(dev);
+ goto err_unlock_cleanup;
ret = msi2500_ctrl_msg(dev, CMD_START_STREAMING, 0);
+ if (ret)
+ goto err_isoc_cleanup;
mutex_unlock(&dev->v4l2_lock);
+ return 0;
+err_isoc_cleanup:
+ msi2500_isoc_cleanup(dev);
+err_unlock_cleanup:
+ mutex_unlock(&dev->v4l2_lock);
+err_cleanup:
+ msi2500_cleanup_queued_bufs(dev, VB2_BUF_STATE_QUEUED);
return ret;
}
@@ -863,7 +879,7 @@ static void msi2500_stop_streaming(struc
if (dev->udev)
msi2500_isoc_cleanup(dev);
- msi2500_cleanup_queued_bufs(dev);
+ msi2500_cleanup_queued_bufs(dev, VB2_BUF_STATE_ERROR);
/* according to tests, at least 700us delay is required */
msleep(20);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 313/602] media: nuvoton: npcm-video: fix error handling in npcm_video_init()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (311 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 312/602] media: msi2500: Return queued buffers on start_streaming() failure Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 314/602] media: nuvoton: npcm-video: fix memory leaks in probe and remove Greg Kroah-Hartman
` (292 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, David Carlier, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Carlier <devnexen@gmail.com>
commit 60ca00792bce46ec170c7ed101f376186d4cf8a9 upstream.
npcm_video_init() has two error handling issues after
of_reserved_mem_device_init() is called:
When dma_set_mask_and_coherent() fails, the function releases the
reserved memory but does not return, allowing execution to fall through
into npcm_video_ece_init() with a failed DMA configuration.
When npcm_video_ece_init() fails, the function returns an error without
calling of_reserved_mem_device_release(), leaking the reserved memory
association.
Fix both by adding the missing return after the DMA mask failure and
adding the missing of_reserved_mem_device_release() call on the ECE init
error path.
Fixes: 46c15a4ff1f4 ("media: nuvoton: Add driver for NPCM video capture and encoding engine")
Cc: stable@vger.kernel.org
Signed-off-by: David Carlier <devnexen@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/platform/nuvoton/npcm-video.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/media/platform/nuvoton/npcm-video.c
+++ b/drivers/media/platform/nuvoton/npcm-video.c
@@ -1719,10 +1719,12 @@ static int npcm_video_init(struct npcm_v
if (rc) {
dev_err(dev, "Failed to set DMA mask\n");
of_reserved_mem_device_release(dev);
+ return rc;
}
rc = npcm_video_ece_init(video);
if (rc) {
+ of_reserved_mem_device_release(dev);
dev_err(dev, "Failed to initialize ECE\n");
return rc;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 314/602] media: nuvoton: npcm-video: fix memory leaks in probe and remove
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (312 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 313/602] media: nuvoton: npcm-video: fix error handling in npcm_video_init() Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 315/602] media: nxp: imx8-isi: Add missing v4l2_subdev_cleanup() in crossbar and pipe Greg Kroah-Hartman
` (291 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, David Carlier, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Carlier <devnexen@gmail.com>
commit 50cc0e547da50b887e63dfa1ad203cd5b735d01e upstream.
npcm_video_probe() allocates the npcm_video structure with kzalloc_obj()
but never frees it on any probe error path or in npcm_video_remove(),
leaking the allocation on every failed probe and every normal unbind.
Additionally, when npcm_video_setup_video() fails, the reserved memory
association established by of_reserved_mem_device_init() in
npcm_video_init() is not released, leaking the rmem_assigned_device
entry on the global list.
Fix both by adding kfree(video) to all probe error paths and to
npcm_video_remove(), and adding the missing
of_reserved_mem_device_release() call when npcm_video_setup_video()
fails.
Fixes: 46c15a4ff1f4 ("media: nuvoton: Add driver for NPCM video capture and encoding engine")
Cc: stable@vger.kernel.org
Signed-off-by: David Carlier <devnexen@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/platform/nuvoton/npcm-video.c | 32 ++++++++++++++++++++--------
1 file changed, 23 insertions(+), 9 deletions(-)
--- a/drivers/media/platform/nuvoton/npcm-video.c
+++ b/drivers/media/platform/nuvoton/npcm-video.c
@@ -1749,42 +1749,55 @@ static int npcm_video_probe(struct platf
regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(regs)) {
dev_err(&pdev->dev, "Failed to parse VCD reg in DTS\n");
- return PTR_ERR(regs);
+ rc = PTR_ERR(regs);
+ goto err_free;
}
video->vcd_regmap = devm_regmap_init_mmio(&pdev->dev, regs,
&npcm_video_regmap_cfg);
if (IS_ERR(video->vcd_regmap)) {
dev_err(&pdev->dev, "Failed to initialize VCD regmap\n");
- return PTR_ERR(video->vcd_regmap);
+ rc = PTR_ERR(video->vcd_regmap);
+ goto err_free;
}
video->reset = devm_reset_control_get(&pdev->dev, NULL);
if (IS_ERR(video->reset)) {
dev_err(&pdev->dev, "Failed to get VCD reset control in DTS\n");
- return PTR_ERR(video->reset);
+ rc = PTR_ERR(video->reset);
+ goto err_free;
}
video->gcr_regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
"nuvoton,sysgcr");
- if (IS_ERR(video->gcr_regmap))
- return PTR_ERR(video->gcr_regmap);
+ if (IS_ERR(video->gcr_regmap)) {
+ rc = PTR_ERR(video->gcr_regmap);
+ goto err_free;
+ }
video->gfx_regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
"nuvoton,sysgfxi");
- if (IS_ERR(video->gfx_regmap))
- return PTR_ERR(video->gfx_regmap);
+ if (IS_ERR(video->gfx_regmap)) {
+ rc = PTR_ERR(video->gfx_regmap);
+ goto err_free;
+ }
rc = npcm_video_init(video);
if (rc)
- return rc;
+ goto err_free;
rc = npcm_video_setup_video(video);
if (rc)
- return rc;
+ goto err_release_mem;
dev_info(video->dev, "NPCM video driver probed\n");
return 0;
+
+err_release_mem:
+ of_reserved_mem_device_release(&pdev->dev);
+err_free:
+ kfree(video);
+ return rc;
}
static void npcm_video_remove(struct platform_device *pdev)
@@ -1799,6 +1812,7 @@ static void npcm_video_remove(struct pla
v4l2_device_unregister(v4l2_dev);
if (video->ece.enable)
npcm_video_ece_stop(video);
+ kfree(video);
of_reserved_mem_device_release(dev);
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 315/602] media: nxp: imx8-isi: Add missing v4l2_subdev_cleanup() in crossbar and pipe
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (313 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 314/602] media: nuvoton: npcm-video: fix memory leaks in probe and remove Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 316/602] media: nxp: imx8-isi: Clean up already-initialized pipes on probe failure Greg Kroah-Hartman
` (290 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Xiaolei Wang, Frank Li,
Laurent Pinchart, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiaolei Wang <xiaolei.wang@windriver.com>
commit 567418eedd25b3d86d489807682030b4b98b73d9 upstream.
Both mxc_isi_crossbar_init() and mxc_isi_pipe_init() call
v4l2_subdev_init_finalize() which allocates the subdev active state,
but neither mxc_isi_crossbar_cleanup() nor mxc_isi_pipe_cleanup()
calls v4l2_subdev_cleanup() to free it.
This causes a memory leak on every rmmod, reported by kmemleak:
unreferenced object 0xffff0000d06fc800 (size 192):
comm "(udev-worker)", pid 254, jiffies 4294913455
backtrace (crc 36eeae58):
kmemleak_alloc+0x34/0x40
__kvmalloc_node_noprof+0x5f8/0x7d8
__v4l2_subdev_state_alloc+0x1fc/0x30c
__v4l2_subdev_init_finalize+0x178/0x368
Add the missing v4l2_subdev_cleanup() calls before media_entity_cleanup()
in both crossbar and pipe cleanup paths.
Fixes: cf21f328fcaf ("media: nxp: Add i.MX8 ISI driver")
Cc: stable@vger.kernel.org
Signed-off-by: Xiaolei Wang <xiaolei.wang@windriver.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Link: https://patch.msgid.link/20260507041318.491594-3-xiaolei.wang@windriver.com
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c | 1 +
drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c | 1 +
2 files changed, 2 insertions(+)
--- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c
+++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-crossbar.c
@@ -494,6 +494,7 @@ err_free:
void mxc_isi_crossbar_cleanup(struct mxc_isi_crossbar *xbar)
{
+ v4l2_subdev_cleanup(&xbar->sd);
media_entity_cleanup(&xbar->sd.entity);
kfree(xbar->pads);
kfree(xbar->inputs);
--- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c
+++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c
@@ -819,6 +819,7 @@ void mxc_isi_pipe_cleanup(struct mxc_isi
{
struct v4l2_subdev *sd = &pipe->sd;
+ v4l2_subdev_cleanup(sd);
media_entity_cleanup(&sd->entity);
mutex_destroy(&pipe->lock);
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 316/602] media: nxp: imx8-isi: Clean up already-initialized pipes on probe failure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (314 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 315/602] media: nxp: imx8-isi: Add missing v4l2_subdev_cleanup() in crossbar and pipe Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 317/602] media: nxp: imx8-isi: Fix missing v4l2_subdev_cleanup() in pipe init error path Greg Kroah-Hartman
` (289 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Xiaolei Wang, Laurent Pinchart,
Frank Li, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiaolei Wang <xiaolei.wang@windriver.com>
commit d970b27cc48ec42f8a72bc3a4a4ad2e5c7a36395 upstream.
When mxc_isi_pipe_init() fails partway through the channel loop or
when mxc_isi_v4l2_init() fails, the already initialized pipes are
not cleaned up.
Fix this by calling mxc_isi_pipe_cleanup() for each already-initialized
pipe in the err_xbar error path.
Fixes: cf21f328fcaf ("media: nxp: Add i.MX8 ISI driver")
Cc: stable@vger.kernel.org
Signed-off-by: Xiaolei Wang <xiaolei.wang@windriver.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20260507041318.491594-5-xiaolei.wang@windriver.com
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c
+++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.c
@@ -501,6 +501,8 @@ static int mxc_isi_probe(struct platform
return 0;
err_xbar:
+ while (i--)
+ mxc_isi_pipe_cleanup(&isi->pipes[i]);
mxc_isi_crossbar_cleanup(&isi->crossbar);
return ret;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 317/602] media: nxp: imx8-isi: Fix missing v4l2_subdev_cleanup() in pipe init error path
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (315 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 316/602] media: nxp: imx8-isi: Clean up already-initialized pipes on probe failure Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 318/602] media: nxp: imx8-isi: Fix potential out-of-bounds issues Greg Kroah-Hartman
` (288 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Xiaolei Wang, Laurent Pinchart,
Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiaolei Wang <xiaolei.wang@windriver.com>
commit 8262de0663318124824aaafd97ddb5d7bb53bd77 upstream.
After v4l2_subdev_init_finalize() succeeds in mxc_isi_pipe_init(), if
platform_get_irq() or devm_request_irq() fails, the error path jumps to
a label that only calls media_entity_cleanup() and mutex_destroy(),
missing the v4l2_subdev_cleanup() call needed to free the subdev active
state allocated by v4l2_subdev_init_finalize().
Add an error_subdev label that calls v4l2_subdev_cleanup() before
falling through to the existing error cleanup.
Fixes: cf21f328fcaf ("media: nxp: Add i.MX8 ISI driver")
Cc: stable@vger.kernel.org
Signed-off-by: Xiaolei Wang <xiaolei.wang@windriver.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Link: https://patch.msgid.link/20260507041318.491594-4-xiaolei.wang@windriver.com
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
--- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c
+++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c
@@ -796,18 +796,20 @@ int mxc_isi_pipe_init(struct mxc_isi_dev
irq = platform_get_irq(to_platform_device(isi->dev), id);
if (irq < 0) {
ret = irq;
- goto error;
+ goto error_subdev;
}
ret = devm_request_irq(isi->dev, irq, mxc_isi_pipe_irq_handler,
0, dev_name(isi->dev), pipe);
if (ret < 0) {
dev_err(isi->dev, "failed to request IRQ (%d)\n", ret);
- goto error;
+ goto error_subdev;
}
return 0;
+error_subdev:
+ v4l2_subdev_cleanup(sd);
error:
media_entity_cleanup(&sd->entity);
mutex_destroy(&pipe->lock);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 318/602] media: nxp: imx8-isi: Fix potential out-of-bounds issues
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (316 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 317/602] media: nxp: imx8-isi: Fix missing v4l2_subdev_cleanup() in pipe init error path Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 319/602] media: nxp: imx8-isi: Fix scale factor calculation for hardware rounding Greg Kroah-Hartman
` (287 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Frank Li, Guoniu Zhou,
Laurent Pinchart, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guoniu Zhou <guoniu.zhou@nxp.com>
commit 57a7ec5c9f38ce6c4d6209c4b75c8e57e1fea6cf upstream.
The maximum downscaling factor supported by ISI can be up to 16. Add
minimum value constraint before applying the setting to hardware.
Otherwise, the process will not respond even when Ctrl+C is executed.
Fixes: cf21f328fcaf ("media: nxp: Add i.MX8 ISI driver")
Cc: stable@vger.kernel.org
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Guoniu Zhou <guoniu.zhou@nxp.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Link: https://patch.msgid.link/20260323-isi-v3-1-8df53b24e622@oss.nxp.com
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/platform/nxp/imx8-isi/imx8-isi-core.h | 16 ++++++++++++++++
drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c | 11 ++++++++---
drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c | 13 ++++++++-----
3 files changed, 32 insertions(+), 8 deletions(-)
--- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.h
+++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-core.h
@@ -11,6 +11,7 @@
#define __MXC_ISI_CORE_H__
#include <linux/list.h>
+#include <linux/math.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/types.h>
@@ -403,4 +404,19 @@ static inline void mxc_isi_debug_cleanup
}
#endif
+/*
+ * ISI scaling engine works in two parts: it performs pre-decimation of
+ * the image followed by bilinear filtering to achieve the desired
+ * downscaling factor.
+ *
+ * The decimation filter provides a maximum downscaling factor of 8, and
+ * the subsequent bilinear filter provides a maximum downscaling factor
+ * of 2. Combined, the maximum scaling factor can be up to 16.
+ */
+static inline unsigned int
+mxc_isi_clamp_downscale_16(unsigned int val, unsigned int max_val)
+{
+ return clamp(val, max(1U, DIV_ROUND_UP(max_val, 16)), max_val);
+}
+
#endif /* __MXC_ISI_CORE_H__ */
--- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c
+++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-m2m.c
@@ -504,9 +504,14 @@ __mxc_isi_m2m_try_fmt_vid(struct mxc_isi
const enum mxc_isi_video_type type)
{
if (type == MXC_ISI_VIDEO_M2M_CAP) {
- /* Downscaling only */
- pix->width = min(pix->width, ctx->queues.out.format.width);
- pix->height = min(pix->height, ctx->queues.out.format.height);
+ const struct v4l2_pix_format_mplane *format =
+ &ctx->queues.out.format;
+
+ /* Downscaling only, by up to 16. */
+ pix->width = mxc_isi_clamp_downscale_16(pix->width,
+ format->width);
+ pix->height = mxc_isi_clamp_downscale_16(pix->height,
+ format->height);
}
return mxc_isi_format_try(ctx->m2m->pipe, pix, type);
--- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c
+++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-pipe.c
@@ -641,16 +641,19 @@ static int mxc_isi_pipe_set_selection(st
/* Composing is supported on the sink only. */
return -EINVAL;
- /* The sink crop is bound by the sink format downscaling only). */
+ /*
+ * The ISI supports downscaling only, with a factor up to 16.
+ * Clamp the compose rectangle size accordingly.
+ */
format = mxc_isi_pipe_get_pad_format(pipe, state,
MXC_ISI_PIPE_PAD_SINK);
sel->r.left = 0;
sel->r.top = 0;
- sel->r.width = clamp(sel->r.width, MXC_ISI_MIN_WIDTH,
- format->width);
- sel->r.height = clamp(sel->r.height, MXC_ISI_MIN_HEIGHT,
- format->height);
+ sel->r.width = mxc_isi_clamp_downscale_16(sel->r.width,
+ format->width);
+ sel->r.height = mxc_isi_clamp_downscale_16(sel->r.height,
+ format->height);
rect = mxc_isi_pipe_get_pad_compose(pipe, state,
MXC_ISI_PIPE_PAD_SINK);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 319/602] media: nxp: imx8-isi: Fix scale factor calculation for hardware rounding
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (317 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 318/602] media: nxp: imx8-isi: Fix potential out-of-bounds issues Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 320/602] media: pci: dm1105: Free allocated workqueue Greg Kroah-Hartman
` (286 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Guoniu Zhou, Laurent Pinchart,
Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guoniu Zhou <guoniu.zhou@nxp.com>
commit 5eb54da3f874b44149556542d949909898865e29 upstream.
The ISI hardware rounds the actual output size up to an integer, as
described in i.MX93 Reference Manual section 57.7.8 (Channel 0 Scale
Factor). The scale factor must be calculated to ensure the theoretical
output value rounds up to exactly the desired size.
Fixes: cf21f328fcaf ("media: nxp: Add i.MX8 ISI driver")
Cc: stable@vger.kernel.org
Signed-off-by: Guoniu Zhou <guoniu.zhou@nxp.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Link: https://patch.msgid.link/20260323-isi-v3-2-8df53b24e622@oss.nxp.com
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
--- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c
+++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c
@@ -112,7 +112,14 @@ static u32 mxc_isi_channel_scaling_ratio
else
*dec = 8;
- return min_t(u32, from * 0x1000 / (to * *dec), ISI_DOWNSCALE_THRESHOLD);
+ /*
+ * The ISI rounds output dimensions up to the next integer (i.MX93 RM
+ * section 57.7.8). Calculate the scale factor such that the theoretical
+ * output (input / scale_factor) rounds up to exactly the desired
+ * output.
+ */
+ return min_t(u32, DIV_ROUND_UP(from * 0x1000, to * *dec),
+ ISI_DOWNSCALE_THRESHOLD);
}
static void mxc_isi_channel_set_scaling(struct mxc_isi_pipe *pipe,
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 320/602] media: pci: dm1105: Free allocated workqueue
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (318 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 319/602] media: nxp: imx8-isi: Fix scale factor calculation for hardware rounding Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 321/602] media: pwc: Drain fill_buf on start_streaming() failure Greg Kroah-Hartman
` (285 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Krzysztof Kozlowski, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
commit 1a65db225b25bb8c8febf16974c060e0cc242eb9 upstream.
Destroy allocated workqueue in remove() callback to free its resources,
thus fixing memory leak.
Fixes: 519a4bdcf822 ("V4L/DVB (11984): Add support for yet another SDMC DM1105 based DVB-S card.")
Cc: <stable@vger.kernel.org>
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/pci/dm1105/dm1105.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/media/pci/dm1105/dm1105.c
+++ b/drivers/media/pci/dm1105/dm1105.c
@@ -1194,6 +1194,7 @@ static void dm1105_remove(struct pci_dev
dm1105_hw_exit(dev);
free_irq(pdev->irq, dev);
+ destroy_workqueue(dev->wq);
pci_iounmap(pdev, dev->io_mem);
pci_release_regions(pdev);
pci_disable_device(pdev);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 321/602] media: pwc: Drain fill_buf on start_streaming() failure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (319 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 320/602] media: pci: dm1105: Free allocated workqueue Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 322/602] media: pwc: Return queued buffers " Greg Kroah-Hartman
` (284 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Valery Borovsky, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Valery Borovsky <vebohr@gmail.com>
commit 906e410dcffbbd99fb4081abab817a830033aa28 upstream.
pwc_isoc_init() submits its isochronous URBs with
usb_submit_urb(.., GFP_KERNEL) in a loop. After the first URB is
submitted, its completion handler pwc_isoc_handler() can run on another
CPU before the loop finishes:
start_streaming()
pwc_isoc_init()
usb_submit_urb(urbs[0], GFP_KERNEL)
pwc_isoc_handler(urbs[0])
pdev->fill_buf =
pwc_get_next_fill_buf(pdev)
usb_submit_urb(urbs[i>0], ..) -> fails
pwc_isoc_cleanup(pdev) /* kills URBs */
return ret;
pwc_cleanup_queued_bufs(pdev, VB2_BUF_STATE_QUEUED)
pwc_get_next_fill_buf() detaches a buffer from pdev->queued_bufs and
stores it in pdev->fill_buf. The error path in start_streaming() only
drains pdev->queued_bufs, so the buffer parked in pdev->fill_buf is
leaked. vb2_start_streaming() then triggers
WARN_ON(owned_by_drv_count).
stop_streaming() already handles this since commit 80b0963e1698
("[media] pwc: fix WARN_ON"), which added the fill_buf drain in the
teardown path but not in the start_streaming() error path. Mirror that
handling on failure so start_streaming() returns with no buffer owned
by the driver.
Issue identified by automated review of the INV-003 series at
https://sashiko.dev/
Fixes: 885fe18f5542 ("[media] pwc: Replace private buffer management code with videobuf2")
Cc: stable@vger.kernel.org
Signed-off-by: Valery Borovsky <vebohr@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/usb/pwc/pwc-if.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/drivers/media/usb/pwc/pwc-if.c
+++ b/drivers/media/usb/pwc/pwc-if.c
@@ -727,6 +727,11 @@ static int start_streaming(struct vb2_qu
pwc_camera_power(pdev, 0);
/* And cleanup any queued bufs!! */
pwc_cleanup_queued_bufs(pdev, VB2_BUF_STATE_QUEUED);
+ if (pdev->fill_buf) {
+ vb2_buffer_done(&pdev->fill_buf->vb.vb2_buf,
+ VB2_BUF_STATE_QUEUED);
+ pdev->fill_buf = NULL;
+ }
}
mutex_unlock(&pdev->v4l2_lock);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 322/602] media: pwc: Return queued buffers on start_streaming() failure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (320 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 321/602] media: pwc: Drain fill_buf on start_streaming() failure Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 323/602] media: qcom: camss: Fix RDI streaming for CSID GEN2 Greg Kroah-Hartman
` (283 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Valery Borovsky, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Valery Borovsky <vebohr@gmail.com>
commit 975b2ee20e569d47821e4f6c9761b4664d48a6a4 upstream.
The vb2 framework hands buffers to the driver via buf_queue() before
calling start_streaming(). If start_streaming() returns an error
without first returning those buffers via vb2_buffer_done(),
vb2_start_streaming() fires WARN_ON(owned_by_drv_count) and the queued
buffers leak.
pwc's start_streaming() had two early returns that hit this trap:
-ENODEV when the USB device was already disconnected, and -ERESTARTSYS
when mutex_lock_interruptible() was interrupted by a signal. Call the
existing pwc_cleanup_queued_bufs() helper with VB2_BUF_STATE_QUEUED
before returning (matching the state already used by the
pwc_isoc_init() error path in the same function).
This mirrors the uvcvideo fix in commit 4cf3b6fd54eb ("media: uvcvideo:
Return queued buffers on start_streaming() failure").
Fixes: ceede9fa8939 ("[media] pwc: Fix locking")
Cc: stable@vger.kernel.org
Signed-off-by: Valery Borovsky <vebohr@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/usb/pwc/pwc-if.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
--- a/drivers/media/usb/pwc/pwc-if.c
+++ b/drivers/media/usb/pwc/pwc-if.c
@@ -711,11 +711,15 @@ static int start_streaming(struct vb2_qu
struct pwc_device *pdev = vb2_get_drv_priv(vq);
int r;
- if (!pdev->udev)
+ if (!pdev->udev) {
+ pwc_cleanup_queued_bufs(pdev, VB2_BUF_STATE_QUEUED);
return -ENODEV;
+ }
- if (mutex_lock_interruptible(&pdev->v4l2_lock))
+ if (mutex_lock_interruptible(&pdev->v4l2_lock)) {
+ pwc_cleanup_queued_bufs(pdev, VB2_BUF_STATE_QUEUED);
return -ERESTARTSYS;
+ }
/* Turn on camera and set LEDS on */
pwc_camera_power(pdev, 1);
pwc_set_leds(pdev, leds[0], leds[1]);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 323/602] media: qcom: camss: Fix RDI streaming for CSID GEN2
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (321 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 322/602] media: pwc: Return queued buffers " Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 324/602] media: radio-si476x: Unregister v4l2_device on probe failure Greg Kroah-Hartman
` (282 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Bryan ODonoghue, Vladimir Zapolskiy,
Loic Poulain, Bryan ODonoghue
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
commit 618765634cefbdddafa84f07f82e9dd05b86cb9c upstream.
Fix streaming from CSIDn RDI1 and RDI2 to VFEn RDI1 and RDI2. A pattern we
have replicated throughout CAMSS where we use the VC number to populate
both the VC fields and port fields of the CSID means that in practice only
VC = 0 on CSIDn:RDI0 to VFEn:RDI0 works.
Fix that for CSID gen2 by separating VC and port. Fix to VC zero as a
bugfix we will look to properly populate the VC field with follow on
patches later.
Fixes: 729fc005c8e2 ("media: qcom: camss: Split testgen, RDI and RX for CSID 170")
Cc: stable@vger.kernel.org
Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Reviewed-by: Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>
Reviewed-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
Signed-off-by: Bryan O'Donoghue <bod@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/platform/qcom/camss/camss-csid-gen2.c | 47 ++++++++++----------
1 file changed, 24 insertions(+), 23 deletions(-)
--- a/drivers/media/platform/qcom/camss/camss-csid-gen2.c
+++ b/drivers/media/platform/qcom/camss/camss-csid-gen2.c
@@ -208,10 +208,10 @@ static void __csid_ctrl_rdi(struct csid_
writel_relaxed(val, csid->base + CSID_RDI_CTRL(rdi));
}
-static void __csid_configure_testgen(struct csid_device *csid, u8 enable, u8 vc)
+static void __csid_configure_testgen(struct csid_device *csid, u8 enable, u8 port, u8 vc)
{
struct csid_testgen_config *tg = &csid->testgen;
- struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc];
+ struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + port];
const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats,
csid->res->formats->nformats,
input_format->code);
@@ -258,10 +258,10 @@ static void __csid_configure_testgen(str
writel_relaxed(val, csid->base + CSID_TPG_CTRL);
}
-static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 vc)
+static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 port, u8 vc)
{
/* Source pads matching RDI channels on hardware. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. */
- struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc];
+ struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + port];
const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats,
csid->res->formats->nformats,
input_format->code);
@@ -272,14 +272,14 @@ static void __csid_configure_rdi_stream(
* the four least significant bits of the five bit VC
* bitfield to generate an internal CID value.
*
- * CSID_RDI_CFG0(vc)
+ * CSID_RDI_CFG0(port)
* DT_ID : 28:27
* VC : 26:22
* DT : 21:16
*
* CID : VC 3:0 << 2 | DT_ID 1:0
*/
- u8 dt_id = vc & 0x03;
+ u8 dt_id = port & 0x03;
val = 1 << RDI_CFG0_BYTE_CNTR_EN;
val |= 1 << RDI_CFG0_FORMAT_MEASURE_EN;
@@ -289,56 +289,57 @@ static void __csid_configure_rdi_stream(
val |= format->data_type << RDI_CFG0_DATA_TYPE;
val |= vc << RDI_CFG0_VIRTUAL_CHANNEL;
val |= dt_id << RDI_CFG0_DT_ID;
- writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc));
+ writel_relaxed(val, csid->base + CSID_RDI_CFG0(port));
/* CSID_TIMESTAMP_STB_POST_IRQ */
val = 2 << RDI_CFG1_TIMESTAMP_STB_SEL;
- writel_relaxed(val, csid->base + CSID_RDI_CFG1(vc));
+ writel_relaxed(val, csid->base + CSID_RDI_CFG1(port));
val = 1;
- writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PERIOD(vc));
+ writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PERIOD(port));
val = 0;
- writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PATTERN(vc));
+ writel_relaxed(val, csid->base + CSID_RDI_FRM_DROP_PATTERN(port));
val = 1;
- writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PERIOD(vc));
+ writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PERIOD(port));
val = 0;
- writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PATTERN(vc));
+ writel_relaxed(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PATTERN(port));
val = 1;
- writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PERIOD(vc));
+ writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PERIOD(port));
val = 0;
- writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PATTERN(vc));
+ writel_relaxed(val, csid->base + CSID_RDI_RPP_PIX_DROP_PATTERN(port));
val = 1;
- writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PERIOD(vc));
+ writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PERIOD(port));
val = 0;
- writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PATTERN(vc));
+ writel_relaxed(val, csid->base + CSID_RDI_RPP_LINE_DROP_PATTERN(port));
val = 0;
- writel_relaxed(val, csid->base + CSID_RDI_CTRL(vc));
+ writel_relaxed(val, csid->base + CSID_RDI_CTRL(port));
- val = readl_relaxed(csid->base + CSID_RDI_CFG0(vc));
+ val = readl_relaxed(csid->base + CSID_RDI_CFG0(port));
val |= enable << RDI_CFG0_ENABLE;
- writel_relaxed(val, csid->base + CSID_RDI_CFG0(vc));
+ writel_relaxed(val, csid->base + CSID_RDI_CFG0(port));
}
static void csid_configure_stream(struct csid_device *csid, u8 enable)
{
struct csid_testgen_config *tg = &csid->testgen;
u8 i;
- /* Loop through all enabled VCs and configure stream for each */
+
+ /* Loop through all enabled ports and configure a stream for each */
for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++)
if (csid->phy.en_vc & BIT(i)) {
if (tg->enabled)
- __csid_configure_testgen(csid, enable, i);
+ __csid_configure_testgen(csid, enable, i, 0);
- __csid_configure_rdi_stream(csid, enable, i);
- __csid_configure_rx(csid, &csid->phy, i);
+ __csid_configure_rdi_stream(csid, enable, i, 0);
+ __csid_configure_rx(csid, &csid->phy, 0);
__csid_ctrl_rdi(csid, enable, i);
}
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 324/602] media: radio-si476x: Unregister v4l2_device on probe failure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (322 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 323/602] media: qcom: camss: Fix RDI streaming for CSID GEN2 Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 325/602] media: rtl2832: fix use-after-free in rtl2832_remove() Greg Kroah-Hartman
` (281 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Ijae Kim, Myeonghun Pak,
Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Myeonghun Pak <mhun512@gmail.com>
commit 436a693af04ffb889aaf87cb69ec1f2b21d3569c upstream.
si476x_radio_probe() registers radio->v4l2dev before allocating the V4L2
controls and before registering the video device. If any of those later
steps fails, probe returns through the exit label after freeing only the
control handler.
A failed probe does not call si476x_radio_remove(), so the
v4l2_device_unregister() there is not reached. This leaves the parent
device reference taken by v4l2_device_register() behind on the error path.
Unregister the V4L2 device in the probe error path after freeing the
controls.
Fixes: b879a9c2a755 ("[media] v4l2: Add a V4L2 driver for SI476X MFD")
Cc: stable@vger.kernel.org
Co-developed-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Myeonghun Pak <mhun512@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/radio/radio-si476x.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/media/radio/radio-si476x.c
+++ b/drivers/media/radio/radio-si476x.c
@@ -1493,6 +1493,7 @@ static int si476x_radio_probe(struct pla
return 0;
exit:
v4l2_ctrl_handler_free(radio->videodev.ctrl_handler);
+ v4l2_device_unregister(&radio->v4l2dev);
return rval;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 325/602] media: rtl2832: fix use-after-free in rtl2832_remove()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (323 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 324/602] media: radio-si476x: Unregister v4l2_device on probe failure Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 326/602] media: rtl2832_sdr: Return queued buffers on start_streaming() failure Greg Kroah-Hartman
` (280 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, syzbot+019ced393ab913002b75,
Deepanshu Kartikey, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Deepanshu Kartikey <kartikey406@gmail.com>
commit 680daf40a82d483949f87f0d8f98639dc47e610c upstream.
cancel_delayed_work_sync() is called before i2c_mux_del_adapters()
in rtl2832_remove(). While the cancel waits for any running instance
of i2c_gate_work to finish, it does not prevent the timer from being
rescheduled by a concurrent thread.
During probe, the r820t_attach() call attempts I2C transfers through
the mux adapter. These transfers go through i2c_mux_master_xfer(),
which calls rtl2832_deselect() after the transfer completes,
rescheduling i2c_gate_work via schedule_delayed_work(). If this
transfer is still in flight when rtl2832_remove() runs,
rtl2832_deselect() can reschedule i2c_gate_work after it has been
cancelled, causing a use-after-free when kfree(dev) is called.
Fix this by calling i2c_mux_del_adapters() before
cancel_delayed_work_sync(). Once the mux adapter is unregistered, no
new I2C transfers can go through it, so rtl2832_deselect() can no
longer reschedule i2c_gate_work. The subsequent
cancel_delayed_work_sync() is then guaranteed to be final.
Fixes: cddcc40b1b15 ("[media] rtl2832: convert to use an explicit i2c mux core")
Cc: stable@vger.kernel.org
Reported-by: syzbot+019ced393ab913002b75@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=019ced393ab913002b75
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/dvb-frontends/rtl2832.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -1115,10 +1115,10 @@ static void rtl2832_remove(struct i2c_cl
dev_dbg(&client->dev, "\n");
- cancel_delayed_work_sync(&dev->i2c_gate_work);
-
i2c_mux_del_adapters(dev->muxc);
+ cancel_delayed_work_sync(&dev->i2c_gate_work);
+
regmap_exit(dev->regmap);
kfree(dev);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 326/602] media: rtl2832_sdr: Return queued buffers on start_streaming() failure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (324 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 325/602] media: rtl2832: fix use-after-free in rtl2832_remove() Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 327/602] media: saa7134: Fix a possible memory leak in saa7134_video_init1 Greg Kroah-Hartman
` (279 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Valery Borovsky, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Valery Borovsky <vebohr@gmail.com>
commit 33ca0aab6f4bd90921fc1395478f38f72c4d19af upstream.
The vb2 framework hands buffers to the driver via buf_queue() before
calling start_streaming(). If start_streaming() returns an error
without first returning those buffers via vb2_buffer_done(),
vb2_start_streaming() fires WARN_ON(owned_by_drv_count) and the queued
buffers leak.
rtl2832_sdr_start_streaming() had multiple error paths that hit this
trap: two direct early returns (-ENODEV, -ERESTARTSYS), plus six
`goto err` paths covering subdev s_power, tuner setup, ADC setup,
stream-buffer allocation, urb allocation, and urb submission failures.
None of them returned the queued buffers.
The original function had no distinct success exit and fell straight
through into the err label, which previously only did mutex_unlock and
"return ret". Adding queued-buffer cleanup at err must therefore be
paired with an explicit success return; otherwise every successful
start would also drain the buffer queue and kill streaming. Add that
success return, then add rtl2832_sdr_cleanup_queued_bufs() at the err
label and before each early return.
The cleanup helper takes a vb2_buffer_state argument so that the
start_streaming error paths can pass VB2_BUF_STATE_QUEUED (as
expected by userspace on start_streaming failure) while stop_streaming
keeps its existing VB2_BUF_STATE_ERROR semantics.
This mirrors the uvcvideo fix in commit 4cf3b6fd54eb ("media: uvcvideo:
Return queued buffers on start_streaming() failure").
The err label still does not roll back power_ctrl(), frontend_ctrl(),
the POWER_ON flag, or stream/URB allocations that may have happened
before the failing step. Those are pre-existing leaks of a different
class and are not addressed here.
Fixes: 771138920eaf ("[media] rtl2832_sdr: Realtek RTL2832 SDR driver module")
Cc: stable@vger.kernel.org
Signed-off-by: Valery Borovsky <vebohr@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/dvb-frontends/rtl2832_sdr.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
--- a/drivers/media/dvb-frontends/rtl2832_sdr.c
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.c
@@ -399,7 +399,8 @@ static int rtl2832_sdr_alloc_urbs(struct
}
/* Must be called with vb_queue_lock hold */
-static void rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_dev *dev)
+static void rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_dev *dev,
+ enum vb2_buffer_state state)
{
struct platform_device *pdev = dev->pdev;
unsigned long flags;
@@ -413,7 +414,7 @@ static void rtl2832_sdr_cleanup_queued_b
buf = list_entry(dev->queued_bufs.next,
struct rtl2832_sdr_frame_buf, list);
list_del(&buf->list);
- vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
+ vb2_buffer_done(&buf->vb.vb2_buf, state);
}
spin_unlock_irqrestore(&dev->queued_bufs_lock, flags);
}
@@ -855,11 +856,15 @@ static int rtl2832_sdr_start_streaming(s
dev_dbg(&pdev->dev, "\n");
- if (!dev->udev)
+ if (!dev->udev) {
+ rtl2832_sdr_cleanup_queued_bufs(dev, VB2_BUF_STATE_QUEUED);
return -ENODEV;
+ }
- if (mutex_lock_interruptible(&dev->v4l2_lock))
+ if (mutex_lock_interruptible(&dev->v4l2_lock)) {
+ rtl2832_sdr_cleanup_queued_bufs(dev, VB2_BUF_STATE_QUEUED);
return -ERESTARTSYS;
+ }
if (d->props->power_ctrl)
d->props->power_ctrl(d, 1);
@@ -900,7 +905,11 @@ static int rtl2832_sdr_start_streaming(s
if (ret)
goto err;
+ mutex_unlock(&dev->v4l2_lock);
+ return 0;
+
err:
+ rtl2832_sdr_cleanup_queued_bufs(dev, VB2_BUF_STATE_QUEUED);
mutex_unlock(&dev->v4l2_lock);
return ret;
@@ -920,7 +929,7 @@ static void rtl2832_sdr_stop_streaming(s
rtl2832_sdr_kill_urbs(dev);
rtl2832_sdr_free_urbs(dev);
rtl2832_sdr_free_stream_bufs(dev);
- rtl2832_sdr_cleanup_queued_bufs(dev);
+ rtl2832_sdr_cleanup_queued_bufs(dev, VB2_BUF_STATE_ERROR);
rtl2832_sdr_unset_adc(dev);
/* sleep tuner */
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 327/602] media: saa7134: Fix a possible memory leak in saa7134_video_init1
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (325 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 326/602] media: rtl2832_sdr: Return queued buffers on start_streaming() failure Greg Kroah-Hartman
@ 2026-07-30 14:11 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 328/602] media: stm32: dcmi: unregister notifier on probe failure Greg Kroah-Hartman
` (278 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:11 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Ma Ke, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ma Ke <make24@iscas.ac.cn>
commit f86ed548386e3050e5f8f25b450d09dc009d9a88 upstream.
In saa7134_video_init1(), the return value of the first
saa7134_pgtable_alloc() is not checked. If it fails, the function
continues as if successful, leaving the driver with an invalid page
table. Additionally, if vb2_queue_init() for the VBI queue fails after
the video queue page table has been allocated, the allocated memory is
not freed before returning. The second saa7134_pgtable_alloc() also
lacks a return value check. Errors occur during device probing before
the device is fully registered, the normal cleanup path in
saa7134_finidev() is not executed, leading to memory leaks and
potential use of uninitialized DMA resources.
Check the return value of both saa7134_pgtable_alloc() calls and
propagate errors. On failure of any later step, free allocated page
tables to avoid memory leaks. Ensure control handlers are also
released on error to prevent further resource leakage.
Found by code review.
Signed-off-by: Ma Ke <make24@iscas.ac.cn>
Cc: stable@vger.kernel.org
Fixes: a00e68888d5d ("[media] saa7134: move saa7134_pgtable to saa7134_dmaqueue")
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/pci/saa7134/saa7134-video.c | 25 ++++++++++++++++++++-----
1 file changed, 20 insertions(+), 5 deletions(-)
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -1716,8 +1716,10 @@ int saa7134_video_init1(struct saa7134_d
q->dev = &dev->pci->dev;
ret = vb2_queue_init(q);
if (ret)
- return ret;
- saa7134_pgtable_alloc(dev->pci, &dev->video_q.pt);
+ goto err_free_ctrl;
+ ret = saa7134_pgtable_alloc(dev->pci, &dev->video_q.pt);
+ if (ret)
+ goto err_free_ctrl;
q = &dev->vbi_vbq;
q->type = V4L2_BUF_TYPE_VBI_CAPTURE;
@@ -1734,11 +1736,24 @@ int saa7134_video_init1(struct saa7134_d
q->lock = &dev->lock;
q->dev = &dev->pci->dev;
ret = vb2_queue_init(q);
- if (ret)
- return ret;
- saa7134_pgtable_alloc(dev->pci, &dev->vbi_q.pt);
+ if (ret) {
+ saa7134_pgtable_free(dev->pci, &dev->video_q.pt);
+ goto err_free_ctrl;
+ }
+
+ ret = saa7134_pgtable_alloc(dev->pci, &dev->vbi_q.pt);
+ if (ret) {
+ saa7134_pgtable_free(dev->pci, &dev->video_q.pt);
+ goto err_free_ctrl;
+ }
return 0;
+
+err_free_ctrl:
+ v4l2_ctrl_handler_free(&dev->ctrl_handler);
+ if (card_has_radio(dev))
+ v4l2_ctrl_handler_free(&dev->radio_ctrl_handler);
+ return ret;
}
void saa7134_video_fini(struct saa7134_dev *dev)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 328/602] media: stm32: dcmi: unregister notifier on probe failure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (326 preceding siblings ...)
2026-07-30 14:11 ` [PATCH 6.12 327/602] media: saa7134: Fix a possible memory leak in saa7134_video_init1 Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 329/602] media: sun4i-csi: Return queued buffers on start_streaming() failure Greg Kroah-Hartman
` (277 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Myeonghun Pak, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Myeonghun Pak <mhun512@gmail.com>
commit 084973ebd67b28f0945c5d45408f86c58b540110 upstream.
dcmi_graph_init() registers the async notifier before dcmi_probe() toggles
the reset line. If reset_control_assert() or reset_control_deassert()
fails afterwards, probe returns through err_cleanup and the driver core
will not call dcmi_remove().
Unregister the notifier before cleaning it up on that error path,
matching the successful remove path and the V4L2 async notifier lifetime
rules.
Signed-off-by: Myeonghun Pak <mhun512@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Fixes: d079f94c9046 ("media: platform: Switch to v4l2_async_notifier_add_subdev")
Cc: stable@vger.kernel.org
[hverkuil: added Fixes tag]
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/platform/st/stm32/stm32-dcmi.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/media/platform/st/stm32/stm32-dcmi.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmi.c
@@ -2069,6 +2069,7 @@ static int dcmi_probe(struct platform_de
return 0;
err_cleanup:
+ v4l2_async_nf_unregister(&dcmi->notifier);
v4l2_async_nf_cleanup(&dcmi->notifier);
err_media_entity_cleanup:
media_entity_cleanup(&dcmi->vdev->entity);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 329/602] media: sun4i-csi: Return queued buffers on start_streaming() failure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (327 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 328/602] media: stm32: dcmi: unregister notifier on probe failure Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 330/602] media: tegra-video: vi: fix invalid u32 return value in format lookup Greg Kroah-Hartman
` (276 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Valery Borovsky, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Valery Borovsky <vebohr@gmail.com>
commit bbba3e260a62810a717b4442a3bb96d0ec0f6309 upstream.
The vb2 framework hands buffers to the driver via buf_queue() before
calling start_streaming(). If start_streaming() returns an error
without first returning those buffers via vb2_buffer_done(),
vb2_start_streaming() fires WARN_ON(owned_by_drv_count) and the queued
buffers leak.
sun4i_csi_start_streaming() returned -EINVAL when no matching CSI
format could be found, before any setup (scratch buffer allocation,
pipeline start) had been performed. The remaining error paths already
converge on the err_clear_dma_queue label, which calls
return_all_buffers(..., VB2_BUF_STATE_QUEUED) under csi->qlock. Jump
to that label directly: the intermediate err_disable_device /
err_disable_pipeline / err_free_scratch_buffer labels are skipped,
which is correct because nothing they would undo has happened yet.
This mirrors the uvcvideo fix in commit 4cf3b6fd54eb ("media: uvcvideo:
Return queued buffers on start_streaming() failure").
Fixes: 577bbf23b758 ("media: sunxi: Add A10 CSI driver")
Cc: stable@vger.kernel.org
Signed-off-by: Valery Borovsky <vebohr@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/platform/sunxi/sun4i-csi/sun4i_dma.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
--- a/drivers/media/platform/sunxi/sun4i-csi/sun4i_dma.c
+++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_dma.c
@@ -234,8 +234,10 @@ static int sun4i_csi_start_streaming(str
int ret;
csi_fmt = sun4i_csi_find_format(&csi->fmt.pixelformat, NULL);
- if (!csi_fmt)
- return -EINVAL;
+ if (!csi_fmt) {
+ ret = -EINVAL;
+ goto err_clear_dma_queue;
+ }
dev_dbg(csi->dev, "Starting capture\n");
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 330/602] media: tegra-video: vi: fix invalid u32 return value in format lookup
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (328 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 329/602] media: sun4i-csi: Return queued buffers on start_streaming() failure Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 331/602] media: ti: vpe: unwind v4l2 device registration on probe error Greg Kroah-Hartman
` (275 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Hans Verkuil, Luca Ceresoli,
Hungyu Lin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hungyu Lin <dennylin0707@gmail.com>
commit d5b50055338e131a1a99f923ebb0361974a00f36 upstream.
tegra_get_format_fourcc_by_idx() returns a u32 but uses -EINVAL to
signal an out-of-bounds index. This results in a large unsigned
value being returned, which may be interpreted as a valid fourcc.
Returning 0 is not a valid fourcc either. This condition should
never happen, so use WARN_ON_ONCE() to catch unexpected out-of-bounds
access and return a valid fallback format instead.
Suggested-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Fixes: 3d8a97eabef0 ("media: tegra-video: Add Tegra210 Video input driver")
Cc: stable@vger.kernel.org
Reviewed-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
Signed-off-by: Hungyu Lin <dennylin0707@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/staging/media/tegra-video/vi.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/staging/media/tegra-video/vi.c
+++ b/drivers/staging/media/tegra-video/vi.c
@@ -80,8 +80,8 @@ static int tegra_get_format_idx_by_code(
static u32 tegra_get_format_fourcc_by_idx(struct tegra_vi *vi,
unsigned int index)
{
- if (index >= vi->soc->nformats)
- return -EINVAL;
+ if (WARN_ON_ONCE(index >= vi->soc->nformats))
+ return vi->soc->video_formats[0].fourcc;
return vi->soc->video_formats[index].fourcc;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 331/602] media: ti: vpe: unwind v4l2 device registration on probe error
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (329 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 330/602] media: tegra-video: vi: fix invalid u32 return value in format lookup Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 332/602] media: v4l2-ctrls-request: add NULL check in v4l2_ctrl_request_complete() Greg Kroah-Hartman
` (274 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Ijae Kim, Myeonghun Pak,
Yemike Abhilash Chandra, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Myeonghun Pak <mhun512@gmail.com>
commit e0f1c9a90ef665f2587c274a8fed59f2dfc575a6 upstream.
If the vpe_top resource is missing, vpe_probe() returns -ENODEV after
v4l2_device_register() has succeeded. Probe failures do not call the
driver's remove callback, so the v4l2 device remains registered on that
error path.
Route that failure through the existing v4l2_device_unregister() unwind
label, matching the other errors after v4l2_device_register().
Fixes: 4d59c7d45585 ("media: ti-vpe: vpe: Add missing null pointer checks")
Cc: stable@vger.kernel.org
Co-developed-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Ijae Kim <ae878000@gmail.com>
Signed-off-by: Myeonghun Pak <mhun512@gmail.com>
Reviewed-by: Yemike Abhilash Chandra <y-abhilashchandra@ti.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/platform/ti/vpe/vpe.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/media/platform/ti/vpe/vpe.c
+++ b/drivers/media/platform/ti/vpe/vpe.c
@@ -2545,7 +2545,8 @@ static int vpe_probe(struct platform_dev
"vpe_top");
if (!dev->res) {
dev_err(&pdev->dev, "missing 'vpe_top' resources data\n");
- return -ENODEV;
+ ret = -ENODEV;
+ goto v4l2_dev_unreg;
}
/*
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 332/602] media: v4l2-ctrls-request: add NULL check in v4l2_ctrl_request_complete()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (330 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 331/602] media: ti: vpe: unwind v4l2 device registration on probe error Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 333/602] media: v4l2-ctrls: validate HEVC active reference counts Greg Kroah-Hartman
` (273 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Sergey Shtylyov, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sergey Shtylyov <s.shtylyov@auroraos.dev>
commit caced3578bf9f104a4aaad8f46c4c719e705d9a6 upstream.
If CONFIG_MEDIA_CONTROLLER is undefined, media_request_object_find() will
always return NULL, so its 2nd call in v4l2_ctrl_request_complete() would
fail as well as the 1st one and thus cause hdl to have a wrong value (at
the top of memory) and list_for_each_entry() to iterate over the garbage
data located there. Add NULL check for the 2nd call and place the error
cleanup at the end of v4l2_ctrl_request_complete()...
Found by Linux Verification Center (linuxtesting.org) with the Svace static
analysis tool.
Fixes: c3bf5129f339 ("media: v4l2-ctrls: always copy the controls on completion")
Cc: stable@vger.kernel.org
Signed-off-by: Sergey Shtylyov <s.shtylyov@auroraos.dev>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/v4l2-core/v4l2-ctrls-request.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
--- a/drivers/media/v4l2-core/v4l2-ctrls-request.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-request.c
@@ -348,13 +348,12 @@ void v4l2_ctrl_request_complete(struct m
ret = v4l2_ctrl_handler_init(hdl, (main_hdl->nr_of_buckets - 1) * 8);
if (!ret)
ret = v4l2_ctrl_request_bind(req, hdl, main_hdl);
- if (ret) {
- v4l2_ctrl_handler_free(hdl);
- kfree(hdl);
- return;
- }
+ if (ret)
+ goto error;
hdl->request_is_queued = true;
obj = media_request_object_find(req, &req_ops, main_hdl);
+ if (!obj)
+ goto error;
}
hdl = container_of(obj, struct v4l2_ctrl_handler, req_obj);
@@ -389,6 +388,11 @@ void v4l2_ctrl_request_complete(struct m
mutex_unlock(main_hdl->lock);
media_request_object_complete(obj);
media_request_object_put(obj);
+ return;
+
+error:
+ v4l2_ctrl_handler_free(hdl);
+ kfree(hdl);
}
EXPORT_SYMBOL(v4l2_ctrl_request_complete);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 333/602] media: v4l2-ctrls: validate HEVC active reference counts
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (331 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 332/602] media: v4l2-ctrls-request: add NULL check in v4l2_ctrl_request_complete() Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 334/602] media: v4l2-fwnode: Fix subdev owner overwritten in v4l2_async_register_subdev_sensor() Greg Kroah-Hartman
` (272 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Pengpeng Hou, Nicolas Dufresne,
Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <pengpeng@iscas.ac.cn>
commit afbe4bc252d90a6f8fad869b06d5430f615f22f9 upstream.
HEVC slice parameters are shared stateless V4L2 controls, but the common
validation path does not verify the active L0/L1 reference counts before
driver-specific code consumes them.
The original report came from Cedrus, but the active count bounds are
not Cedrus-specific. Validate them in the common HEVC slice control path
so stateless HEVC drivers get the same basic guarantees as soon as the
control is queued.
Do not reject ref_idx_l0/ref_idx_l1 entries here. Existing userspace may
use out-of-range sentinel values such as 0xff for missing references, and
some hardware can use that information for concealment. Keep this common
check limited to the active reference counts.
Fixes: d395a78db9eab ("media: hevc: Add decode params control")
Cc: stable@vger.kernel.org
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Signed-off-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/v4l2-core/v4l2-ctrls-core.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
--- a/drivers/media/v4l2-core/v4l2-ctrls-core.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls-core.c
@@ -812,6 +812,7 @@ static int std_validate_compound(const s
struct v4l2_ctrl_h264_decode_params *p_h264_dec_params;
struct v4l2_ctrl_hevc_sps *p_hevc_sps;
struct v4l2_ctrl_hevc_pps *p_hevc_pps;
+ struct v4l2_ctrl_hevc_slice_params *p_hevc_slice_params;
struct v4l2_ctrl_hdr10_mastering_display *p_hdr10_mastering;
struct v4l2_ctrl_hevc_decode_params *p_hevc_decode_params;
struct v4l2_area *area;
@@ -1100,6 +1101,18 @@ static int std_validate_compound(const s
break;
case V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS:
+ p_hevc_slice_params = p;
+
+ if (p_hevc_slice_params->num_ref_idx_l0_active_minus1 >=
+ V4L2_HEVC_DPB_ENTRIES_NUM_MAX)
+ return -EINVAL;
+
+ if (p_hevc_slice_params->slice_type != V4L2_HEVC_SLICE_TYPE_B)
+ break;
+
+ if (p_hevc_slice_params->num_ref_idx_l1_active_minus1 >=
+ V4L2_HEVC_DPB_ENTRIES_NUM_MAX)
+ return -EINVAL;
break;
case V4L2_CTRL_TYPE_HDR10_CLL_INFO:
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 334/602] media: v4l2-fwnode: Fix subdev owner overwritten in v4l2_async_register_subdev_sensor()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (332 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 333/602] media: v4l2-ctrls: validate HEVC active reference counts Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 335/602] media: v4l2-subdev: Fail {enable,disable}_streams and s_streaming nicely Greg Kroah-Hartman
` (271 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Frank Li, Mirela Rabulea,
Laurent Pinchart, Sakari Ailus
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mirela Rabulea <mirela.rabulea@nxp.com>
commit 06cb687a5132fcffe624c0070576ab852ac6b568 upstream.
The v4l2 helper v4l2_async_register_subdev_sensor() calls
v4l2_async_register_subdev(), which is a macro that expands to
__v4l2_async_register_subdev(sd,THIS_MODULE). Since the macro is expanded
inside v4l2-fwnode.c, THIS_MODULE resolves to the v4l2-fwnode module
rather than the sensor driver module that originally set sd->owner. When
v4l2-fwnode is built-in, THIS_MODULE evaluates to NULL, which then
overwrites the sensor driver's owner with NULL.
This causes the problem that the sensor module's reference count is never
incremented during async registration, so the module can be removed while
the subdevice is still in use by a notifier (e.g., a CSI-2 receiver
bridge driver).
Fix this by renaming v4l2_async_register_subdev_sensor() to
__v4l2_async_register_subdev_sensor() with an added explicit module
argument and introducing a wrapper macro:
#define v4l2_async_register_subdev_sensor(sd) \
__v4l2_async_register_subdev_sensor(sd, THIS_MODULE)
This ensures the sensor driver module is properly referenced even when
the sensor driver does not init the owner field before calling
v4l2_async_register_subdev_sensor() and prevents premature module removal.
Fixes: aef69d54755d ("media: v4l: fwnode: Add a convenience function for registering sensors")
Cc: stable@vger.kernel.org
Suggested-by: Frank Li <Frank.Li@nxp.com>
Link: https://lore.kernel.org/linux-media/20240315073125.275501-2-sakari.ailus@linux.intel.com/
Signed-off-by: Mirela Rabulea <mirela.rabulea@nxp.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/v4l2-core/v4l2-fwnode.c | 6 +++---
include/media/v4l2-async.h | 4 +++-
2 files changed, 6 insertions(+), 4 deletions(-)
--- a/drivers/media/v4l2-core/v4l2-fwnode.c
+++ b/drivers/media/v4l2-core/v4l2-fwnode.c
@@ -1205,7 +1205,7 @@ v4l2_async_nf_parse_fwnode_sensor(struct
return 0;
}
-int v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd)
+int __v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd, struct module *module)
{
struct v4l2_async_notifier *notifier;
int ret;
@@ -1231,7 +1231,7 @@ int v4l2_async_register_subdev_sensor(st
if (ret < 0)
goto out_cleanup;
- ret = v4l2_async_register_subdev(sd);
+ ret = __v4l2_async_register_subdev(sd, module);
if (ret < 0)
goto out_unregister;
@@ -1249,7 +1249,7 @@ out_cleanup:
return ret;
}
-EXPORT_SYMBOL_GPL(v4l2_async_register_subdev_sensor);
+EXPORT_SYMBOL_GPL(__v4l2_async_register_subdev_sensor);
MODULE_DESCRIPTION("V4L2 fwnode binding parsing library");
MODULE_LICENSE("GPL");
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -333,8 +333,10 @@ int __v4l2_async_register_subdev(struct
* An error is returned if the module is no longer loaded on any attempts
* to register it.
*/
+#define v4l2_async_register_subdev_sensor(sd) \
+ __v4l2_async_register_subdev_sensor(sd, THIS_MODULE)
int __must_check
-v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd);
+__v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd, struct module *module);
/**
* v4l2_async_unregister_subdev - unregisters a sub-device to the asynchronous
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 335/602] media: v4l2-subdev: Fail {enable,disable}_streams and s_streaming nicely
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (333 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 334/602] media: v4l2-fwnode: Fix subdev owner overwritten in v4l2_async_register_subdev_sensor() Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 336/602] media: vb2: use ssize_t for vb2_read/vb2_write Greg Kroah-Hartman
` (270 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Sakari Ailus, Laurent Pinchart
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sakari Ailus <sakari.ailus@linux.intel.com>
commit 0bcbfd1c1142d85faef8df5cb679d37f71394c5f upstream.
If a sub-device does not set enable_streams() and disable_streams() pad
ops while it sets the s_stream() video op to
v4l2_subdev_s_stream_helper(), enabling or disabling streaming either way
on the sub-device will result calling v4l2_subdev_s_stream_helper() and
v4l2_subdev_{enable,disable}_streams() recursively, exhausting the stack.
Return -ENOIOCTLCMD in this case to handle the situation gracefully.
Fixes: b62949ddaa52 ("media: subdev: Support single-stream case in v4l2_subdev_enable/disable_streams()")
Cc: stable@vger.kernel.org
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/v4l2-core/v4l2-subdev.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -2438,6 +2438,10 @@ int v4l2_subdev_s_stream_helper(struct v
u64 source_mask = 0;
int pad_index = -1;
+ if (WARN_ON(!v4l2_subdev_has_op(sd, pad, enable_streams) ||
+ !v4l2_subdev_has_op(sd, pad, disable_streams)))
+ return -ENOIOCTLCMD;
+
/*
* Find the source pad. This helper is meant for subdevs that have a
* single source pad, so failures shouldn't happen, but catch them
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 336/602] media: vb2: use ssize_t for vb2_read/vb2_write
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (334 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 335/602] media: v4l2-subdev: Fail {enable,disable}_streams and s_streaming nicely Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 337/602] media: vidtv: fix reference leak on failed device registration Greg Kroah-Hartman
` (269 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Zile Xiong, Marek Szyprowski,
Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zile Xiong <xiongzile99@gmail.com>
commit a562d6dc86bdfdd299e1b4734977a8d63e803583 upstream.
vb2_read() and vb2_write() return size_t, but propagate
negative errno values from __vb2_perform_fileio().
This relies on implicit signed/unsigned conversions in callers
(e.g. vb2_fop_read()) to recover error codes:
__vb2_perform_fileio() -> -EINVAL
vb2_read() -> (size_t)-EINVAL
vb2_fop_read() -> -EINVAL
This relies on implicit conversions that are not obvious.
These helpers are exported (EXPORT_SYMBOL_GPL) and part of the
vb2 API, so changing their return type may affect existing users.
However, they conceptually follow read/write semantics, where
ssize_t is typically used to return either a byte count or a
negative error code.
Switch vb2_read() and vb2_write() to ssize_t, and update
__vb2_perform_fileio() accordingly.
Signed-off-by: Zile Xiong <xiongzile99@gmail.com>
Acked-by: Marek Szyprowski <m.szyprowski@samsung.com>
Fixes: b25748fe6126 ("[media] v4l: videobuf2: add read() and write() emulator")
Cc: stable@vger.kernel.org
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/common/videobuf2/videobuf2-core.c | 12 ++++++------
include/media/videobuf2-core.h | 8 ++++----
2 files changed, 10 insertions(+), 10 deletions(-)
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -2991,8 +2991,8 @@ static int __vb2_cleanup_fileio(struct v
* @nonblock: mode selector (1 means blocking calls, 0 means nonblocking)
* @read: access mode selector (1 means read, 0 means write)
*/
-static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_t count,
- loff_t *ppos, int nonblock, int read)
+static ssize_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_t count,
+ loff_t *ppos, int nonblock, int read)
{
struct vb2_fileio_data *fileio;
struct vb2_fileio_buf *buf;
@@ -3155,15 +3155,15 @@ static size_t __vb2_perform_fileio(struc
return ret;
}
-size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
- loff_t *ppos, int nonblocking)
+ssize_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
+ loff_t *ppos, int nonblocking)
{
return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 1);
}
EXPORT_SYMBOL_GPL(vb2_read);
-size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
- loff_t *ppos, int nonblocking)
+ssize_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
+ loff_t *ppos, int nonblocking)
{
return __vb2_perform_fileio(q, (char __user *) data, count,
ppos, nonblocking, 0);
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -1106,8 +1106,8 @@ __poll_t vb2_core_poll(struct vb2_queue
* @ppos: file handle position tracking pointer
* @nonblock: mode selector (1 means blocking calls, 0 means nonblocking)
*/
-size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
- loff_t *ppos, int nonblock);
+ssize_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
+ loff_t *ppos, int nonblock);
/**
* vb2_write() - implements write() syscall logic.
* @q: pointer to &struct vb2_queue with videobuf2 queue.
@@ -1116,8 +1116,8 @@ size_t vb2_read(struct vb2_queue *q, cha
* @ppos: file handle position tracking pointer
* @nonblock: mode selector (1 means blocking calls, 0 means nonblocking)
*/
-size_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
- loff_t *ppos, int nonblock);
+ssize_t vb2_write(struct vb2_queue *q, const char __user *data, size_t count,
+ loff_t *ppos, int nonblock);
/**
* typedef vb2_thread_fnc - callback function for use with vb2_thread.
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 337/602] media: vidtv: fix reference leak on failed device registration
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (335 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 336/602] media: vb2: use ssize_t for vb2_read/vb2_write Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 338/602] media: vimc: " Greg Kroah-Hartman
` (268 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Guangshuo Li, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <lgs201920130244@gmail.com>
commit 9aa21e1549db8882ff77b691e7714153df21dff0 upstream.
When platform_device_register() fails in vidtv_bridge_init(), the
embedded struct device in vidtv_bridge_dev has already been initialized
by device_initialize(), but the failure path returns the error without
dropping the device reference for the current platform device:
vidtv_bridge_init()
-> platform_device_register(&vidtv_bridge_dev)
-> device_initialize(&vidtv_bridge_dev.dev)
-> setup_pdev_dma_masks(&vidtv_bridge_dev)
-> platform_device_add(&vidtv_bridge_dev)
This leads to a reference leak when platform_device_register() fails.
Fix this by calling platform_device_put() before returning the error.
The issue was identified by a static analysis tool I developed and
confirmed by manual review.
Fixes: f90cf6079bf67 ("media: vidtv: add a bridge driver")
Cc: stable@vger.kernel.org
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/test-drivers/vidtv/vidtv_bridge.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/media/test-drivers/vidtv/vidtv_bridge.c
+++ b/drivers/media/test-drivers/vidtv/vidtv_bridge.c
@@ -594,8 +594,10 @@ static int __init vidtv_bridge_init(void
int ret;
ret = platform_device_register(&vidtv_bridge_dev);
- if (ret)
+ if (ret) {
+ platform_device_put(&vidtv_bridge_dev);
return ret;
+ }
ret = platform_driver_register(&vidtv_bridge_driver);
if (ret)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 338/602] media: vimc: fix reference leak on failed device registration
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (336 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 337/602] media: vidtv: fix reference leak on failed device registration Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 339/602] media: vivid: add vivid_update_reduced_fps() Greg Kroah-Hartman
` (267 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Guangshuo Li, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <lgs201920130244@gmail.com>
commit 33e2b833c66b890a0d71c4fa82d4c97143f7f75f upstream.
When platform_device_register() fails in vimc_init(), the embedded
struct device in vimc_pdev has already been initialized by
device_initialize(), but the failure path returns the error without
dropping the device reference for the current platform device:
vimc_init()
-> platform_device_register(&vimc_pdev)
-> device_initialize(&vimc_pdev.dev)
-> setup_pdev_dma_masks(&vimc_pdev)
-> platform_device_add(&vimc_pdev)
This leads to a reference leak when platform_device_register() fails.
Fix this by calling platform_device_put() before returning the error.
The issue was identified by a static analysis tool I developed and
confirmed by manual review.
Fixes: 4babf057c143f ("media: vimc: allocate vimc_device dynamically")
Cc: stable@vger.kernel.org
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/test-drivers/vimc/vimc-core.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/media/test-drivers/vimc/vimc-core.c
+++ b/drivers/media/test-drivers/vimc/vimc-core.c
@@ -424,6 +424,7 @@ static int __init vimc_init(void)
if (ret) {
dev_err(&vimc_pdev.dev,
"platform device registration failed (err=%d)\n", ret);
+ platform_device_put(&vimc_pdev);
return ret;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 339/602] media: vivid: add vivid_update_reduced_fps()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (337 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 338/602] media: vimc: " Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 340/602] media: vivid: check for vb2_is_busy() when toggling caps Greg Kroah-Hartman
` (266 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Nicolas Dufresne, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hans Verkuil <hverkuil+cisco@kernel.org>
commit 1d793a29efb4260f90913f5287939bf95573b073 upstream.
Don't call vivid_update_format_cap() when switching to/from reduced fps
for HDMI inputs: that will also reset the format, which is overkill for
this.
Make a new vivid_update_reduced_fps() function that just updates the
dev->timeperframe_vid_cap.
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Fixes: c79aa6aeadb0 ("[media] vivid-capture: add control for reduced frame rate")
Cc: stable@vger.kernel.org
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/test-drivers/vivid/vivid-ctrls.c | 3 +-
drivers/media/test-drivers/vivid/vivid-vid-cap.c | 32 +++++++++++++----------
drivers/media/test-drivers/vivid/vivid-vid-cap.h | 1
3 files changed, 22 insertions(+), 14 deletions(-)
--- a/drivers/media/test-drivers/vivid/vivid-ctrls.c
+++ b/drivers/media/test-drivers/vivid/vivid-ctrls.c
@@ -576,7 +576,8 @@ static int vivid_vid_cap_s_ctrl(struct v
break;
case VIVID_CID_REDUCED_FPS:
dev->reduced_fps = ctrl->val;
- vivid_update_format_cap(dev, true);
+ if (dev->input_type[dev->input] == HDMI)
+ vivid_update_reduced_fps(dev);
break;
case VIVID_CID_HAS_CROP_CAP:
dev->has_crop_cap = ctrl->val;
--- a/drivers/media/test-drivers/vivid/vivid-vid-cap.c
+++ b/drivers/media/test-drivers/vivid/vivid-vid-cap.c
@@ -361,6 +361,24 @@ static enum tpg_pixel_aspect vivid_get_p
return TPG_PIXEL_ASPECT_SQUARE;
}
+void vivid_update_reduced_fps(struct vivid_dev *dev)
+{
+ struct v4l2_bt_timings *bt = &dev->dv_timings_cap[dev->input].bt;
+ unsigned int size = V4L2_DV_BT_FRAME_WIDTH(bt) * V4L2_DV_BT_FRAME_HEIGHT(bt);
+ u64 pixelclock;
+
+ if (dev->reduced_fps && can_reduce_fps(bt)) {
+ pixelclock = div_u64(bt->pixelclock * 1000, 1001);
+ bt->flags |= V4L2_DV_FL_REDUCED_FPS;
+ } else {
+ pixelclock = bt->pixelclock;
+ bt->flags &= ~V4L2_DV_FL_REDUCED_FPS;
+ }
+ dev->timeperframe_vid_cap = (struct v4l2_fract) {
+ size / 100, (u32)pixelclock / 100
+ };
+}
+
/*
* Called whenever the format has to be reset which can occur when
* changing inputs, standard, timings, etc.
@@ -369,8 +387,6 @@ void vivid_update_format_cap(struct vivi
{
struct v4l2_bt_timings *bt = &dev->dv_timings_cap[dev->input].bt;
u32 dims[V4L2_CTRL_MAX_DIMS] = {};
- unsigned size;
- u64 pixelclock;
switch (dev->input_type[dev->input]) {
case WEBCAM:
@@ -399,17 +415,7 @@ void vivid_update_format_cap(struct vivi
case HDMI:
dev->src_rect.width = bt->width;
dev->src_rect.height = bt->height;
- size = V4L2_DV_BT_FRAME_WIDTH(bt) * V4L2_DV_BT_FRAME_HEIGHT(bt);
- if (dev->reduced_fps && can_reduce_fps(bt)) {
- pixelclock = div_u64(bt->pixelclock * 1000, 1001);
- bt->flags |= V4L2_DV_FL_REDUCED_FPS;
- } else {
- pixelclock = bt->pixelclock;
- bt->flags &= ~V4L2_DV_FL_REDUCED_FPS;
- }
- dev->timeperframe_vid_cap = (struct v4l2_fract) {
- size / 100, (u32)pixelclock / 100
- };
+ vivid_update_reduced_fps(dev);
if (bt->interlaced)
dev->field_cap = V4L2_FIELD_ALTERNATE;
else
--- a/drivers/media/test-drivers/vivid/vivid-vid-cap.h
+++ b/drivers/media/test-drivers/vivid/vivid-vid-cap.h
@@ -9,6 +9,7 @@
#define _VIVID_VID_CAP_H_
void vivid_update_quality(struct vivid_dev *dev);
+void vivid_update_reduced_fps(struct vivid_dev *dev);
void vivid_update_format_cap(struct vivid_dev *dev, bool keep_controls);
void vivid_update_outputs(struct vivid_dev *dev);
void vivid_update_connected_outputs(struct vivid_dev *dev);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 340/602] media: vivid: check for vb2_is_busy() when toggling caps
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (338 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 339/602] media: vivid: add vivid_update_reduced_fps() Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 341/602] media: vivid: fix cleanup bugs in vivid_init() Greg Kroah-Hartman
` (265 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Nicolas Dufresne,
syzbot+dac8f5eaa46837e97b89, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hans Verkuil <hverkuil+cisco@kernel.org>
commit c2d1a2130c93f6d758af58590b86b2254c7a1dec upstream.
The vivid_update_format_cap/out() functions must only be called if the
capture/output queue are not busy. But for the controls that select
the CROP/COMPOSE/SCALE capability that is not checked.
Only when streaming starts will they be set to 'grabbed' and it is
impossible to change the control, but between REQBUFS and STREAMON you
are still allowed to set these controls. Since vivid_update_format_cap/out
will change the format, this can cause unexpected results.
Besides adding these checks, also add a WARN_ON in
vivid_update_format_cap/out() if the queue is busy.
I'm 90% certain that this is the cause of this syzbot bug:
https://syzkaller.appspot.com/bug?extid=dac8f5eaa46837e97b89
But since we never have reproducers, it is hard to be certain. In any case,
these checks are needed regardless.
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Fixes: 73c3f48230cd ("[media] vivid: add the control handling code")
Cc: stable@vger.kernel.org
Reported-by: syzbot+dac8f5eaa46837e97b89@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=dac8f5eaa46837e97b89
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/test-drivers/vivid/vivid-ctrls.c | 12 ++++++++++++
drivers/media/test-drivers/vivid/vivid-vid-cap.c | 6 ++++++
drivers/media/test-drivers/vivid/vivid-vid-out.c | 6 ++++++
3 files changed, 24 insertions(+)
--- a/drivers/media/test-drivers/vivid/vivid-ctrls.c
+++ b/drivers/media/test-drivers/vivid/vivid-ctrls.c
@@ -580,14 +580,20 @@ static int vivid_vid_cap_s_ctrl(struct v
vivid_update_reduced_fps(dev);
break;
case VIVID_CID_HAS_CROP_CAP:
+ if (vb2_is_busy(&dev->vb_vid_cap_q))
+ return -EBUSY;
dev->has_crop_cap = ctrl->val;
vivid_update_format_cap(dev, true);
break;
case VIVID_CID_HAS_COMPOSE_CAP:
+ if (vb2_is_busy(&dev->vb_vid_cap_q))
+ return -EBUSY;
dev->has_compose_cap = ctrl->val;
vivid_update_format_cap(dev, true);
break;
case VIVID_CID_HAS_SCALER_CAP:
+ if (vb2_is_busy(&dev->vb_vid_cap_q))
+ return -EBUSY;
dev->has_scaler_cap = ctrl->val;
vivid_update_format_cap(dev, true);
break;
@@ -1084,14 +1090,20 @@ static int vivid_vid_out_s_ctrl(struct v
switch (ctrl->id) {
case VIVID_CID_HAS_CROP_OUT:
+ if (vb2_is_busy(&dev->vb_vid_out_q))
+ return -EBUSY;
dev->has_crop_out = ctrl->val;
vivid_update_format_out(dev);
break;
case VIVID_CID_HAS_COMPOSE_OUT:
+ if (vb2_is_busy(&dev->vb_vid_out_q))
+ return -EBUSY;
dev->has_compose_out = ctrl->val;
vivid_update_format_out(dev);
break;
case VIVID_CID_HAS_SCALER_OUT:
+ if (vb2_is_busy(&dev->vb_vid_out_q))
+ return -EBUSY;
dev->has_scaler_out = ctrl->val;
vivid_update_format_out(dev);
break;
--- a/drivers/media/test-drivers/vivid/vivid-vid-cap.c
+++ b/drivers/media/test-drivers/vivid/vivid-vid-cap.c
@@ -388,6 +388,12 @@ void vivid_update_format_cap(struct vivi
struct v4l2_bt_timings *bt = &dev->dv_timings_cap[dev->input].bt;
u32 dims[V4L2_CTRL_MAX_DIMS] = {};
+ /*
+ * This resets the format, so must never be called while vb2_is_busy().
+ */
+ if (WARN_ON(vb2_is_busy(&dev->vb_vid_cap_q)))
+ return;
+
switch (dev->input_type[dev->input]) {
case WEBCAM:
default:
--- a/drivers/media/test-drivers/vivid/vivid-vid-out.c
+++ b/drivers/media/test-drivers/vivid/vivid-vid-out.c
@@ -215,6 +215,12 @@ void vivid_update_format_out(struct vivi
unsigned size, p;
u64 pixelclock;
+ /*
+ * This resets the format, so must never be called while vb2_is_busy().
+ */
+ if (WARN_ON(vb2_is_busy(&dev->vb_vid_out_q)))
+ return;
+
switch (dev->output_type[dev->output]) {
case SVID:
default:
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 341/602] media: vivid: fix cleanup bugs in vivid_init()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (339 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 340/602] media: vivid: check for vb2_is_busy() when toggling caps Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 342/602] media: vpif_capture: fix OF node reference imbalance Greg Kroah-Hartman
` (264 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Guangshuo Li, Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <lgs201920130244@gmail.com>
commit a07c179a92e949172ca52f6d4a13202ea88cd4b7 upstream.
When platform_device_register() fails in vivid_init(), the embedded
struct device in vivid_pdev has already been initialized by
device_initialize(), but the failure path jumps to free_output_strings
without dropping the device reference for the current platform device:
vivid_init()
-> platform_device_register(&vivid_pdev)
-> device_initialize(&vivid_pdev.dev)
-> setup_pdev_dma_masks(&vivid_pdev)
-> platform_device_add(&vivid_pdev)
This leads to a reference leak when platform_device_register() fails.
Fix this by calling platform_device_put() before jumping to the common
cleanup path.
Also, the unreg_driver label incorrectly calls
platform_driver_register() instead of platform_driver_unregister(),
which breaks cleanup when workqueue creation fails after successful
driver registration. Fix that as well.
The reference leak was identified by a static analysis tool I developed
and confirmed by manual review. The incorrect cleanup call was found
during code inspection.
Fixes: f46d740fb0258 ("[media] vivid: turn this into a platform_device")
Fixes: d7c969f37515d ("media: vivid: Add 'Is Connected To' menu controls")
Cc: stable@vger.kernel.org
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/test-drivers/vivid/vivid-core.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
--- a/drivers/media/test-drivers/vivid/vivid-core.c
+++ b/drivers/media/test-drivers/vivid/vivid-core.c
@@ -2291,8 +2291,10 @@ static int __init vivid_init(void)
}
}
ret = platform_device_register(&vivid_pdev);
- if (ret)
+ if (ret) {
+ platform_device_put(&vivid_pdev);
goto free_output_strings;
+ }
ret = platform_driver_register(&vivid_pdrv);
if (ret)
goto unreg_device;
@@ -2313,7 +2315,7 @@ static int __init vivid_init(void)
destroy_hdmi_wq:
destroy_workqueue(update_hdmi_ctrls_workqueue);
unreg_driver:
- platform_driver_register(&vivid_pdrv);
+ platform_driver_unregister(&vivid_pdrv);
unreg_device:
platform_device_unregister(&vivid_pdev);
free_output_strings:
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 342/602] media: vpif_capture: fix OF node reference imbalance
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (340 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 341/602] media: vivid: fix cleanup bugs in vivid_init() Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 343/602] ALSA: seq: close a re-opened queue timer in the destructor Greg Kroah-Hartman
` (263 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Kevin Hilman, Johan Hovold,
Hans Verkuil
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <johan@kernel.org>
commit 2282f979560af6bbc8ee2c1ee8663197312cee5b upstream.
The driver reuses the OF node of the parent device but fails to take
another reference to balance the one dropped by the platform bus code
when unbinding the parent and releasing the child devices.
Fix this by using the intended helper for reusing OF nodes.
Fixes: 4a5f8ae50b66 ("[media] davinci: vpif_capture: get subdevs from DT when available")
Cc: stable@vger.kernel.org # 4.13
Cc: Kevin Hilman <khilman@baylibre.com>
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/platform/ti/davinci/vpif_capture.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/media/platform/ti/davinci/vpif_capture.c
+++ b/drivers/media/platform/ti/davinci/vpif_capture.c
@@ -1501,7 +1501,7 @@ vpif_capture_get_pdata(struct platform_d
* video ports & endpoints data.
*/
if (pdev->dev.parent && pdev->dev.parent->of_node)
- pdev->dev.of_node = pdev->dev.parent->of_node;
+ device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent);
if (!IS_ENABLED(CONFIG_OF) || !pdev->dev.of_node)
return pdev->dev.platform_data;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 343/602] ALSA: seq: close a re-opened queue timer in the destructor
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (341 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 342/602] media: vpif_capture: fix OF node reference imbalance Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 344/602] ALSA: timer: drain a slaves callback before its master detaches it Greg Kroah-Hartman
` (262 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Norbert Szetei, Takashi Iwai
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Norbert Szetei <norbert@doyensec.com>
commit 2c4dc0ed50b05cd847a4b34b8cebf0775f19aeb9 upstream.
queue_delete() closes the queue timer, then frees it. snd_seq_timer_close()
clears q->timer->timeri. snd_use_lock_sync() then drains borrowers, and
snd_seq_timer_delete() frees q->timer.
A borrower can re-open the timer inside that window. A SET_QUEUE_CLIENT
that took a queueptr() use_lock reference before the queue was unlinked
runs snd_seq_timer_open() after the close. Open refuses re-open only while
timeri is set, and the close just cleared it, so it re-opens timeri.
snd_seq_timer_delete() does not close that instance. Its snd_seq_timer_stop()
is a no-op, because running was cleared first. So it frees q->timer with the
instance still live. The queue is freed next.
The instance stays on the global timer with callback_data pointing at the
freed queue. A non-owner START on the unlocked queue arms it. The next tick
derefs the freed queue in snd_seq_timer_interrupt().
Reachable by an unprivileged user with access to /dev/snd/seq. No CAP and
no queue ownership required.
Close any lingering instance in the destructor. There, ->timeri can no
longer change: the queue is unlinked and all use_lock borrowers have
drained, so no snd_seq_queue_use() can re-open it. Close it before clearing
q->timer. snd_timer_close() waits for any in-flight snd_seq_timer_interrupt()
to finish, and that callback still reads q->timer (via snd_seq_check_queue()),
so q->timer must stay valid until it drains.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Norbert Szetei <norbert@doyensec.com>
Link: https://patch.msgid.link/422FDB81-2A68-47C7-A22D-2D3301E2E86D@doyensec.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
sound/core/seq/seq_timer.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
--- a/sound/core/seq/seq_timer.c
+++ b/sound/core/seq/seq_timer.c
@@ -61,12 +61,23 @@ struct snd_seq_timer *snd_seq_timer_new(
void snd_seq_timer_delete(struct snd_seq_timer **tmr)
{
struct snd_seq_timer *t = *tmr;
- *tmr = NULL;
+ struct snd_timer_instance *ti;
if (t == NULL) {
pr_debug("ALSA: seq: snd_seq_timer_delete() called with NULL timer\n");
return;
}
+
+ scoped_guard(spinlock_irq, &t->lock) {
+ ti = t->timeri;
+ t->timeri = NULL;
+ }
+ if (ti) {
+ snd_timer_close(ti);
+ snd_timer_instance_free(ti);
+ }
+
+ *tmr = NULL;
t->running = 0;
/* reset time */
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 344/602] ALSA: timer: drain a slaves callback before its master detaches it
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (342 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 343/602] ALSA: seq: close a re-opened queue timer in the destructor Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 345/602] ALSA: timer: dont re-enter an instance callback that is still running Greg Kroah-Hartman
` (261 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Norbert Szetei, Takashi Iwai
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Norbert Szetei <norbert@doyensec.com>
commit bdefe1346a8e6b8dc8593406dc2617e985fcbcab upstream.
snd_timer_close_locked() drains the closing instance's own in-flight
callback (IFLG_CALLBACK) before freeing it, but not its slaves'. When a
master instance is closed, remove_slave_links() clears each slave's
->timer; the slave's own close then reads timer == NULL and takes the
branch that skips the drain entirely (snd_timer_stop_slave() also no-ops
on a NULL timer). So a slave whose callback is still running when the
master is closed is freed underneath the live callback, leading to
use-after-free.
Drain the slaves too before remove_slave_links() severs them.
snd_timer_stop() has already taken this instance off the active list, so
no new slave callback can be queued. Take the slaves off the ack list so
a pending one can't fire either, then wait for any that is already in
flight.
Fixes: 37745918e0e7 ("ALSA: timer: Introduce virtual userspace-driven timers")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Norbert Szetei <norbert@doyensec.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/D26598EB-DBF7-4D76-9F71-8E4BD59822D4@doyensec.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
sound/core/timer.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -437,10 +437,20 @@ static void snd_timer_close_locked(struc
snd_timer_stop(timeri);
if (timer) {
+ struct snd_timer_instance *slave;
+ bool busy;
+
timer->num_instances--;
- /* wait, until the active callback is finished */
+ /* unqueue then drain the slaves' callbacks before remove_slave_links() severs them */
spin_lock_irq(&timer->lock);
- while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) {
+ list_for_each_entry(slave, &timeri->slave_list_head, open_list)
+ list_del_init(&slave->ack_list);
+ for (;;) {
+ busy = timeri->flags & SNDRV_TIMER_IFLG_CALLBACK;
+ list_for_each_entry(slave, &timeri->slave_list_head, open_list)
+ busy |= slave->flags & SNDRV_TIMER_IFLG_CALLBACK;
+ if (!busy)
+ break;
spin_unlock_irq(&timer->lock);
udelay(10);
spin_lock_irq(&timer->lock);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 345/602] ALSA: timer: dont re-enter an instance callback that is still running
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (343 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 344/602] ALSA: timer: drain a slaves callback before its master detaches it Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 346/602] wifi: ath6kl: fix OOB access from firmware ADDBA window size Greg Kroah-Hartman
` (260 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Takashi Iwai, Norbert Szetei
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Norbert Szetei <norbert@doyensec.com>
commit 70d28bfcd6224eed75986b3b987b997e59643fa4 upstream.
The userspace-driven timer (utimer) TRIGGER ioctl calls
snd_timer_interrupt() directly with no serialization, so two threads
triggering the same utimer can run snd_timer_interrupt() on one
snd_timer concurrently.
snd_timer_process_callbacks() drops timer->lock around each instance
callback and marks the in-flight callback with the single
SNDRV_TIMER_IFLG_CALLBACK bit; snd_timer_close_locked() waits on that
bit to drain an in-flight callback before freeing the instance. The bit
cannot represent two concurrent callbacks: when a second interrupt
re-queues an instance whose callback is still running, both run at once,
the first to finish clears the bit, and the close-path drain then frees
the instance (and its callback_data) while the other callback is still
live - a use-after-free reachable by any user able to open
/dev/snd/timer, both via a user timer instance and via a sequencer queue
timer bound to the utimer.
snd_timer_interrupt() sets IFLG_CALLBACK before dropping timer->lock, so
a concurrent interrupt already observes it under the lock. Skip
re-queuing an instance (and its slaves) to the ack/sack list while its
callback is in flight; the accumulated pticks are delivered on the next
tick, so no event is lost.
Fixes: 37745918e0e7 ("ALSA: timer: Introduce virtual userspace-driven timers")
Cc: stable@vger.kernel.org
Suggested-by: Takashi Iwai <tiwai@suse.de>
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Norbert Szetei <norbert@doyensec.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/6F9B6501-8E65-4265-B02C-7EFB240D1664@doyensec.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
sound/core/timer.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -883,12 +883,15 @@ void snd_timer_interrupt(struct snd_time
ack_list_head = &timer->ack_list_head;
else
ack_list_head = &timer->sack_list_head;
- if (list_empty(&ti->ack_list))
+ /* don't requeue an instance whose callback is still running */
+ if (list_empty(&ti->ack_list) &&
+ !(ti->flags & SNDRV_TIMER_IFLG_CALLBACK))
list_add_tail(&ti->ack_list, ack_list_head);
list_for_each_entry(ts, &ti->slave_active_head, active_list) {
ts->pticks = ti->pticks;
ts->resolution = resolution;
- if (list_empty(&ts->ack_list))
+ if (list_empty(&ts->ack_list) &&
+ !(ts->flags & SNDRV_TIMER_IFLG_CALLBACK))
list_add_tail(&ts->ack_list, ack_list_head);
}
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 346/602] wifi: ath6kl: fix OOB access from firmware ADDBA window size
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (344 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 345/602] ALSA: timer: dont re-enter an instance callback that is still running Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 347/602] wifi: mwifiex: fix NULL dereference when the AP has HT-cap but no HT-oper Greg Kroah-Hartman
` (259 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Vasanthakumar Thiagarajan,
Tristan Madani, Jeff Johnson
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <tristan@talencesecurity.com>
commit 44126b6994eeb28f2103b638e698f40a1244f327 upstream.
aggr_recv_addba_req_evt() logs a debug message when the firmware-supplied
win_sz is outside [AGGR_WIN_SZ_MIN, AGGR_WIN_SZ_MAX] but does not
return. The out-of-range win_sz is then used in TID_WINDOW_SZ() to
compute a kzalloc size and stored in rxtid->hold_q_sz, leading to
zero-size or overflowed allocations and subsequent out-of-bounds access.
Clean up any previously active aggregation session for the TID first,
then return early when win_sz is out of the valid range, instead of
proceeding with a broken allocation size.
Fixes: bdcd81707973 ("Add ath6kl cleaned up driver")
Cc: stable@vger.kernel.org
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
Signed-off-by: Tristan Madani <tristan@talencesecurity.com>
Link: https://patch.msgid.link/20260702005020.708717-1-tristmd@gmail.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/wireless/ath/ath6kl/txrx.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
--- a/drivers/net/wireless/ath/ath6kl/txrx.c
+++ b/drivers/net/wireless/ath/ath6kl/txrx.c
@@ -1722,13 +1722,15 @@ void aggr_recv_addba_req_evt(struct ath6
rxtid = &aggr_conn->rx_tid[tid];
- if (win_sz < AGGR_WIN_SZ_MIN || win_sz > AGGR_WIN_SZ_MAX)
- ath6kl_dbg(ATH6KL_DBG_WLAN_RX, "%s: win_sz %d, tid %d\n",
- __func__, win_sz, tid);
-
if (rxtid->aggr)
aggr_delete_tid_state(aggr_conn, tid);
+ if (win_sz < AGGR_WIN_SZ_MIN || win_sz > AGGR_WIN_SZ_MAX) {
+ ath6kl_dbg(ATH6KL_DBG_WLAN_RX, "%s: win_sz %d, tid %d\n",
+ __func__, win_sz, tid);
+ return;
+ }
+
rxtid->seq_next = seq_no;
hold_q_size = TID_WINDOW_SZ(win_sz) * sizeof(struct skb_hold_q);
rxtid->hold_q = kzalloc(hold_q_size, GFP_KERNEL);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 347/602] wifi: mwifiex: fix NULL dereference when the AP has HT-cap but no HT-oper
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (345 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 346/602] wifi: ath6kl: fix OOB access from firmware ADDBA window size Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 348/602] wifi: wilc1000: validate assoc response length before subtracting header Greg Kroah-Hartman
` (258 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Doruk Tan Ozturk, Francesco Dolcini,
Johannes Berg
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Doruk Tan Ozturk <doruk@0sec.ai>
commit c3d68e294cbb6a4090bb219d3dcaca85a011809b upstream.
mwifiex_tdls_add_ht_oper() gates its follow-the-AP-bandwidth path on
bss_desc->bcn_ht_cap being present, but then dereferences a different
pointer, bss_desc->bcn_ht_oper:
if (ISSUPP_CHANWIDTH40(priv->adapter->hw_dot_11n_dev_cap) &&
bss_desc->bcn_ht_cap &&
ISALLOWED_CHANWIDTH40(bss_desc->bcn_ht_oper->ht_param))
bcn_ht_cap and bcn_ht_oper are populated independently while parsing the
associated AP's beacon in mwifiex_update_bss_desc_with_ie(): an AP that
advertises an HT Capabilities element but no HT Operation element leaves
bcn_ht_cap non-NULL and bcn_ht_oper NULL. Setting up a TDLS link to a
peer while associated to such an AP then dereferences the NULL
bcn_ht_oper and crashes the kernel. Every other bcn_ht_oper user in the
driver NULL-checks it first.
Guard on the pointer that is actually dereferenced.
Found by 0sec automated security-research tooling (https://0sec.ai).
Fixes: 396939f94084 ("mwifiex: add HT operation IE in TDLS setup confirm")
Cc: stable@vger.kernel.org
Assisted-by: 0sec:multi-model
Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
Reviewed-by: Francesco Dolcini <francesco.dolcini@toradex.com>
Link: https://patch.msgid.link/20260716103042.88469-1-doruk@0sec.ai
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/wireless/marvell/mwifiex/tdls.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/wireless/marvell/mwifiex/tdls.c
+++ b/drivers/net/wireless/marvell/mwifiex/tdls.c
@@ -215,7 +215,7 @@ mwifiex_tdls_add_ht_oper(struct mwifiex_
/* follow AP's channel bandwidth */
if (ISSUPP_CHANWIDTH40(priv->adapter->hw_dot_11n_dev_cap) &&
- bss_desc->bcn_ht_cap &&
+ bss_desc->bcn_ht_oper &&
ISALLOWED_CHANWIDTH40(bss_desc->bcn_ht_oper->ht_param))
ht_oper->ht_param = bss_desc->bcn_ht_oper->ht_param;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 348/602] wifi: wilc1000: validate assoc response length before subtracting header
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (346 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 347/602] wifi: mwifiex: fix NULL dereference when the AP has HT-cap but no HT-oper Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 349/602] wifi: mt76: mt7615: drop TXRX_NOTIFY on non-mmio buses Greg Kroah-Hartman
` (257 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Huihui Huang, Johannes Berg
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Huihui Huang <hhhuang@smu.edu.sg>
commit 4c4c97b60a5e978121d9ee8cb0ab3916e5d6a8de upstream.
wilc_parse_assoc_resp_info() computes the trailing IE length as
ies_len = buffer_len - sizeof(*res);
without first checking that buffer_len is at least sizeof(struct
wilc_assoc_resp) (6 bytes). buffer_len is the length reported for a
received association response (host_int_parse_assoc_resp_info() passes
hif_drv->assoc_resp / assoc_resp_info_len straight in) and must be
validated before the driver accesses the fixed header.
For a frame shorter than the 6-byte fixed header, the subtraction wraps.
For a four-byte response the result is truncated to a u16 ies_len of
65534, so kmemdup() then attempts to copy 65534 bytes starting at
buffer + sizeof(*res), beyond the valid association-response data
(CWE-125). A response shorter than four bytes can also cause an
out-of-bounds read of res->status_code at offsets 2 and 3.
Reject frames too short to hold the fixed header before touching the
header or computing ies_len. Also set the connection status to a failure
on this path: the caller falls through to a
"conn_info->status == WLAN_STATUS_SUCCESS" check after the parser
returns, so leaving the status untouched could let a malformed short
response be treated as a successful association.
Fixes: c5c77ba18ea6 ("staging: wilc1000: Add SDIO/SPI 802.11 driver")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Huihui Huang <hhhuang@smu.edu.sg>
Link: https://patch.msgid.link/20260714091811.3596126-1-hhhuang@smu.edu.sg
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/wireless/microchip/wilc1000/hif.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/drivers/net/wireless/microchip/wilc1000/hif.c
+++ b/drivers/net/wireless/microchip/wilc1000/hif.c
@@ -600,6 +600,11 @@ static s32 wilc_parse_assoc_resp_info(u8
u16 ies_len;
struct wilc_assoc_resp *res = (struct wilc_assoc_resp *)buffer;
+ if (buffer_len < sizeof(*res)) {
+ ret_conn_info->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ return -EINVAL;
+ }
+
ret_conn_info->status = le16_to_cpu(res->status_code);
if (ret_conn_info->status == WLAN_STATUS_SUCCESS) {
ies = &buffer[sizeof(*res)];
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 349/602] wifi: mt76: mt7615: drop TXRX_NOTIFY on non-mmio buses
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (347 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 348/602] wifi: wilc1000: validate assoc response length before subtracting header Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 350/602] wifi: mt76: mt7921: " Greg Kroah-Hartman
` (256 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Devin Wittmayer, Felix Fietkau
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Devin Wittmayer <lucid_duck@justthetip.ca>
commit 39afc46c0243d10b7795e6e6cf4ae91f41732120 upstream.
PKT_TYPE_TXRX_NOTIFY is an mmio-only event, but mt7615_rx_check() and
mt7615_queue_rx_skb() dispatch it to mt7615_mac_tx_free() on every bus.
mt7615_mac_tx_free() cleans the DMA tx queues with
mt76_queue_tx_cleanup(), which calls queue_ops->tx_cleanup(). Only the
mmio queue ops implement that callback; on the mt7663 USB and SDIO
buses it is NULL, so a TXRX_NOTIFY there calls a NULL pointer in the RX
worker. Same defect as the mt7921 and mt7925 patches in this series.
Drop the event on non-mmio buses via mt76_is_mmio(), as in
commit 5683e1488aa9 ("wifi: mt76: connac: do not check WED status for
non-mmio devices").
Fixes: eb99cc95c3b6 ("mt76: mt7615: introduce mt7663u support")
Cc: stable@vger.kernel.org
Signed-off-by: Devin Wittmayer <lucid_duck@justthetip.ca>
Link: https://patch.msgid.link/20260627191336.20223-4-lucid_duck@justthetip.ca
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/wireless/mediatek/mt76/mt7615/mac.c | 6 ++++++
1 file changed, 6 insertions(+)
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c
@@ -1612,6 +1612,8 @@ bool mt7615_rx_check(struct mt76_dev *md
switch (type) {
case PKT_TYPE_TXRX_NOTIFY:
+ if (!mt76_is_mmio(mdev))
+ return false;
mt7615_mac_tx_free(dev, data, len);
return false;
case PKT_TYPE_TXS:
@@ -1645,6 +1647,10 @@ void mt7615_queue_rx_skb(struct mt76_dev
dev_kfree_skb(skb);
break;
case PKT_TYPE_TXRX_NOTIFY:
+ if (!mt76_is_mmio(mdev)) {
+ dev_kfree_skb(skb);
+ break;
+ }
mt7615_mac_tx_free(dev, skb->data, skb->len);
dev_kfree_skb(skb);
break;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 350/602] wifi: mt76: mt7921: drop TXRX_NOTIFY on non-mmio buses
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (348 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 349/602] wifi: mt76: mt7615: drop TXRX_NOTIFY on non-mmio buses Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 351/602] wifi: mt76: mt7925: " Greg Kroah-Hartman
` (255 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Devin Wittmayer, Felix Fietkau
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Devin Wittmayer <lucid_duck@justthetip.ca>
commit da4082e91acabc1498611ed8ccc53f0610baefc6 upstream.
PKT_TYPE_TXRX_NOTIFY is an mmio-only event, but mt7921_rx_check() and
mt7921_queue_rx_skb() dispatch it to mt7921_mac_tx_free() on every bus.
mt7921_mac_tx_free() cleans the DMA tx queues with
mt76_queue_tx_cleanup(), which calls queue_ops->tx_cleanup(). Only the
mmio queue ops implement that callback; on USB and SDIO it is NULL, so
a TXRX_NOTIFY there calls a NULL pointer in the RX worker:
BUG: kernel NULL pointer dereference, address: 0000000000000000
RIP: 0010:0x0
Call Trace:
mt7921_mac_tx_free+0x64/0x310 [mt7921_common]
mt7921_rx_check+0x5f/0xf0 [mt7921_common]
mt76u_rx_worker+0x1b9/0x620 [mt76_usb]
Drop the event on non-mmio buses via mt76_is_mmio(), as in
commit 5683e1488aa9 ("wifi: mt76: connac: do not check WED status for
non-mmio devices").
Fixes: 48fab5bbef40 ("mt76: mt7921: introduce mt7921s support")
Cc: stable@vger.kernel.org
Signed-off-by: Devin Wittmayer <lucid_duck@justthetip.ca>
Link: https://patch.msgid.link/20260627191336.20223-2-lucid_duck@justthetip.ca
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mac.c
@@ -580,8 +580,9 @@ bool mt7921_rx_check(struct mt76_dev *md
switch (type) {
case PKT_TYPE_TXRX_NOTIFY:
- /* PKT_TYPE_TXRX_NOTIFY can be received only by mmio devices */
- mt7921_mac_tx_free(dev, data, len); /* mmio */
+ if (!mt76_is_mmio(mdev))
+ return false;
+ mt7921_mac_tx_free(dev, data, len);
return false;
case PKT_TYPE_TXS:
for (rxd += 2; rxd + 8 <= end; rxd += 8)
@@ -610,7 +611,10 @@ void mt7921_queue_rx_skb(struct mt76_dev
switch (type) {
case PKT_TYPE_TXRX_NOTIFY:
- /* PKT_TYPE_TXRX_NOTIFY can be received only by mmio devices */
+ if (!mt76_is_mmio(mdev)) {
+ napi_consume_skb(skb, 1);
+ break;
+ }
mt7921_mac_tx_free(dev, skb->data, skb->len);
napi_consume_skb(skb, 1);
break;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 351/602] wifi: mt76: mt7925: drop TXRX_NOTIFY on non-mmio buses
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (349 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 350/602] wifi: mt76: mt7921: " Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 352/602] wifi: brcmfmac: make release_scratchbuffers idempotent Greg Kroah-Hartman
` (254 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Devin Wittmayer, Felix Fietkau
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Devin Wittmayer <lucid_duck@justthetip.ca>
commit feeff151c83e7f0ffcdedcad5343852d23d1f6e1 upstream.
PKT_TYPE_TXRX_NOTIFY is an mmio-only event, but mt7925_rx_check() and
mt7925_queue_rx_skb() dispatch it to mt7925_mac_tx_free() on every bus.
mt7925_mac_tx_free() cleans the DMA tx queues with
mt76_queue_tx_cleanup(), which calls queue_ops->tx_cleanup(). Only the
mmio queue ops implement that callback; on USB it is NULL, so a
TXRX_NOTIFY there calls a NULL pointer in the RX worker:
BUG: kernel NULL pointer dereference, address: 0000000000000000
RIP: 0010:0x0
Call Trace:
mt7925_mac_tx_free+0x58/0x350 [mt7925_common]
mt7925_rx_check+0xe2/0x130 [mt7925_common]
mt76u_rx_worker+0x1b9/0x620 [mt76_usb]
Drop the event on non-mmio buses via mt76_is_mmio(), as in
commit 5683e1488aa9 ("wifi: mt76: connac: do not check WED status for
non-mmio devices").
Fixes: c948b5da6bbe ("wifi: mt76: mt7925: add Mediatek Wi-Fi7 driver for mt7925 chips")
Cc: stable@vger.kernel.org
Signed-off-by: Devin Wittmayer <lucid_duck@justthetip.ca>
Link: https://patch.msgid.link/20260627191336.20223-3-lucid_duck@justthetip.ca
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/wireless/mediatek/mt76/mt7925/mac.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mac.c
@@ -1204,8 +1204,9 @@ bool mt7925_rx_check(struct mt76_dev *md
switch (type) {
case PKT_TYPE_TXRX_NOTIFY:
- /* PKT_TYPE_TXRX_NOTIFY can be received only by mmio devices */
- mt7925_mac_tx_free(dev, data, len); /* mmio */
+ if (!mt76_is_mmio(mdev))
+ return false;
+ mt7925_mac_tx_free(dev, data, len);
return false;
case PKT_TYPE_TXS:
for (rxd += 4; rxd + 12 <= end; rxd += 12)
@@ -1241,7 +1242,10 @@ void mt7925_queue_rx_skb(struct mt76_dev
switch (type) {
case PKT_TYPE_TXRX_NOTIFY:
- /* PKT_TYPE_TXRX_NOTIFY can be received only by mmio devices */
+ if (!mt76_is_mmio(mdev)) {
+ napi_consume_skb(skb, 1);
+ break;
+ }
mt7925_mac_tx_free(dev, skb->data, skb->len);
napi_consume_skb(skb, 1);
break;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 352/602] wifi: brcmfmac: make release_scratchbuffers idempotent
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (350 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 351/602] wifi: mt76: mt7925: " Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 353/602] staging: rtl8723bs: fix OOB reads in rtw_get_wps_ie() Greg Kroah-Hartman
` (253 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Fan Wu, Arend van Spriel,
Johannes Berg
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fan Wu <fanwu01@zju.edu.cn>
commit 538c51e9d124cf656f2dd0c0394a8545efc7102d upstream.
brcmf_pcie_release_scratchbuffers() frees the shared.scratch and
shared.ringupd DMA buffers with dma_free_coherent() but does not clear
the pointers afterwards, unlike the sibling release_ringbuffers() which
NULLs commonrings/flowrings/idxbuf on release.
Both the bus_reset .reset callback (brcmf_pcie_reset) and
brcmf_pcie_remove() call release_scratchbuffers. When reset teardown
has run before removal, remove's own teardown would call
dma_free_coherent() a second time on the already-freed DMA allocation.
NULL the pointers after free, matching release_ringbuffers(), so a later
release observes that the allocation has already been released. This
patch makes repeated sequential release safe; the reset-work lifetime is
handled separately by the following patch.
This issue was found by an in-house static analysis tool.
Fixes: 4684997d9eea ("brcmfmac: reset PCIe bus on a firmware crash")
Cc: stable@vger.kernel.org
Signed-off-by: Fan Wu <fanwu01@zju.edu.cn>
Assisted-by: Codex:gpt-5.6
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Link: https://patch.msgid.link/20260718024353.3147201-2-fanwu01@zju.edu.cn
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -1376,16 +1376,20 @@ fail:
static void
brcmf_pcie_release_scratchbuffers(struct brcmf_pciedev_info *devinfo)
{
- if (devinfo->shared.scratch)
+ if (devinfo->shared.scratch) {
dma_free_coherent(&devinfo->pdev->dev,
BRCMF_DMA_D2H_SCRATCH_BUF_LEN,
devinfo->shared.scratch,
devinfo->shared.scratch_dmahandle);
- if (devinfo->shared.ringupd)
+ devinfo->shared.scratch = NULL;
+ }
+ if (devinfo->shared.ringupd) {
dma_free_coherent(&devinfo->pdev->dev,
BRCMF_DMA_D2H_RINGUPD_BUF_LEN,
devinfo->shared.ringupd,
devinfo->shared.ringupd_dmahandle);
+ devinfo->shared.ringupd = NULL;
+ }
}
static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 353/602] staging: rtl8723bs: fix OOB reads in rtw_get_wps_ie()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (351 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 352/602] wifi: brcmfmac: make release_scratchbuffers idempotent Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 354/602] staging: rtl8723bs: fix inverted HT40 secondary channel offset Greg Kroah-Hartman
` (252 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, stable, Moksh Panicker
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Moksh Panicker <mokshpanicker.7@gmail.com>
commit 0e95ff792ae0aa6fbad9455943e9e1e4062670e9 upstream.
rtw_get_wps_ie() iterates over IE data from network frames without
validating that the IE header and payload fit within the remaining
buffer before reading them. Specifically:
- in_ie[cnt + 1] is read without checking cnt + 1 < in_len
- memcmp(&in_ie[cnt + 2], ...) accesses cnt + 2 without bounds check
- in_ie[cnt + 1] is used as length without verifying payload fits
Add bounds checks at the top of the loop body to break early if fewer
than 2 bytes remain for the IE header, or if the declared payload
extends past the end of the buffer. Also require at least 4 bytes of
payload before comparing the WPS OUI.
Fixes: 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver")
Cc: stable <stable@kernel.org>
Signed-off-by: Moksh Panicker <mokshpanicker.7@gmail.com>
Link: https://patch.msgid.link/20260625202911.26782-1-mokshpanicker.7@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/staging/rtl8723bs/core/rtw_ieee80211.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
--- a/drivers/staging/rtl8723bs/core/rtw_ieee80211.c
+++ b/drivers/staging/rtl8723bs/core/rtw_ieee80211.c
@@ -679,7 +679,14 @@ u8 *rtw_get_wps_ie(u8 *in_ie, uint in_le
while (cnt < in_len) {
eid = in_ie[cnt];
- if ((eid == WLAN_EID_VENDOR_SPECIFIC) && (!memcmp(&in_ie[cnt + 2], wps_oui, 4))) {
+ if (cnt + 2 > in_len)
+ break;
+
+ if (in_ie[cnt + 1] + 2 > in_len - cnt)
+ break;
+
+ if ((eid == WLAN_EID_VENDOR_SPECIFIC) && (in_ie[cnt + 1] >= 4) &&
+ (!memcmp(&in_ie[cnt + 2], wps_oui, 4))) {
wpsie_ptr = &in_ie[cnt];
if (wps_ie)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 354/602] staging: rtl8723bs: fix inverted HT40 secondary channel offset
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (352 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 353/602] staging: rtl8723bs: fix OOB reads in rtw_get_wps_ie() Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 355/602] Bluetooth: hci_sync: Protect UUID list traversal Greg Kroah-Hartman
` (251 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, MinJea Kim
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: MinJea Kim <qndkdrnl@gmail.com>
commit 30d49cba27f8905bc288cef5846963f0004f644c upstream.
rtw_get_chan_type() maps the driver's channel offset to nl80211 channel
types the wrong way around.
In this driver HAL_PRIME_CHNL_OFFSET_LOWER means the primary channel is
the lower 20 MHz half of the 40 MHz pair, i.e. the secondary channel is
above the primary one: rtw_get_center_ch() computes the center channel
as "channel + 2" for OFFSET_LOWER, and bwmode_update_check() sets
OFFSET_LOWER when the AP's HT operation IE announces SCA (secondary
channel above). In nl80211 terms that is NL80211_CHAN_HT40PLUS, not
HT40MINUS.
Because of the inversion, cfg80211_rtw_get_channel() reports an HT40+
association as HT40-. For an HT40+ AP on a low channel (e.g. channel 3)
the resulting chandef spans below the 2.4 GHz band edge and is invalid,
so the regulatory core tears the connection down 60 seconds
(REG_ENFORCE_GRACE_MS) after the AP's country IE triggers a regdomain
change: reg_check_chans_work() considers the reported chandef unusable
and calls cfg80211_leave(). The supplicant then reconnects, the country
IE changes the regdomain again, and the cycle repeats, causing a
disconnect/reconnect loop every ~65 seconds for as long as the link is
up.
Observed on a TECLAST X80 Power tablet (RTL8723BS) associated to an
HT40+ AP on channel 3 with a KR country IE; a kprobe trace showed
cfg80211_disconnect() being invoked from reg_check_chans_work(). With
the mapping fixed, "iw dev wlan0 info" reports the correct
"width: 40 MHz, center1: 2432 MHz" and the periodic disconnects stop.
Fixes: 5402cc178c5d ("staging: rtl8723bs: add get_channel cfg80211 implementation")
Cc: stable@vger.kernel.org
Assisted-by: Claude-Code:claude-fable-5 bpftrace
Signed-off-by: MinJea Kim <qndkdrnl@gmail.com>
Link: https://patch.msgid.link/20260714131421.3980-1-qndkdrnl@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
+++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
@@ -1965,7 +1965,7 @@ static u8 rtw_get_chan_type(struct adapt
else
return NL80211_CHAN_NO_HT;
case CHANNEL_WIDTH_40:
- if (mlme_ext->cur_ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
+ if (mlme_ext->cur_ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
return NL80211_CHAN_HT40PLUS;
else
return NL80211_CHAN_HT40MINUS;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 355/602] Bluetooth: hci_sync: Protect UUID list traversal
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (353 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 354/602] staging: rtl8723bs: fix inverted HT40 secondary channel offset Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 356/602] Bluetooth: RFCOMM: Fix session UAF in set_termios Greg Kroah-Hartman
` (250 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Chengfeng Ye, Luiz Augusto von Dentz
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chengfeng Ye <nicoyip.dev@gmail.com>
commit e9027ffbf5a0f3c12ca8900822e884eae9f0821b upstream.
The hci_sync conversion moved class-of-device and EIR generation from an
HCI request built under hdev->lock to asynchronous command sync work.
The worker holds hdev->req_lock, but that lock does not serialize access
to hdev->uuids against add_uuid() and remove_uuid(), which update the
list under hdev->lock.
The following interleaving can therefore occur:
CPU0 (command sync work) CPU1 (management socket)
fetch uuid from the list
list_del(&uuid->list)
kfree(uuid)
read uuid->size
KASAN reports the resulting use-after-free:
BUG: KASAN: slab-use-after-free in eir_create+0xb8f/0xee0
Read of size 1 at addr ffff88810dbd8620 by task kworker/u17:0/87
Workqueue: hci0 hci_cmd_sync_work
Call Trace:
eir_create+0xb8f/0xee0
hci_update_eir_sync+0x1c0/0x330
hci_cmd_sync_work+0x13c/0x290
process_one_work+0x63a/0x1070
worker_thread+0x45b/0xd10
Allocated by task 86:
__kasan_kmalloc+0x8f/0xa0
add_uuid+0x18a/0x4b0
hci_sock_sendmsg+0x1033/0x1ea0
Freed by task 92:
__kasan_slab_free+0x43/0x70
kfree+0x131/0x3c0
remove_uuid+0x25e/0x560
hci_sock_sendmsg+0x1033/0x1ea0
Hold hdev->lock while generating and committing the class-of-device and
EIR snapshots. Release it before sending an HCI command, so controller
waits do not happen under the device lock. This protects all UUID list
walks in these paths and restores the serialization lost in the command
sync conversion.
Fixes: 161510ccf91c ("Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1")
Cc: stable@vger.kernel.org
Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/bluetooth/hci_sync.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -929,12 +929,16 @@ int hci_update_eir_sync(struct hci_dev *
memset(&cp, 0, sizeof(cp));
+ hci_dev_lock(hdev);
eir_create(hdev, cp.data);
- if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
+ if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0) {
+ hci_dev_unlock(hdev);
return 0;
+ }
memcpy(hdev->eir, cp.data, sizeof(cp.data));
+ hci_dev_unlock(hdev);
return __hci_cmd_sync_status(hdev, HCI_OP_WRITE_EIR, sizeof(cp), &cp,
HCI_CMD_TIMEOUT);
@@ -966,6 +970,7 @@ int hci_update_class_sync(struct hci_dev
if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
return 0;
+ hci_dev_lock(hdev);
cod[0] = hdev->minor_class;
cod[1] = hdev->major_class;
cod[2] = get_service_classes(hdev);
@@ -973,8 +978,12 @@ int hci_update_class_sync(struct hci_dev
if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
cod[1] |= 0x20;
- if (memcmp(cod, hdev->dev_class, 3) == 0)
+ if (memcmp(cod, hdev->dev_class, 3) == 0) {
+ hci_dev_unlock(hdev);
return 0;
+ }
+
+ hci_dev_unlock(hdev);
return __hci_cmd_sync_status(hdev, HCI_OP_WRITE_CLASS_OF_DEV,
sizeof(cod), cod, HCI_CMD_TIMEOUT);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 356/602] Bluetooth: RFCOMM: Fix session UAF in set_termios
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (354 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 355/602] Bluetooth: hci_sync: Protect UUID list traversal Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 357/602] exec: fix unsigned loop counter wrap in transfer_args_to_stack() Greg Kroah-Hartman
` (249 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Chengfeng Ye, Luiz Augusto von Dentz
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chengfeng Ye <nicoyip.dev@gmail.com>
commit c783399efc22d035443f1dfbf2a09bf9562aaa5e upstream.
rfcomm_tty_set_termios() tests dlc->session without rfcomm_mutex and
later passes the pointer to rfcomm_send_rpn(). The latter dereferences
both session->initiator and session->sock. Meanwhile, krfcommd can
unlink the DLC and free the session while holding rfcomm_mutex.
The race can proceed as follows:
TTY ioctl task krfcommd
-------------- --------
load dlc->session
enter rfcomm_send_rpn()
lock rfcomm_mutex
clear dlc->session
free session
unlock rfcomm_mutex
read session->initiator
KASAN reported:
BUG: KASAN: slab-use-after-free in rfcomm_send_rpn+0x297/0x2a0
Read of size 4 at addr ffff88810012a850 by task poc/92
Call Trace:
rfcomm_send_rpn+0x297/0x2a0
rfcomm_tty_set_termios+0x50d/0x850
tty_set_termios+0x596/0x950
set_termios+0x46a/0x6e0
tty_mode_ioctl+0x152/0xbd0
tty_ioctl+0x915/0x1240
__x64_sys_ioctl+0x134/0x1c0
Allocated by task 92:
rfcomm_session_add+0x9e/0x2e0
rfcomm_dlc_open+0x8b1/0xe00
rfcomm_dev_activate+0x85/0x1a0
rfcomm_tty_open+0x90/0x280
Freed by task 68:
kfree+0x131/0x3c0
rfcomm_session_del+0x119/0x180
rfcomm_run+0x737/0x4710
Add rfcomm_dlc_send_rpn(), which holds rfcomm_mutex while it verifies
that the DLC is still attached and sends the RPN frame. Have the TTY
path use the helper and drop its unlocked session check. This keeps the
session valid through both the frame construction and socket send.
Fixes: 3a5e903c09ae ("[Bluetooth]: Implement RFCOMM remote port negotiation")
Cc: stable@vger.kernel.org
Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/net/bluetooth/rfcomm.h | 3 +++
net/bluetooth/rfcomm/core.c | 17 +++++++++++++++++
net/bluetooth/rfcomm/tty.c | 7 +++----
3 files changed, 23 insertions(+), 4 deletions(-)
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -229,6 +229,9 @@ int rfcomm_send_rpn(struct rfcomm_sessio
u8 bit_rate, u8 data_bits, u8 stop_bits,
u8 parity, u8 flow_ctrl_settings,
u8 xon_char, u8 xoff_char, u16 param_mask);
+int rfcomm_dlc_send_rpn(struct rfcomm_dlc *d, u8 bit_rate, u8 data_bits,
+ u8 stop_bits, u8 parity, u8 flow_ctrl_settings,
+ u8 xon_char, u8 xoff_char, u16 param_mask);
/* ---- RFCOMM DLCs (channels) ---- */
struct rfcomm_dlc *rfcomm_dlc_alloc(gfp_t prio);
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -1031,6 +1031,23 @@ int rfcomm_send_rpn(struct rfcomm_sessio
return rfcomm_send_frame(s, buf, ptr - buf);
}
+int rfcomm_dlc_send_rpn(struct rfcomm_dlc *d, u8 bit_rate, u8 data_bits,
+ u8 stop_bits, u8 parity, u8 flow_ctrl_settings,
+ u8 xon_char, u8 xoff_char, u16 param_mask)
+{
+ int err = -ENOTCONN;
+
+ rfcomm_lock();
+ if (d->session)
+ err = rfcomm_send_rpn(d->session, 1, d->dlci, bit_rate,
+ data_bits, stop_bits, parity,
+ flow_ctrl_settings, xon_char, xoff_char,
+ param_mask);
+ rfcomm_unlock();
+
+ return err;
+}
+
static int rfcomm_send_rls(struct rfcomm_session *s, int cr, u8 dlci, u8 status)
{
struct rfcomm_hdr *hdr;
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -861,7 +861,7 @@ static void rfcomm_tty_set_termios(struc
BT_DBG("tty %p termios %p", tty, old);
- if (!dev || !dev->dlc || !dev->dlc->session)
+ if (!dev || !dev->dlc)
return;
/* Handle turning off CRTSCTS */
@@ -982,9 +982,8 @@ static void rfcomm_tty_set_termios(struc
}
if (changes)
- rfcomm_send_rpn(dev->dlc->session, 1, dev->dlc->dlci, baud,
- data_bits, stop_bits, parity,
- RFCOMM_RPN_FLOW_NONE, x_on, x_off, changes);
+ rfcomm_dlc_send_rpn(dev->dlc, baud, data_bits, stop_bits, parity,
+ RFCOMM_RPN_FLOW_NONE, x_on, x_off, changes);
}
static void rfcomm_tty_throttle(struct tty_struct *tty)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 357/602] exec: fix unsigned loop counter wrap in transfer_args_to_stack()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (355 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 356/602] Bluetooth: RFCOMM: Fix session UAF in set_termios Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 358/602] binfmt_misc: set have_execfd only once the interpreter is opened Greg Kroah-Hartman
` (248 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Hildenbrand (Arm),
Christian Brauner (Amutable)
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Brauner <brauner@kernel.org>
commit 16cc4f5c1c4b9e45eca7f7deefa5410a292db599 upstream.
The stop value is derived from bprm->p >> PAGE_SHIFT. The index variable
is an unsigned long. If bprm->p drops below PAGE_SIZE and stop becomes
zero the loop condition index >= stop is always true.
After the index == 0 iteration the decrement wraps to ULONG_MAX and
bprm->page[ULONG_MAX] reads sizeof(void *) bytes in front of the array.
The pointer has wrapped to -1. That garbage pointer is then passed to
kmap_local_page() and PAGE_SIZE bytes are copied from wherever that
lands into the stack of the process being created. And the loop doesn't
terminate either...
Getting there only requires bprm->p < PAGE_SIZE. On !MMU
bprm_set_stack_limit() and bprm_hit_stack_limit() are empty. So the only
constraint on how far bprm->p is pushed down is valid_arg_len(), i.e.
that each individual string still fits in what is left.
bprm->p starts at PAGE_SIZE * MAX_ARG_PAGES - sizeof(void *) so a
single argument or environment string of a little over 31 pages leaves
it in the first page:
Oops - load access fault [#1]
CPU: 0 UID: 0 PID: 1 Comm: victim Not tainted 7.2.0-rc4 #1
epc : __memcpy+0xd4/0xf8
ra : transfer_args_to_stack+0xaa/0xae
s4 : ffffffffffffffff s2 : 0000000000000000
a1 : ffffffdc98000000 a2 : 0000000000001000
status: 0000000a00001880 badaddr: ffffffdc98000000 cause: 0000000000000005
[<801a5324>] __memcpy+0xd4/0xf8
[<800d5f6a>] load_flat_binary+0x43a/0x65e
[<800a2de4>] bprm_execve+0x1d4/0x316
[<800a351a>] do_execveat_common+0x12e/0x138
[<800a3d44>] __riscv_sys_execve+0x38/0x4e
Kernel panic - not syncing: Fatal exception in interrupt
This is an arcane bug but we should still fix it.
Count down from MAX_ARG_PAGES so the loop ends when index reaches stop,
stop == 0 included. The iterations performed are unchanged for every
other value of stop.
Only CONFIG_MMU=n builds are affected, transfer_args_to_stack() is used
by binfmt_flat and binfmt_elf_fdpic on nommu only.
The loop predates git history. commit 7e7ec6a93434
("elf_fdpic_transfer_args_to_stack(): make it generic") only moved it
from binfmt_elf_fdpic.c into fs/exec.c and narrowed the copy to the used
part of the first page. The condition and the decrement are unchanged
from 2.6.12-rc2.
Link: https://patch.msgid.link/20260721-hochachtung-staumauer-pigmente-15d71f7d7d04@brauner
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Reviewed-by: David Hildenbrand (Arm) <david@kernel.org>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/exec.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -856,7 +856,7 @@ int transfer_args_to_stack(struct linux_
stop = bprm->p >> PAGE_SHIFT;
sp = *sp_location;
- for (index = MAX_ARG_PAGES - 1; index >= stop; index--) {
+ for (index = MAX_ARG_PAGES; index-- > stop; ) {
unsigned int offset = index == stop ? bprm->p & ~PAGE_MASK : 0;
char *src = kmap_local_page(bprm->page[index]) + offset;
sp -= PAGE_SIZE - offset;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 358/602] binfmt_misc: set have_execfd only once the interpreter is opened
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (356 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 357/602] exec: fix unsigned loop counter wrap in transfer_args_to_stack() Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 359/602] platform/loongarch: laptop: Explicitly reset bl_powered state when suspend Greg Kroah-Hartman
` (247 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Christian Brauner (Amutable)
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Brauner <brauner@kernel.org>
commit bbf5f639918dc011aaf60aab8480218758ee68c5 upstream.
load_misc_binary() raises bprm->have_execfd as soon as it sees the 'O'
(or 'C') flag. This happens well before it opens the interpreter. If
that open fails the flag stays set on the bprm. binfmt_misc is at the
head of the format list so an interpreter open failure that returns
-ENOEXEC lets the search fall through to a later format. This means it
runs the matched binary directly having never staged an interpreter. So
bprm->executable is NULL while have_execfd falsely claims a descriptor
is present.
Consequently, begin_new_exec() dereferences the missing executable:
would_dump(bprm, bprm->executable);
and NULL derefs. Had it not, the hand-off later in the same function
would have failed anyway. FD_ADD(0, bprm->executable) rejects a NULL
file with -ENOMEM. Both sites are past the point of no return so the
exec cannot be unwound either way.
This can be reached by unprivileged users as binfmt_misc can be mounted
in user namespaces. So a user can register an 'O' entry whose
interpreter lives on a FUSE mount, have the FUSE server fail the open
with -ENOEXEC and execute a native ELF file that matches the entry.
have_execfd only means anything alongside the executable it describes
which is not set until the interpreter has been opened and staged.
So lets raise it there, next to execfd_creds, which is already set at
that point. An open failure now leaves it clear, so the fallback format
derives credentials from the binary and emits no AT_EXECFD, as it would
for any native exec. The argv rewrite load_misc_binary() performs before
the open is still not undone. This means the binary sees the interpreter
path in argv[0] and its own path in argv[1] but that predates this
change and only became observable once the exec stopped faulting.
Link: https://patch.msgid.link/20260720-beglichen-kognitiv-organismus-5e1e55326c56@brauner
Fixes: bc2bf338d54b ("exec: Remove recursion from search_binary_handler")
Cc: stable@vger.kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/binfmt_misc.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -227,9 +227,6 @@ static int load_misc_binary(struct linux
goto ret;
}
- if (fmt->flags & MISC_FMT_OPEN_BINARY)
- bprm->have_execfd = 1;
-
/* make argv[1] be the path to the binary */
retval = copy_string_kernel(bprm->interp, bprm);
if (retval < 0)
@@ -259,6 +256,8 @@ static int load_misc_binary(struct linux
goto ret;
bprm->interpreter = interp_file;
+ if (fmt->flags & MISC_FMT_OPEN_BINARY)
+ bprm->have_execfd = 1;
if (fmt->flags & MISC_FMT_CREDENTIALS)
bprm->execfd_creds = 1;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 359/602] platform/loongarch: laptop: Explicitly reset bl_powered state when suspend
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (357 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 358/602] binfmt_misc: set have_execfd only once the interpreter is opened Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 360/602] rust: allow `clippy::unwrap_or_default` globally Greg Kroah-Hartman
` (246 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yao Zi, Xi Ruoyao, Zixing Liu,
Huacai Chen
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zixing Liu <liushuyu@aosc.io>
commit 91a70492c03040d51b36f595530d6491d5d6c541 upstream.
On EAECIS NL60R with EC firmware version 1.11, resuming from S3 has a
very high chance (>90%) of causing the EC to lose the previous backlight
power state. When this happens, the laptop resumes normally from S3, but
the backlight remains off (when shining on the screen with a flash light,
we can see the screen contents are updating normally).
Since there is no generic way to query the EC's backlight state on
Loongson laptop platforms, assume the worst-case scenario and restart
the backlight power inside the kernel each time the system resumes.
Cc: stable@vger.kernel.org
Fixes: 53c762b47f72 ("platform/loongarch: laptop: Add backlight power control support")
Tested-by: Yao Zi <me@ziyao.cc>
Tested-by: Xi Ruoyao <xry111@xry111.site>
Signed-off-by: Zixing Liu <liushuyu@aosc.io>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/platform/loongarch/loongson-laptop.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/platform/loongarch/loongson-laptop.c
+++ b/drivers/platform/loongarch/loongson-laptop.c
@@ -189,6 +189,7 @@ static int __init setup_acpi_notify(stru
static int loongson_hotkey_suspend(struct device *dev)
{
+ bl_powered = false;
return 0;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 360/602] rust: allow `clippy::unwrap_or_default` globally
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (358 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 359/602] platform/loongarch: laptop: Explicitly reset bl_powered state when suspend Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 361/602] objtool/rust: add one more `noreturn` Rust function for Rust 1.99.0 Greg Kroah-Hartman
` (245 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Miguel Ojeda, Alexandre Courbot
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexandre Courbot <acourbot@nvidia.com>
commit 4688cf884b3abcd12498e03b625d1916bf49a1e4 upstream.
Starting with rustc 1.88, the `clippy::unwrap_or_default` lint triggers
on `rust/kernel/soc.rs` if `CONFIG_CC_OPTIMIZE_FOR_SIZE=y`:
warning: use of `unwrap_or` to construct default value
--> ../rust/kernel/soc.rs:66:10
|
66 | .unwrap_or(core::ptr::null())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
This is a clippy bug [1]: the lint decides whether an expression is
equivalent to `Default::default()` by inspecting the optimized MIR of
`<*const T as Default>::default` exported by `core`, so its outcome
depends on the optimization level `core` was built with. Moreover, its
suggestion ignores our MSRV of 1.85 (`Default` for `*const T` is only
stable since Rust 1.88), so we could not apply it anyway.
Disable the lint globally rather than working around this single
occurrence; it can be re-enabled conditionally using `rustc-min-version`
once clippy is fixed.
Link: https://github.com/rust-lang/rust-clippy/issues/17379 [1]
Suggested-by: Miguel Ojeda <ojeda@kernel.org>
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
Cc: stable@vger.kernel.org # Needed in 6.12.y and later (Rust is pinned in older LTSs).
Link: https://patch.msgid.link/20260708-soc_unwrap_or-v2-1-007ed724cc7b@nvidia.com
[ Moved to non-versioned group. - Miguel ]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
Makefile | 5 +++++
1 file changed, 5 insertions(+)
--- a/Makefile
+++ b/Makefile
@@ -443,6 +443,10 @@ KBUILD_USERLDFLAGS := $(USERLDFLAGS)
# These flags apply to all Rust code in the tree, including the kernel and
# host programs.
+#
+# `-Aclippy::unwrap_or_default`: the lint is buggy [1] and ignores our
+# MSRV. It can trigger depending on the optimization level.
+# [1] https://github.com/rust-lang/rust-clippy/issues/17379
export rust_common_flags := --edition=2021 \
-Zbinary_dep_depinfo=y \
-Astable_features \
@@ -464,6 +468,7 @@ export rust_common_flags := --edition=20
-Aclippy::uninlined_format_args \
-Wclippy::unnecessary_safety_comment \
-Wclippy::unnecessary_safety_doc \
+ -Aclippy::unwrap_or_default \
-Wrustdoc::missing_crate_level_docs \
-Wrustdoc::unescaped_backticks
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 361/602] objtool/rust: add one more `noreturn` Rust function for Rust 1.99.0
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (359 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 360/602] rust: allow `clippy::unwrap_or_default` globally Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 362/602] LoongArch: Fix oops during single-step debugging Greg Kroah-Hartman
` (244 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Josh Poimboeuf, Peter Zijlstra,
Petr Pavlu, Alice Ryhl, Miguel Ojeda
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miguel Ojeda <ojeda@kernel.org>
commit 5a81c35c3b18cd59ded56171a6a9f643b92a6759 upstream.
Starting with Rust 1.99.0 (expected 2026-10-01), under
`CONFIG_RUST_DEBUG_ASSERTIONS=y`, `objtool` may report:
rust/kernel.o: warning: objtool: _R..._6kernel12module_param9set_paramaEB4_()
falls through to next function _R..._6kernel12module_param9set_paramhEB4_()
(and many others) due to calls to the `noreturn` symbol [1]:
core::panicking::panic_null_reference_constructed
Thus add the mangled one to the list so that `objtool` knows it is
actually `noreturn`.
See commit 56d680dd23c3 ("objtool/rust: list `noreturn` Rust functions")
for more details.
Cc: stable@vger.kernel.org # Needed in 6.12.y and later (Rust is pinned in older LTSs).
Cc: Josh Poimboeuf <jpoimboe@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Petr Pavlu <petr.pavlu@suse.com>
Link: https://github.com/rust-lang/rust/pull/158796 [1]
Reported-by: Alice Ryhl <aliceryhl@google.com>
Closes: https://lore.kernel.org/rust-for-linux/alEBInX9gD1M5NAr@google.com/
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Tested-by: Alice Ryhl <aliceryhl@google.com>
Link: https://patch.msgid.link/20260710173252.191781-1-ojeda@kernel.org
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
tools/objtool/check.c | 1 +
1 file changed, 1 insertion(+)
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -220,6 +220,7 @@ static bool is_rust_noreturn(const struc
str_ends_with(func->name, "_4core9panicking18panic_nounwind_fmt") ||
str_ends_with(func->name, "_4core9panicking19assert_failed_inner") ||
str_ends_with(func->name, "_4core9panicking30panic_null_pointer_dereference") ||
+ str_ends_with(func->name, "_4core9panicking32panic_null_reference_constructed") ||
str_ends_with(func->name, "_4core9panicking36panic_misaligned_pointer_dereference") ||
str_ends_with(func->name, "_7___rustc17rust_begin_unwind") ||
strstr(func->name, "_4core9panicking13assert_failed") ||
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 362/602] LoongArch: Fix oops during single-step debugging
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (360 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 361/602] objtool/rust: add one more `noreturn` Rust function for Rust 1.99.0 Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 363/602] LoongArch: Move jump_label_init() before parse_early_param() Greg Kroah-Hartman
` (243 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Haoran Jiang, Huacai Chen
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haoran Jiang <jianghaoran@kylinos.cn>
commit 73555fdab5e1e4f24ca000c41a616b34edf4b55d upstream.
When entering KDB via a breakpoint and then performing single-step
debugging, an oops is triggered. Now during single-step debugging,
kdb_local() expects the reason to be KDB_REASON_SSTEP, but it is
actually KDB_REASON_OOPS. In kdb_stub(), when determining the reason,
the ex_vector for single-step should be 0, as already implemented on
other architectures such as arm64 and riscv.
Before the patch:
[112]kdb> ss
Entering kdb (current=0x900020009f520000, pid 10661) on
processor 112 Oops: (null)
due to oops @ 0x90000000005b57a4
Cc: stable@vger.kernel.org
Signed-off-by: Haoran Jiang <jianghaoran@kylinos.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/loongarch/kernel/kgdb.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/arch/loongarch/kernel/kgdb.c
+++ b/arch/loongarch/kernel/kgdb.c
@@ -252,7 +252,8 @@ static int kgdb_loongarch_notify(struct
if (atomic_read(&kgdb_active) != -1)
kgdb_nmicallback(smp_processor_id(), regs);
- if (kgdb_handle_exception(args->trapnr, args->signr, cmd, regs))
+ if (kgdb_handle_exception(regs->csr_era == stepped_address ? 0 : args->trapnr,
+ args->signr, cmd, regs))
return NOTIFY_DONE;
if (atomic_read(&kgdb_setting_breakpoint))
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 363/602] LoongArch: Move jump_label_init() before parse_early_param()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (361 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 362/602] LoongArch: Fix oops during single-step debugging Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 364/602] LoongArch: Retrieve CPU package ID from PPTT when available Greg Kroah-Hartman
` (242 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Kanglong Wang, Huacai Chen
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kanglong Wang <wangkanglong@loongson.cn>
commit ea68d444a658783234a06f05414e41cf93a18fb2 upstream.
When enabling both CONFIG_MEM_ALLOC_PROFILING=y and
CONFIG_MEM_ALLOC_PROFILING_ENABLED_BY_DEFAULT=y, then diabling memory
profiling by adding the boot parameter 'sysctl.vm.mem_profiling=0' will
cause the kernel failed to boot.
After analysis, this is because jump_label_init() must be called before
parse_early_param(), the early param handlers may modify static keys by
static_branch_enable/disable().
Fix this by moving jump_label_init() to before parse_early_param(). The
solution is similar to other architectures.
Cc: <stable@vger.kernel.org>
Signed-off-by: Kanglong Wang <wangkanglong@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/loongarch/kernel/setup.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
--- a/arch/loongarch/kernel/setup.c
+++ b/arch/loongarch/kernel/setup.c
@@ -610,6 +610,7 @@ void __init setup_arch(char **cmdline_p)
memblock_init();
pagetable_init();
bootcmdline_init(cmdline_p);
+ jump_label_init(); /* Initialise the static keys for early params */
parse_early_param();
reserve_initrd_mem();
@@ -617,8 +618,6 @@ void __init setup_arch(char **cmdline_p)
arch_mem_init(cmdline_p);
resource_init();
- jump_label_init(); /* Initialise the static keys for paravirtualization */
-
#ifdef CONFIG_SMP
plat_smp_setup();
prefill_possible_map();
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 364/602] LoongArch: Retrieve CPU package ID from PPTT when available
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (362 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 363/602] LoongArch: Move jump_label_init() before parse_early_param() Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 365/602] cdrom: fix stack out-of-bounds read in CDROMVOLCTRL Greg Kroah-Hartman
` (241 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Mingcong Bai, Xi Ruoyao, Rong Bao,
Huacai Chen
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rong Bao <rong.bao@csmantle.top>
commit 4e8f58620f6717f72f3d88a2c8f25c0c656d0ba7 upstream.
Currently, the LoongArch CPU topology initialization code calculates
each core's package ID by dividing its physical ID by loongson_sysconf.
cores_per_package. This relies on the assumption that cores_per_package
counts in the same domain as physical IDs.
On Loongson-3B6000 (XB612B0V_1.2), cores_per_package matches the visible
core count -- 24 in this case. However, the physical IDs range from 0 to
31 in a noncontinuous fashion:
$ cat /proc/cpuinfo | grep -i -F 'global_id'
global_id : 0
global_id : 1
global_id : 4
global_id : 5
global_id : 6
global_id : 7
global_id : 8
global_id : 9
global_id : 10
global_id : 11
global_id : 14
global_id : 15
global_id : 16
global_id : 17
global_id : 20
global_id : 21
global_id : 22
global_id : 23
global_id : 26
global_id : 27
global_id : 28
global_id : 29
global_id : 30
global_id : 31
Retrieve the exact package ID from ACPI PPTT when available, in the same
style as retrieving the core ID and thread ID in parse_acpi_topology().
Use this information in loongson_init_secondary() when the PPTT readout
is successful. The original division logic is kept as a fallback.
Meanwhile, since some existing code paths like loongson3_cpufreq expect
a continuous integer sequence of package IDs in [0, MAX_PACKAGES) when
retrieving from cpu_data[], here we also canonicalize the package ID to
be filled in parse_acpi_topology() to meet such an expectation.
Cc: stable@vger.kernel.org
Tested-by: Mingcong Bai <jeffbai@aosc.io>
Co-developed-by: Xi Ruoyao <xry111@xry111.site>
Signed-off-by: Xi Ruoyao <xry111@xry111.site>
Signed-off-by: Rong Bao <rong.bao@csmantle.top>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/loongarch/kernel/acpi.c | 27 ++++++++++++++++++++++++++-
arch/loongarch/kernel/smp.c | 4 ++--
2 files changed, 28 insertions(+), 3 deletions(-)
--- a/arch/loongarch/kernel/acpi.c
+++ b/arch/loongarch/kernel/acpi.c
@@ -200,10 +200,12 @@ static void __init acpi_process_madt(voi
}
int pptt_enabled;
+static int acpi_nr_packages;
+static int acpi_package_ids[MAX_PACKAGES];
int __init parse_acpi_topology(void)
{
- int cpu, topology_id;
+ int i, cpu, topology_id;
for_each_possible_cpu(cpu) {
topology_id = find_acpi_cpu_topology(cpu, 0);
@@ -221,6 +223,29 @@ int __init parse_acpi_topology(void)
cpu_data[cpu].core = topology_id;
}
+
+ topology_id = find_acpi_cpu_topology_package(cpu);
+ if (topology_id < 0) {
+ pr_warn("Invalid BIOS PPTT\n");
+ return -ENOENT;
+ }
+
+ for (i = 0; i < acpi_nr_packages; i++)
+ if (acpi_package_ids[i] == topology_id)
+ break;
+
+ if (i == acpi_nr_packages)
+ acpi_package_ids[acpi_nr_packages++] = topology_id;
+
+ cpu_data[cpu].package = topology_id;
+ }
+
+ for_each_possible_cpu(cpu) {
+ for (i = 0; i < acpi_nr_packages; i++)
+ if (cpu_data[cpu].package == acpi_package_ids[i]) {
+ cpu_data[cpu].package = i; /* Canonicalize */
+ break;
+ }
}
pptt_enabled = 1;
--- a/arch/loongarch/kernel/smp.c
+++ b/arch/loongarch/kernel/smp.c
@@ -377,10 +377,10 @@ void loongson_init_secondary(void)
numa_add_cpu(cpu);
#endif
per_cpu(cpu_state, cpu) = CPU_ONLINE;
- cpu_data[cpu].package =
- cpu_logical_map(cpu) / loongson_sysconf.cores_per_package;
cpu_data[cpu].core = pptt_enabled ? cpu_data[cpu].core :
cpu_logical_map(cpu) % loongson_sysconf.cores_per_package;
+ cpu_data[cpu].package = pptt_enabled ? cpu_data[cpu].package :
+ cpu_logical_map(cpu) / loongson_sysconf.cores_per_package;
cpu_data[cpu].global_id = cpu_logical_map(cpu);
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 365/602] cdrom: fix stack out-of-bounds read in CDROMVOLCTRL
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (363 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 364/602] LoongArch: Retrieve CPU package ID from PPTT when available Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 366/602] firmware: stratix10-svc: fix memory leaks and list corruption bugs Greg Kroah-Hartman
` (240 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Xu Rao, Phillip Potter, Jens Axboe
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xu Rao <raoxu@uniontech.com>
commit b27e195d4db8dea263050bdbeb11881b2999c9c6 upstream.
mmc_ioctl_cdrom_volume() first reads the audio control mode page into a
32-byte stack buffer with cgc->buflen set to 24. If the device reports a
block descriptor, the function increases cgc->buflen to include that
descriptor and reads the page again.
For CDROMVOLCTRL, the function then builds a MODE SELECT parameter list
by moving cgc->buffer forward by offset - 8 bytes. This drops the block
descriptor from the outgoing payload and leaves a new 8-byte mode
parameter header in front of the audio control page. However, cgc->buflen
is left unchanged.
With a standard 8-byte block descriptor, cgc->buffer points at buffer + 8
but cgc->buflen remains 32. cdrom_mode_select() therefore asks the low
level packet path to write 32 bytes from that adjusted pointer, reading 8
bytes past the end of the 32-byte stack buffer.
This is not hit by CDROMVOLREAD, and CDROMVOLCTRL only triggers it on
drives that return a non-zero block descriptor length, which helps explain
why it has gone unnoticed. The overread is also sent to the device as
extra MODE SELECT payload, so it may not produce an obvious local failure.
Reduce cgc->buflen by the same amount as the buffer pointer adjustment so
the MODE SELECT transfer covers only the intended parameter list.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Xu Rao <raoxu@uniontech.com>
Signed-off-by: Phillip Potter <phil@philpotter.co.uk>
Link: https://patch.msgid.link/20260720194421.1497-2-phil@philpotter.co.uk
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/cdrom/cdrom.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -3191,6 +3191,7 @@ static noinline int mmc_ioctl_cdrom_volu
/* set volume */
cgc->buffer = buffer + offset - 8;
+ cgc->buflen -= offset - 8;
memset(cgc->buffer, 0, 8);
return cdrom_mode_select(cdi, cgc);
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 366/602] firmware: stratix10-svc: fix memory leaks and list corruption bugs
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (364 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 365/602] cdrom: fix stack out-of-bounds read in CDROMVOLCTRL Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 367/602] x86/boot/compressed: Disable jump tables Greg Kroah-Hartman
` (239 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Tze Yee Ng, Dinh Nguyen
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tze Yee Ng <tze.yee.ng@altera.com>
commit 9119ceb76e987c2ec2b549ea100e3268ce3a1c7c upstream.
Fix a memory leak when gen_pool_alloc() fails by freeing pmem on the error
path. Switch pmem allocation from devm_kzalloc() to kzalloc() with
explicit kfree() in the free path to match its list-managed lifetime.
Remove the erroneous list_del(&svc_data_mem) which corrupted the list head
on failed lookups.
Fixes: 7ca5ce896524 ("firmware: add Intel Stratix10 service layer driver")
Cc: stable@vger.kernel.org # 5.0+
Signed-off-by: Tze Yee Ng <tze.yee.ng@altera.com>
Signed-off-by: Dinh Nguyen <dinguyen@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/firmware/stratix10-svc.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
--- a/drivers/firmware/stratix10-svc.c
+++ b/drivers/firmware/stratix10-svc.c
@@ -1083,14 +1083,16 @@ void *stratix10_svc_allocate_memory(stru
struct gen_pool *genpool = chan->ctrl->genpool;
size_t s = roundup(size, 1 << genpool->min_alloc_order);
- pmem = devm_kzalloc(chan->ctrl->dev, sizeof(*pmem), GFP_KERNEL);
+ pmem = kzalloc_obj(*pmem);
if (!pmem)
return ERR_PTR(-ENOMEM);
guard(mutex)(&svc_mem_lock);
va = gen_pool_alloc(genpool, s);
- if (!va)
+ if (!va) {
+ kfree(pmem);
return ERR_PTR(-ENOMEM);
+ }
memset((void *)va, 0, s);
pa = gen_pool_virt_to_phys(genpool, va);
@@ -1116,6 +1118,7 @@ EXPORT_SYMBOL_GPL(stratix10_svc_allocate
void stratix10_svc_free_memory(struct stratix10_svc_chan *chan, void *kaddr)
{
struct stratix10_svc_data_mem *pmem;
+
guard(mutex)(&svc_mem_lock);
list_for_each_entry(pmem, &svc_data_mem, node)
@@ -1124,10 +1127,9 @@ void stratix10_svc_free_memory(struct st
(unsigned long)kaddr, pmem->size);
pmem->vaddr = NULL;
list_del(&pmem->node);
+ kfree(pmem);
return;
}
-
- list_del(&svc_data_mem);
}
EXPORT_SYMBOL_GPL(stratix10_svc_free_memory);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 367/602] x86/boot/compressed: Disable jump tables
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (365 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 366/602] firmware: stratix10-svc: fix memory leaks and list corruption bugs Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 368/602] comedi: comedi_parport: deal with premature interrupt Greg Kroah-Hartman
` (238 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Nathan Chancellor, Ingo Molnar,
Ard Biesheuvel, Bill Wendling, Justin Stitt, Nick Desaulniers,
H. Peter Anvin, Peter Zijlstra
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nathan Chancellor <nathan@kernel.org>
commit 4a9ec5ec9555ad62dc5b81a37ac946025c2ea002 upstream.
After a recent upstream LLVM change to start generating jump and lookup
tables in switch statements in more instances [1], linking the
compressed x86 boot image when CONFIG_KERNEL_ZSTD is enabled fails with:
ld.lld: error: Unexpected run-time relocations (.rela) detected!
Dumping the relocations in misc.o, which is the only file influenced by
CONFIG_KERNEL_ZSTD in the decompressor, shows dynamic relocations to
some string constants, which correspond to the string literals in the
switch statement in handle_zstd_error():
Relocation section '.rela.data.rel.ro' at offset 0x277b0 contains 31 entries:
Offset Info Type Symbol's Value Symbol's Name + Addend
0000000000000000 0000006600000001 R_X86_64_64 0000000000000000 .rodata.str1.1 + 73a
0000000000000008 0000006600000001 R_X86_64_64 0000000000000000 .rodata.str1.1 + 78e
0000000000000010 0000006600000001 R_X86_64_64 0000000000000000 .rodata.str1.1 + 78e
0000000000000018 0000006600000001 R_X86_64_64 0000000000000000 .rodata.str1.1 + 78e
...
This optimization is problematic for the decompressor environment, as it
is built as -fPIE without any explicit absolute references (as described
at the top of misc.c) while not applying any dynamic relocations, hence
the linker assertion. To opt out of this optimization, which is of
little value in this special early boot code, and to mirror the other
x86 startup code in arch/x86/boot/startup, disable jump tables in the
decompressor.
Signed-off-by: Nathan Chancellor <nathan@kernel.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Acked-by: Ard Biesheuvel <ardb@kernel.org>
Cc: Bill Wendling <morbo@google.com>
Cc: Justin Stitt <justinstitt@google.com>
Cc: Nick Desaulniers <ndesaulniers@google.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: stable@vger.kernel.org
Link: https://github.com/llvm/llvm-project/commit/fa02a6ed66b1700c996b49c96c6bc0eb014c9518 [1]
Link: https://patch.msgid.link/20260722-x86-boot-compressed-disable-jt-clang-v2-1-7373d38482fb@kernel.org
Closes: https://github.com/ClangBuiltLinux/linux/issues/2165
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/x86/boot/compressed/Makefile | 1 +
1 file changed, 1 insertion(+)
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -27,6 +27,7 @@ targets := vmlinux vmlinux.bin vmlinux.b
KBUILD_CFLAGS := -m$(BITS) -O2 $(CLANG_FLAGS)
KBUILD_CFLAGS += -std=gnu11
KBUILD_CFLAGS += -fno-strict-aliasing -fPIE
+KBUILD_CFLAGS += -fno-jump-tables
KBUILD_CFLAGS += -Wundef
KBUILD_CFLAGS += -DDISABLE_BRANCH_PROFILING
cflags-$(CONFIG_X86_32) := -march=i386
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 368/602] comedi: comedi_parport: deal with premature interrupt
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (366 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 367/602] x86/boot/compressed: Disable jump tables Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 369/602] uio_hv_generic: Bind to FCopy device by default Greg Kroah-Hartman
` (237 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, syzbot+f24c3d5d316011bacc70, stable,
Ian Abbott
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Abbott <abbotti@mev.co.uk>
commit 17221216ae8ce6a24e8a4e787382e3ebc81b88a8 upstream.
Syzbot reported a general protection fault in
`comedi_get_is_subdevice_running()`, which was called from the interrupt
handler `parport_interrupt()` in the "comedi_parport" driver, but it
does not currently have a C reproducer for the problem. It's
probably due to a premature interrupt for one of two reasons:
1. The driver sets up the interrupt handler before the comedi subdevices
used by the interrupt handler have been allocated, but does not
disable the interrupt in the parallel port's CTRL register first.
2. The driver uses a user-supplied I/O port base address which Syzbot
would have supplied, but it might not be backed by real parallel port
hardware.
Change the initialization order in the driver's comedi "attach" handler
(`parport_attach()`) so that the hardware registers are initialized
before the interrupt handler is requested. This should prevent
premature interrupts occurring for real hardware.
Also add a test to the interrupt handler to ensure the comedi device is
fully attached and return early if it isn't.
Fixes: 241ab6ad7108e ("Staging: comedi: add comedi_parport driver")
Reported-by: syzbot+f24c3d5d316011bacc70@syzkaller.appspotmail.com
Cc: stable <stable@kernel.org>
Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Link: https://patch.msgid.link/20260527125104.96596-1-abbotti@mev.co.uk
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/comedi/drivers/comedi_parport.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
--- a/drivers/comedi/drivers/comedi_parport.c
+++ b/drivers/comedi/drivers/comedi_parport.c
@@ -211,6 +211,13 @@ static irqreturn_t parport_interrupt(int
unsigned int ctrl;
unsigned short val = 0;
+ /*
+ * Check device is fully attached. Device interrupts should have
+ * been disabled, but do this in case of bad hardware.
+ */
+ if (!dev->attached)
+ return IRQ_NONE;
+
ctrl = inb(dev->iobase + PARPORT_CTRL_REG);
if (!(ctrl & PARPORT_CTRL_IRQ_ENA))
return IRQ_NONE;
@@ -231,6 +238,9 @@ static int parport_attach(struct comedi_
if (ret)
return ret;
+ outb(0, dev->iobase + PARPORT_DATA_REG);
+ outb(0, dev->iobase + PARPORT_CTRL_REG);
+
if (it->options[1]) {
ret = request_irq(it->options[1], parport_interrupt, 0,
dev->board_name, dev);
@@ -286,9 +296,6 @@ static int parport_attach(struct comedi_
s->cancel = parport_intr_cancel;
}
- outb(0, dev->iobase + PARPORT_DATA_REG);
- outb(0, dev->iobase + PARPORT_CTRL_REG);
-
return 0;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 369/602] uio_hv_generic: Bind to FCopy device by default
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (367 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 368/602] comedi: comedi_parport: deal with premature interrupt Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 370/602] serial: sc16is7xx: implement gpio get_direction() callback Greg Kroah-Hartman
` (236 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Ben Hutchings, stable
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ben Hutchings <benh@debian.org>
commit 87d3621ccc63b3999d756bb59f0cedd738c28eb3 upstream.
The Hyper-V kernel-mode fcopy driver was removed in 6.10 and the new
fcopy daemon requires this uio driver to function. However, by
default the driver does not bind to any devices, and must be
configured through the sysfs "new_id" file.
Since the FCopy device is now only usable through this driver, add its
ID to the driver's ID table so that the daemon will work "out of the
box".
Signed-off-by: Ben Hutchings <benh@debian.org>
Fixes: ec314f61e4fc ("Drivers: hv: Remove fcopy driver")
Cc: stable <stable@kernel.org>
Link: https://patch.msgid.link/ahQ6xuhSReidmN-3@decadent.org.uk
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/uio/uio_hv_generic.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
--- a/drivers/uio/uio_hv_generic.c
+++ b/drivers/uio/uio_hv_generic.c
@@ -395,9 +395,15 @@ hv_uio_remove(struct hv_device *dev)
vmbus_free_ring(dev->channel);
}
+static const struct hv_vmbus_device_id hv_uio_id_table[] = {
+ { HV_FCOPY_GUID },
+ {}
+};
+MODULE_DEVICE_TABLE(vmbus, hv_uio_id_table);
+
static struct hv_driver hv_uio_drv = {
.name = "uio_hv_generic",
- .id_table = NULL, /* only dynamic id's */
+ .id_table = hv_uio_id_table,
.probe = hv_uio_probe,
.remove = hv_uio_remove,
};
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 370/602] serial: sc16is7xx: implement gpio get_direction() callback
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (368 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 369/602] uio_hv_generic: Bind to FCopy device by default Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 371/602] serial: 8250_mid: Fix NULL function pointer dereference on DNV/ICX-D/SNR platforms Greg Kroah-Hartman
` (235 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, stable, Hugo Villeneuve,
Bartosz Golaszewski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
commit af071d9e07e57cfff239e8d09d2f3b05ebc9c667 upstream.
It's strongly recommended for GPIO drivers to always implement the
.get_direction() callback - even when the direction is tracked in
software. The GPIO core emits a warning when the callback is missing
and a user reads the direction of a line, e.g. via
/sys/kernel/debug/gpio.
Fixes: dfeae619d781 ("serial: sc16is7xx")
Cc: stable <stable@kernel.org>
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Acked-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Link: https://patch.msgid.link/20260716210813.2582826-1-hugo@hugovil.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/tty/serial/sc16is7xx.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -1302,6 +1302,17 @@ static void sc16is7xx_gpio_set(struct gp
val ? BIT(offset) : 0);
}
+static int sc16is7xx_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
+{
+ struct sc16is7xx_port *s = gpiochip_get_data(chip);
+ struct uart_port *port = &s->p[0].port;
+ unsigned int val;
+
+ val = sc16is7xx_port_read(port, SC16IS7XX_IODIR_REG);
+
+ return val & BIT(offset) ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
+}
+
static int sc16is7xx_gpio_direction_input(struct gpio_chip *chip,
unsigned offset)
{
@@ -1379,6 +1390,7 @@ static int sc16is7xx_setup_gpio_chip(str
s->gpio.parent = dev;
s->gpio.label = dev_name(dev);
s->gpio.init_valid_mask = sc16is7xx_gpio_init_valid_mask;
+ s->gpio.get_direction = sc16is7xx_gpio_get_direction;
s->gpio.direction_input = sc16is7xx_gpio_direction_input;
s->gpio.get = sc16is7xx_gpio_get;
s->gpio.direction_output = sc16is7xx_gpio_direction_output;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 371/602] serial: 8250_mid: Fix NULL function pointer dereference on DNV/ICX-D/SNR platforms
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (369 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 370/602] serial: sc16is7xx: implement gpio get_direction() callback Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 372/602] mei: bus: access mei_device under device_lock on cleanup Greg Kroah-Hartman
` (234 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, stable, Andy Shevchenko,
Jiangshan Yi
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiangshan Yi <yijiangshan@kylinos.cn>
commit 7fb13fd7e9a59a37cd911efff83abe19e3ee029d upstream.
Commit b1b4efea05a5 ("serial: 8250_mid: Disable DMA for selected
platforms") replaced the dnv_board setup and exit callbacks with
PTR_IF(false, ...), which evaluates to NULL. However, the three call
sites in mid8250_probe() and mid8250_remove() unconditionally
dereference these function pointers without NULL checks, causing a NULL
pointer dereference (kernel oops) on any Denverton (DNV), Ice Lake Xeon
D (ICX-D/CDF), or Snowridge (SNR) platform.
Fix this by adding the missing NULL checks before calling the setup and
exit callbacks.
Fixes: b1b4efea05a5 ("serial: 8250_mid: Disable DMA for selected platforms")
Cc: stable <stable@kernel.org>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Jiangshan Yi <yijiangshan@kylinos.cn>
Link: https://patch.msgid.link/20260715073546.1875083-1-yijiangshan@kylinos.cn
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/tty/serial/8250/8250_mid.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
--- a/drivers/tty/serial/8250/8250_mid.c
+++ b/drivers/tty/serial/8250/8250_mid.c
@@ -318,9 +318,11 @@ static int mid8250_probe(struct pci_dev
if (!uart.port.membase)
return -ENOMEM;
- ret = mid->board->setup(mid, &uart.port);
- if (ret)
- return ret;
+ if (mid->board->setup) {
+ ret = mid->board->setup(mid, &uart.port);
+ if (ret)
+ return ret;
+ }
ret = mid8250_dma_setup(mid, &uart);
if (ret)
@@ -336,7 +338,8 @@ static int mid8250_probe(struct pci_dev
return 0;
err:
- mid->board->exit(mid);
+ if (mid->board->exit)
+ mid->board->exit(mid);
return ret;
}
@@ -346,7 +349,8 @@ static void mid8250_remove(struct pci_de
serial8250_unregister_port(mid->line);
- mid->board->exit(mid);
+ if (mid->board->exit)
+ mid->board->exit(mid);
}
static const struct mid8250_board pnw_board = {
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 372/602] mei: bus: access mei_device under device_lock on cleanup
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (370 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 371/602] serial: 8250_mid: Fix NULL function pointer dereference on DNV/ICX-D/SNR platforms Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 373/602] intel_th: fix MSC output device reference leak Greg Kroah-Hartman
` (233 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, stable, Menachem Adin,
Alexander Usyskin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Usyskin <alexander.usyskin@intel.com>
commit f112ea910e554d58b4b39a4492b7d302f0f4204f upstream.
Fix couple of problems in mei_cl_bus_dev_release():
mei_cl_flush_queues() is running without lock.
bus->file_list access after mei_dev_bus_put(bus) can become a
use-after-free if this was the last reference to bus.
Protect queues cleanup and WARN traversal by device lock there
to avoid the concurrent access problems.
Move WARN traversal before mei_dev_bus_put(bus).
This file uses bus variable name for mei_device, adjust
code of mei_cl_bus_dev_release() to use bus variable too.
Cc: stable <stable@kernel.org>
Fixes: 35e8a426b16a ("mei: bus: Check for still connected devices in mei_cl_bus_dev_release()")
Reviewed-by: Menachem Adin <menachem.adin@intel.com>
Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
Link: https://patch.msgid.link/20260705151259.3054795-1-alexander.usyskin@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/misc/mei/bus.c | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -4,6 +4,7 @@
* Intel Management Engine Interface (Intel MEI) Linux driver
*/
+#include <linux/cleanup.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/kernel.h>
@@ -1353,15 +1354,16 @@ static void mei_dev_bus_put(struct mei_d
static void mei_cl_bus_dev_release(struct device *dev)
{
struct mei_cl_device *cldev = to_mei_cl_device(dev);
- struct mei_device *mdev = cldev->cl->dev;
+ struct mei_device *bus = cldev->bus;
struct mei_cl *cl;
- mei_cl_flush_queues(cldev->cl, NULL);
- mei_me_cl_put(cldev->me_cl);
- mei_dev_bus_put(cldev->bus);
-
- list_for_each_entry(cl, &mdev->file_list, link)
- WARN_ON(cl == cldev->cl);
+ scoped_guard(mutex, &bus->device_lock) {
+ mei_cl_flush_queues(cldev->cl, NULL);
+ mei_me_cl_put(cldev->me_cl);
+ list_for_each_entry(cl, &bus->file_list, link)
+ WARN_ON(cl == cldev->cl);
+ }
+ mei_dev_bus_put(bus);
kfree(cldev->cl);
kfree(cldev);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 373/602] intel_th: fix MSC output device reference leak
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (371 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 372/602] mei: bus: access mei_device under device_lock on cleanup Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 374/602] misc: nsm: only unlock nsm_dev on post-lock error paths Greg Kroah-Hartman
` (232 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, stable, Guangshuo Li, Johan Hovold
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <lgs201920130244@gmail.com>
commit 761b785a0cfbce43761227bc42a7f984f31f8921 upstream.
intel_th_output_open() looks up the output device with
bus_find_device_by_devt(), which returns the device with a reference that
must be dropped after use.
commit 95fc36a234da ("intel_th: fix device leak on output open()")
attempted to drop the reference from intel_th_output_release(). However,
a successful open replaces file->f_op with the output driver file
operations before returning, so close runs the output driver release
callback instead.
For MSC outputs, close runs intel_th_msc_release(), which only removes
the per-file iterator and does not drop the device reference taken by
intel_th_output_open(). Consequently, every successful MSC output open
leaks one device reference.
Drop the device reference from intel_th_msc_release(), which is the
release path actually used for MSC output files. Remove the now-unused
intel_th_output_release() callback from intel_th_output_fops.
Fixes: 95fc36a234da ("intel_th: fix device leak on output open()")
Cc: stable <stable@kernel.org>
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
Reviewed-by: Johan Hovold <johan@kernel.org>
Link: https://patch.msgid.link/20260715070851.2077965-1-lgs201920130244@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/hwtracing/intel_th/core.c | 10 ----------
drivers/hwtracing/intel_th/msu.c | 2 ++
2 files changed, 2 insertions(+), 10 deletions(-)
--- a/drivers/hwtracing/intel_th/core.c
+++ b/drivers/hwtracing/intel_th/core.c
@@ -843,18 +843,8 @@ out_put_device:
return err;
}
-static int intel_th_output_release(struct inode *inode, struct file *file)
-{
- struct intel_th_device *thdev = file->private_data;
-
- put_device(&thdev->dev);
-
- return 0;
-}
-
static const struct file_operations intel_th_output_fops = {
.open = intel_th_output_open,
- .release = intel_th_output_release,
.llseek = noop_llseek,
};
--- a/drivers/hwtracing/intel_th/msu.c
+++ b/drivers/hwtracing/intel_th/msu.c
@@ -1482,8 +1482,10 @@ static int intel_th_msc_release(struct i
{
struct msc_iter *iter = file->private_data;
struct msc *msc = iter->msc;
+ struct intel_th_device *thdev = msc->thdev;
msc_iter_remove(iter, msc);
+ put_device(&thdev->dev);
return 0;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 374/602] misc: nsm: only unlock nsm_dev on post-lock error paths
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (372 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 373/602] intel_th: fix MSC output device reference leak Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 375/602] misc: nsm: pin the module while the device is open Greg Kroah-Hartman
` (231 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, stable, Runyu Xiao, Alexander Graf
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Runyu Xiao <runyu.xiao@seu.edu.cn>
commit ce1fed11d18e163baf7f875152a33bf80f625c1a upstream.
nsm_dev_ioctl() jumps to the common out label even when the initial
copy_from_user() fails before nsm->lock has been taken. The error path
then blindly unlocks a mutex that was never acquired.
This issue was found by our static analysis tool and then manually
reviewed against the current tree.
The grounded PoC kept the miscdevice ioctl entry and the pre-lock
copy_from_user(&raw, argp, _IOC_SIZE(cmd)) failure path by issuing
NSM_IOCTL_RAW with an invalid user pointer. That failure reaches the
shared out label before mutex_lock(&nsm->lock). Lockdep reported:
WARNING: bad unlock balance detected!
exploit/193 is trying to release lock (&global_nsm.lock) at:
nsm_dev_ioctl+0x5f/0xcf [vuln_msv]
but there are no more locks to release!
no locks held by exploit/193.
Return immediately on the pre-lock copy_from_user() failure and keep the
common unlock label for the post-lock paths only.
Fixes: b9873755a6c8 ("misc: Add Nitro Secure Module driver")
Cc: stable <stable@kernel.org>
Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn>
Reviewed-by: Alexander Graf <graf@amazon.com>
Link: https://patch.msgid.link/20260617145350.513875-1-runyu.xiao@seu.edu.cn
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/misc/nsm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/misc/nsm.c
+++ b/drivers/misc/nsm.c
@@ -367,7 +367,7 @@ static long nsm_dev_ioctl(struct file *f
/* Copy user argument struct to kernel argument struct */
r = -EFAULT;
if (copy_from_user(&raw, argp, _IOC_SIZE(cmd)))
- goto out;
+ return r;
mutex_lock(&nsm->lock);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 375/602] misc: nsm: pin the module while the device is open
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (373 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 374/602] misc: nsm: only unlock nsm_dev on post-lock error paths Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 376/602] tracing: Fix mmiotrace possible NULL dereferencing of hiter->dev Greg Kroah-Hartman
` (230 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, stable, Xu Rao
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xu Rao <raoxu@uniontech.com>
commit 3b231f1e9990f4c21220d0a69733ce2105891ff9 upstream.
misc_open() installs a misc driver's file operations with fops_get(),
which pins file_operations::owner before replacing the file's f_op. The
NSM misc device leaves nsm_dev_fops.owner unset, so opening /dev/nsm does
not take a module reference on the nsm driver.
If the driver is built as a module, an open file descriptor can therefore
survive rmmod of the module that provides its ioctl callbacks. A later
ioctl through that descriptor can call into unloaded module text.
Set nsm_dev_fops.owner to THIS_MODULE so the misc core holds the module
while any /dev/nsm file descriptor is open, matching the lifetime
expectation for the installed file operations.
Fixes: b9873755a6c8 ("misc: Add Nitro Secure Module driver")
Cc: stable <stable@kernel.org>
Signed-off-by: Xu Rao <raoxu@uniontech.com>
Link: https://patch.msgid.link/BE6951D13B5E5513+20260713055523.3193089-1-raoxu@uniontech.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/misc/nsm.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/misc/nsm.c
+++ b/drivers/misc/nsm.c
@@ -413,6 +413,7 @@ static int nsm_device_init_vq(struct vir
}
static const struct file_operations nsm_dev_fops = {
+ .owner = THIS_MODULE,
.unlocked_ioctl = nsm_dev_ioctl,
.compat_ioctl = compat_ptr_ioctl,
};
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 376/602] tracing: Fix mmiotrace possible NULL dereferencing of hiter->dev
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (374 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 375/602] misc: nsm: pin the module while the device is open Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 377/602] tracing: Fix resource leak on mmiotrace trace_pipe close Greg Kroah-Hartman
` (229 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Sashiko, Steven Rostedt
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Steven Rostedt <rostedt@goodmis.org>
commit 144f29e85702234b23d2a62abf723e6a17eb5427 upstream.
If the mmio_pipe_open() fails to find a PCI device, the hiter->dev
will be assigned to NULL. The mmiotrace read() function dereferences the
hiter->dev if hiter exists.
Change the test of the read to not only check hiter being NULL, but also
the hiter->dev before dereferencing it.
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260721211143.36dbd559@gandalf.local.home
Fixes: f984b51e0779 ("ftrace: add mmiotrace plugin")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Link: https://sashiko.dev/#/patchset/20260715143604.14481-1-gaikwad.dcg%40gmail.com
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
kernel/trace/trace_mmiotrace.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/kernel/trace/trace_mmiotrace.c
+++ b/kernel/trace/trace_mmiotrace.c
@@ -146,7 +146,7 @@ static ssize_t mmio_read(struct trace_it
goto print_out;
}
- if (!hiter)
+ if (!hiter || !hiter->dev)
return 0;
mmio_print_pcidev(s, hiter->dev);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 377/602] tracing: Fix resource leak on mmiotrace trace_pipe close
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (375 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 376/602] tracing: Fix mmiotrace possible NULL dereferencing of hiter->dev Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 378/602] tracing/eprobe: Fix exact system name matching in eprobe_dyn_event_match() Greg Kroah-Hartman
` (228 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, deepakraog, Steven Rostedt
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: deepakraog <gaikwad.dcg@gmail.com>
commit c1d87e724ae55e781b7cc7ccafb34d9e668582b2 upstream.
The mmiotrace tracer was added May 12th 2008. At that time, resources
created in pipe_open() could not be freed because there was not
pipe_close function pointer of the tracer. The pipe_close function pointer
was added in December 7th, 2009, but the mmiotrace tracer was not updated.
mmio_pipe_open() allocates a header_iter and takes a pci_dev reference
when trace_pipe is opened. mmio_close() frees them, but it was only
wired to the tracer's .close callback.
tracing_release_pipe() invokes .pipe_close, not .close, when the
trace_pipe file is released. As a result, closing trace_pipe with the
mmiotrace tracer active leaked the header_iter allocation and left a
stale pci_dev reference.
Set .pipe_close to mmio_close, matching how function_graph wires both
callbacks to the same handler.
Note, if the trace_pipe is read to completion, it will clean up the
resources, but if one were to run:
# head -n 1 /sys/kernel/tracing/trace_pipe
VERSION 20070824
Over and over again, it would trigger a massive leak.
Cc: stable@vger.kernel.org
Fixes: c521efd1700a8 ("tracing: Add pipe_close interface)
Link: https://patch.msgid.link/20260715143604.14481-1-gaikwad.dcg@gmail.com
Signed-off-by: deepakraog <gaikwad.dcg@gmail.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
kernel/trace/trace_mmiotrace.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/kernel/trace/trace_mmiotrace.c
+++ b/kernel/trace/trace_mmiotrace.c
@@ -109,7 +109,6 @@ static void mmio_pipe_open(struct trace_
iter->private = hiter;
}
-/* XXX: This is not called when the pipe is closed! */
static void mmio_close(struct trace_iterator *iter)
{
struct header_iter *hiter = iter->private;
@@ -279,6 +278,7 @@ static struct tracer mmio_tracer __read_
.start = mmio_trace_start,
.pipe_open = mmio_pipe_open,
.close = mmio_close,
+ .pipe_close = mmio_close,
.read = mmio_read,
.print_line = mmio_print_line,
.noboot = true,
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 378/602] tracing/eprobe: Fix exact system name matching in eprobe_dyn_event_match()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (376 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 377/602] tracing: Fix resource leak on mmiotrace trace_pipe close Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 379/602] tracing/probes: Avoid temporary buffer truncation in trace_probe_match_command_args() Greg Kroah-Hartman
` (227 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Masami Hiramatsu (Google)
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
commit f418d68d71fd4a0a9cef92377bc8c4c3334b5b53 upstream.
eprobe_dyn_event_match() checks if the target event system in argv[0]
matches ep->event_system using strncmp(ep->event_system, argv[0], len).
However, if ep->event_system is longer than len (e.g. "eprobes" vs
"ep/event"), strncmp() still returns 0 because the first len characters
match.
Check that ep->event_system[len] is '\0' to ensure exact system name
matching.
Link: https://lore.kernel.org/all/178454235856.290363.14872590900774231133.stgit@devnote2/
Fixes: 7d5fda1c841f ("tracing: Fix event probe removal from dynamic events")
Cc: stable@vger.kernel.org
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
kernel/trace/trace_eprobe.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/kernel/trace/trace_eprobe.c
+++ b/kernel/trace/trace_eprobe.c
@@ -168,7 +168,8 @@ static bool eprobe_dyn_event_match(const
if (!slash)
return false;
- if (strncmp(ep->event_system, argv[0], slash - argv[0]))
+ if (strncmp(ep->event_system, argv[0], slash - argv[0]) ||
+ ep->event_system[slash - argv[0]] != '\0')
return false;
if (strcmp(ep->event_name, slash + 1))
return false;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 379/602] tracing/probes: Avoid temporary buffer truncation in trace_probe_match_command_args()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (377 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 378/602] tracing/eprobe: Fix exact system name matching in eprobe_dyn_event_match() Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 380/602] tracing/probes: Fix potential underflow in LEN_OR_ZERO macro Greg Kroah-Hartman
` (226 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Masami Hiramatsu (Google)
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
commit 15f197856d68882af9416fc97516bb55079b7677 upstream.
In trace_probe_match_command_args(), a stack buffer buf[MAX_ARGSTR_LEN + 1]
(256 bytes) is used to format "<name>=<comm>". However, since name can
be up to 32 bytes (MAX_ARG_NAME_LEN) and comm up to 255 bytes
(MAX_ARGSTR_LEN), the formatted string can exceed 256 bytes and get
truncated by snprintf(), causing spurious argument matching failures.
Instead of formatting into a temporary buffer on stack, compare the
argument name, the '=' delimiter, and the comm expression directly.
Link: https://lore.kernel.org/all/178454233010.290363.10428767141343428804.stgit@devnote2/
Fixes: eb5bf81330a7 ("tracing/kprobe: Add per-probe delete from event")
Cc: stable@vger.kernel.org
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
kernel/trace/trace_probe.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
--- a/kernel/trace/trace_probe.c
+++ b/kernel/trace/trace_probe.c
@@ -2212,16 +2212,17 @@ int trace_probe_compare_arg_type(struct
bool trace_probe_match_command_args(struct trace_probe *tp,
int argc, const char **argv)
{
- char buf[MAX_ARGSTR_LEN + 1];
int i;
if (tp->nr_args < argc)
return false;
for (i = 0; i < argc; i++) {
- snprintf(buf, sizeof(buf), "%s=%s",
- tp->args[i].name, tp->args[i].comm);
- if (strcmp(buf, argv[i]))
+ int len = strlen(tp->args[i].name);
+
+ if (strncmp(argv[i], tp->args[i].name, len) ||
+ argv[i][len] != '=' ||
+ strcmp(argv[i] + len + 1, tp->args[i].comm))
return false;
}
return true;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 380/602] tracing/probes: Fix potential underflow in LEN_OR_ZERO macro
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (378 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 379/602] tracing/probes: Avoid temporary buffer truncation in trace_probe_match_command_args() Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 381/602] tracing/probes: Prevent out-of-bounds write in __trace_probe_log_err() Greg Kroah-Hartman
` (225 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Masami Hiramatsu (Google)
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
commit 8ce20bfba48902e1382187cd1a852f7cf3a1e739 upstream.
In __set_print_fmt(), LEN_OR_ZERO is defined as (len ? len - pos : 0).
If len is non-zero but smaller than pos, len - pos evaluates to a negative
integer. When passed as a size argument to snprintf(), this negative value
is cast to a large unsigned size_t, bypassing buffer size limits.
Ensure len > pos before subtracting to avoid integer underflow.
Link: https://lore.kernel.org/all/178454234934.290363.15247317871499514139.stgit@devnote2/
Fixes: 5bf652aaf46c ("tracing/probes: Integrate duplicate set_print_fmt()")
Cc: stable@vger.kernel.org
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
kernel/trace/trace_probe.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/kernel/trace/trace_probe.c
+++ b/kernel/trace/trace_probe.c
@@ -1886,7 +1886,7 @@ int traceprobe_update_arg(struct probe_a
}
/* When len=0, we just calculate the needed length */
-#define LEN_OR_ZERO (len ? len - pos : 0)
+#define LEN_OR_ZERO (len > pos ? len - pos : 0)
static int __set_print_fmt(struct trace_probe *tp, char *buf, int len,
enum probe_print_type ptype)
{
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 381/602] tracing/probes: Prevent out-of-bounds write in __trace_probe_log_err()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (379 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 380/602] tracing/probes: Fix potential underflow in LEN_OR_ZERO macro Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 382/602] arm64: syscall: Ensure saved x0 is kept in-sync with tracer updates Greg Kroah-Hartman
` (224 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Masami Hiramatsu (Google)
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
commit a9d6fb284039a5d3858a1d9f9a0d7e46cfb7c2d4 upstream.
If trace_probe_log.argc is 0 in __trace_probe_log_err(), the loop
constructing the command string will not execute and p will remain equal to
command. Writing to *(p - 1) will cause an out-of-bounds access before
command. This should not happen, but better to be treated.
Reject if trace_probe_log.argc is 0.
Link: https://lore.kernel.org/all/178454233992.290363.18323091580600697731.stgit@devnote2/
Fixes: ab105a4fb894 ("tracing: Use tracing error_log with probe events")
Cc: stable@vger.kernel.org
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
kernel/trace/trace_probe.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/kernel/trace/trace_probe.c
+++ b/kernel/trace/trace_probe.c
@@ -187,7 +187,7 @@ void __trace_probe_log_err(int offset, i
lockdep_assert_held(&dyn_event_ops_mutex);
- if (!trace_probe_log.argv)
+ if (!trace_probe_log.argv || !trace_probe_log.argc)
return;
/* Recalculate the length and allocate buffer */
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 382/602] arm64: syscall: Ensure saved x0 is kept in-sync with tracer updates
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (380 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 381/602] tracing/probes: Prevent out-of-bounds write in __trace_probe_log_err() Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 383/602] Revert "arm64: syscall: Ensure saved x0 is kept in-sync with tracer updates" Greg Kroah-Hartman
` (223 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Kees Cook, Jinjie Ruan, Mark Rutland,
Yiqi Sun, Catalin Marinas, Will Deacon
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Will Deacon <will@kernel.org>
commit e057b94772328221405b067c3a85fe479b915dc8 upstream.
When seccomp support was originally added to arm64 in a1ae65b21941
("arm64: add seccomp support"), seccomp was erroneously called _before_
the ptrace syscall-enter-stop and therefore the tracer could trivially
manipulate the syscall register state after the seccomp check had
passed. This was subsequently fixed in a5cd110cb836 ("arm64/ptrace: run
seccomp after ptrace") by moving the seccomp check after the tracer has
run. Unfortunately, a decade later, that fix has been reported to be
incomplete.
On arm64, both the first argument to a syscall and its eventual return
value are allocated to register x0. In order to facilitate syscall
restarting and querying of syscall arguments on the syscall exit path,
the original value of x0 is stashed in 'struct pt_regs::orig_x0' early
during the syscall entry path and is returned for the first argument by
syscall_get_arguments(). Unlike 32-bit Arm, this stashed value is not
directly exposed via ptrace() and so changes to register x0 made by the
tracer on a syscall-enter-stop are not reflected in 'orig_x0'. This
means that seccomp, syscall tracepoints and audit can observe a stale
value for the register compared to the argument that will be observed by
the actual syscall.
Re-sync 'orig_x0' from x0 on the syscall entry path following a
potential ptrace stop (i.e. PTRACE_EVENTMSG_SYSCALL_ENTRY or
SECCOMP_RET_TRACE). This behaviour is limited to native tasks (because
compat tasks expose 'orig_r0' to ptrace) where the syscall is not being
skipped (because x0 is updated to hold the return value of -ENOSYS in
that case).
Cc: Kees Cook <kees@kernel.org>
Cc: Jinjie Ruan <ruanjinjie@huawei.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: stable@vger.kernel.org
Reported-by: Yiqi Sun <sunyiqixm@gmail.com>
Link: https://lore.kernel.org/all/20260529065444.1336608-1-sunyiqixm@gmail.com/
Suggested-by: Catalin Marinas <catalin.marinas@arm.com>
Fixes: a5cd110cb836 ("arm64/ptrace: run seccomp after ptrace")
Reviewed-by: Jinjie Ruan <ruanjinjie@huawei.com>
Tested-by: Jinjie Ruan <ruanjinjie@huawei.com>
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/arm64/kernel/ptrace.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -2285,6 +2285,21 @@ static void report_syscall(struct pt_reg
}
}
+static void update_syscall_orig_x0_after_ptrace(struct pt_regs *regs)
+{
+ /*
+ * Keep orig_x0 authoritative so that seccomp (via
+ * syscall_get_arguments()), audit and the restart path all see the same
+ * first argument the syscall is dispatched with, even if it has been
+ * updated by a tracer. Skip this for NO_SYSCALL (set either by the user
+ * or the tracer), as regs[0] holds the return value (see the comment in
+ * el0_svc_common()) and can be unwound using syscall_rollback().
+ * For compat tasks, orig_r0 is provided directly through GPR index 17.
+ */
+ if (!is_compat_task() && regs->syscallno != NO_SYSCALL)
+ regs->orig_x0 = regs->regs[0];
+}
+
int syscall_trace_enter(struct pt_regs *regs)
{
unsigned long flags = read_thread_flags();
@@ -2293,12 +2308,26 @@ int syscall_trace_enter(struct pt_regs *
report_syscall(regs, PTRACE_SYSCALL_ENTER);
if (flags & _TIF_SYSCALL_EMU)
return NO_SYSCALL;
+
+ /*
+ * Ensure ptrace changes to x0 during a regular
+ * syscall-enter-stop (PTRACE_SYSCALL) are visible to
+ * subsequent seccomp checks, tracepoints and audit.
+ */
+ update_syscall_orig_x0_after_ptrace(regs);
}
/* Do the secure computing after ptrace; failures should be fast. */
if (secure_computing() == -1)
return NO_SYSCALL;
+ /*
+ * Ensure tracer changes to x0 during seccomp ptrace exit
+ * processing (SECCOMP_RET_TRACE) are visible to tracepoints and
+ * audit.
+ */
+ update_syscall_orig_x0_after_ptrace(regs);
+
if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
trace_sys_enter(regs, regs->syscallno);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 383/602] Revert "arm64: syscall: Ensure saved x0 is kept in-sync with tracer updates"
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (381 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 382/602] arm64: syscall: Ensure saved x0 is kept in-sync with tracer updates Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 384/602] mptcp: decrement subflows counter on failed passive join Greg Kroah-Hartman
` (222 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Will Deacon
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Will Deacon <will@kernel.org>
commit 26b483d52417253d88a3a01262ac85914a7aec8e upstream.
This reverts commit e057b94772328221405b067c3a85fe479b915dc8.
Sashiko points out that updating 'orig_x0' after secure_computing()
has returned is too late to handle the case where a seccomp filter is
re-evaluated after initially returning SECCOMP_RET_TRACE. This means
that a tracer can manipulate the first argument of the syscall behind
seccomp's back.
For now, revert the initial fix and we'll have another crack at it soon.
Since the incorrect fix was cc'd to stable, do the same here with an
appropriate fixes tag.
Cc: stable@vger.kernel.org
Fixes: e057b9477232 ("arm64: syscall: Ensure saved x0 is kept in-sync with tracer updates")
Link: https://sashiko.dev/#/patchset/20260716120640.6590-1-will@kernel.org
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/arm64/kernel/ptrace.c | 29 -----------------------------
1 file changed, 29 deletions(-)
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -2285,21 +2285,6 @@ static void report_syscall(struct pt_reg
}
}
-static void update_syscall_orig_x0_after_ptrace(struct pt_regs *regs)
-{
- /*
- * Keep orig_x0 authoritative so that seccomp (via
- * syscall_get_arguments()), audit and the restart path all see the same
- * first argument the syscall is dispatched with, even if it has been
- * updated by a tracer. Skip this for NO_SYSCALL (set either by the user
- * or the tracer), as regs[0] holds the return value (see the comment in
- * el0_svc_common()) and can be unwound using syscall_rollback().
- * For compat tasks, orig_r0 is provided directly through GPR index 17.
- */
- if (!is_compat_task() && regs->syscallno != NO_SYSCALL)
- regs->orig_x0 = regs->regs[0];
-}
-
int syscall_trace_enter(struct pt_regs *regs)
{
unsigned long flags = read_thread_flags();
@@ -2308,26 +2293,12 @@ int syscall_trace_enter(struct pt_regs *
report_syscall(regs, PTRACE_SYSCALL_ENTER);
if (flags & _TIF_SYSCALL_EMU)
return NO_SYSCALL;
-
- /*
- * Ensure ptrace changes to x0 during a regular
- * syscall-enter-stop (PTRACE_SYSCALL) are visible to
- * subsequent seccomp checks, tracepoints and audit.
- */
- update_syscall_orig_x0_after_ptrace(regs);
}
/* Do the secure computing after ptrace; failures should be fast. */
if (secure_computing() == -1)
return NO_SYSCALL;
- /*
- * Ensure tracer changes to x0 during seccomp ptrace exit
- * processing (SECCOMP_RET_TRACE) are visible to tracepoints and
- * audit.
- */
- update_syscall_orig_x0_after_ptrace(regs);
-
if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
trace_sys_enter(regs, regs->syscallno);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 384/602] mptcp: decrement subflows counter on failed passive join
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (382 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 383/602] Revert "arm64: syscall: Ensure saved x0 is kept in-sync with tracer updates" Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 385/602] mptcp: only set DATA_FIN when a mapping is present Greg Kroah-Hartman
` (221 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Chenguang Zhao,
Matthieu Baerts (NGI0), Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chenguang Zhao <zhaochenguang@kylinos.cn>
commit f3ca0ee2cc308e33896536789cbc5f3a12ca7b30 upstream.
mptcp_pm_allow_new_subflow() increments extra_subflows before
__mptcp_finish_join() on the passive MP_JOIN path.
In case of race conditions, the subflow is dropped without calling
mptcp_close_ssk(), so the counter is not rolled back.
Call mptcp_pm_close_subflow() when the join completion fails to
decrement the subflows counter.
Fixes: 10f6d46c943d ("mptcp: fix race between MP_JOIN and close")
Cc: stable@vger.kernel.org
Signed-off-by: Chenguang Zhao <zhaochenguang@kylinos.cn>
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20260722-net-mptcp-misc-fixes-7-2-rc5-v1-1-6fb595bc86ef@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/mptcp/protocol.c | 1 +
1 file changed, 1 insertion(+)
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -3825,6 +3825,7 @@ bool mptcp_finish_join(struct sock *ssk)
mptcp_data_unlock(parent);
if (!ret) {
+ mptcp_pm_close_subflow(msk);
err_prohibited:
subflow->reset_reason = MPTCP_RST_EPROHIBIT;
return false;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 385/602] mptcp: only set DATA_FIN when a mapping is present
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (383 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 384/602] mptcp: decrement subflows counter on failed passive join Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 386/602] sctp: dont free the ASCONFs own transport in DEL-IP processing Greg Kroah-Hartman
` (220 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Paolo Abeni, Michael Bommarito,
Matthieu Baerts (NGI0), Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <michael.bommarito@gmail.com>
commit b2ff91b752b0d85e8815e7f44fd85205c4268094 upstream.
mptcp_get_options() clears only the status group of struct
mptcp_options_received; data_seq, subflow_seq and data_len are filled in
by mptcp_parse_option() exclusively inside the DSS mapping block, which
runs only when the DSS M (mapping present) bit is set.
A peer can send a DSS option with the DATA_FIN flag set but the mapping
bit clear. The parser then records mp_opt->data_fin while leaving
data_len and data_seq uninitialized. For a zero-length segment
mptcp_incoming_options() evaluates
if (mp_opt.data_fin && mp_opt.data_len == 1 &&
mptcp_update_rcv_data_fin(msk, mp_opt.data_seq, mp_opt.dsn64))
which reads the uninitialized data_len and data_seq; KMSAN reports an
uninit-value in mptcp_incoming_options(). The stale data_seq can also be
fed into the receive-side DATA_FIN sequence tracking.
Record the DATA_FIN flag only when the DSS option carries a mapping, so
data_fin is never set without data_seq and data_len also being present.
data_fin is part of the status group that mptcp_get_options() clears up
front, so on the no-map path it stays zero and the zero-length DATA_FIN
branch is simply skipped. A DATA_FIN is always transmitted together with
a mapping (mptcp_write_data_fin() sets use_map along with data_seq and
data_len), so legitimate DATA_FIN handling is unaffected.
Move the pr_debug() that logs the parsed DSS flags below the mapping
block, so it reports the final data_fin value instead of the stale one
it would otherwise print before the assignment.
Fixes: 43b54c6ee382 ("mptcp: Use full MPTCP-level disconnect state machine")
Suggested-by: Paolo Abeni <pabeni@redhat.com>
Cc: stable@vger.kernel.org
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20260709191925.2811195-1-michael.bommarito@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/mptcp/options.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
--- a/net/mptcp/options.c
+++ b/net/mptcp/options.c
@@ -157,17 +157,11 @@ static void mptcp_parse_option(const str
ptr++;
flags = (*ptr++) & MPTCP_DSS_FLAG_MASK;
- mp_opt->data_fin = (flags & MPTCP_DSS_DATA_FIN) != 0;
mp_opt->dsn64 = (flags & MPTCP_DSS_DSN64) != 0;
mp_opt->use_map = (flags & MPTCP_DSS_HAS_MAP) != 0;
mp_opt->ack64 = (flags & MPTCP_DSS_ACK64) != 0;
mp_opt->use_ack = (flags & MPTCP_DSS_HAS_ACK);
- pr_debug("data_fin=%d dsn64=%d use_map=%d ack64=%d use_ack=%d\n",
- mp_opt->data_fin, mp_opt->dsn64,
- mp_opt->use_map, mp_opt->ack64,
- mp_opt->use_ack);
-
expected_opsize = TCPOLEN_MPTCP_DSS_BASE;
if (mp_opt->use_ack) {
@@ -178,12 +172,18 @@ static void mptcp_parse_option(const str
}
if (mp_opt->use_map) {
+ mp_opt->data_fin = (flags & MPTCP_DSS_DATA_FIN) != 0;
if (mp_opt->dsn64)
expected_opsize += TCPOLEN_MPTCP_DSS_MAP64;
else
expected_opsize += TCPOLEN_MPTCP_DSS_MAP32;
}
+ pr_debug("data_fin=%d dsn64=%d use_map=%d ack64=%d use_ack=%d\n",
+ mp_opt->data_fin, mp_opt->dsn64,
+ mp_opt->use_map, mp_opt->ack64,
+ mp_opt->use_ack);
+
/* Always parse any csum presence combination, we will enforce
* RFC 8684 Section 3.3.0 checks later in subflow_data_ready
*/
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 386/602] sctp: dont free the ASCONFs own transport in DEL-IP processing
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (384 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 385/602] mptcp: only set DATA_FIN when a mapping is present Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 387/602] sctp: avoid auth_enable sysctl UAF during netns teardown Greg Kroah-Hartman
` (219 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, stable, Jun Yang, Xin Long,
Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jun Yang <junvyyang@tencent.com>
commit 9b2854f86f0b56e9027d68e7a3fc909d1a9b566f upstream.
sctp_process_asconf() caches the transport the ASCONF chunk is processed
against in asconf->transport (== chunk->transport, set once in sctp_rcv()).
For an ASCONF located through its Address Parameter by
__sctp_rcv_asconf_lookup(), that cached transport corresponds to the
Address Parameter, which need not be the packet's source address.
sctp_process_asconf_param() rejects a DEL-IP for the packet source address
(ADDIP D8, SCTP_ERROR_DEL_SRC_IP), but nothing protects asconf->transport.
A single ASCONF can therefore carry, in order:
[Address Parameter L] [DEL-IP L] [DEL-IP 0.0.0.0]
where L differs from the source. The DEL-IP for L passes the D8 check and
calls sctp_assoc_rm_peer() on the transport that asconf->transport still
points at, freeing it (RCU-deferred). The following wildcard DEL-IP then
reuses the now-dangling asconf->transport in sctp_assoc_set_primary() and
sctp_assoc_del_nonprimary_peers(): set_primary() dereferences the freed
transport (->ipaddr, ->state) and plants the dangling pointer into
asoc->peer.primary_path / active_path, and del_nonprimary_peers(), keeping
only the pointer that is no longer on the list, removes every real
transport, leaving the association with a transport_count of 0 and
primary_path/active_path pointing at freed memory.
Reject a DEL-IP that targets the transport the ASCONF is being processed
against, mirroring the existing source-address guard, so the wildcard
branch can never reuse a freed transport.
Fixes: 42e30bf3463c ("[SCTP]: Handle the wildcard ADD-IP Address parameter")
Cc: stable@kernel.org
Signed-off-by: Jun Yang <junvyyang@tencent.com>
Acked-by: Xin Long <lucien.xin@gmail.com>
Link: https://patch.msgid.link/tencent_73762ED1DF08CC9D5F5F61954B01350CFE0A@qq.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/sctp/sm_make_chunk.c | 6 ++++++
1 file changed, 6 insertions(+)
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -3171,6 +3171,12 @@ static __be16 sctp_process_asconf_param(
if (!peer)
return SCTP_ERROR_DNS_FAILED;
+ /* Don't free asconf->transport; a later wildcard DEL-IP
+ * parameter reuses it.
+ */
+ if (peer == asconf->transport)
+ return SCTP_ERROR_REQ_REFUSED;
+
sctp_assoc_rm_peer(asoc, peer);
break;
case SCTP_PARAM_SET_PRIMARY:
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 387/602] sctp: avoid auth_enable sysctl UAF during netns teardown
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (385 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 386/602] sctp: dont free the ASCONFs own transport in DEL-IP processing Greg Kroah-Hartman
@ 2026-07-30 14:12 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 388/602] sctp: close UDP tunnel sockets " Greg Kroah-Hartman
` (218 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:12 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yuan Tan, Yifan Wu, Juefei Pu,
Xin Liu, Qi Tang, Zhiling Zou, Ren Wei, Xin Long, Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhiling Zou <roxy520tt@gmail.com>
commit f8d5e7846025f4ab15a461235f8ebae9094a361a upstream.
proc_sctp_do_auth() updates the SCTP control socket after changing
net.sctp.auth_enable. The handler gets the per-net SCTP state from
ctl->data, so an already opened sysctl file can still target a network
namespace while that namespace is being torn down.
SCTP previously registered its per-net sysctls from sctp_defaults_init(),
while the control socket is created later from sctp_ctrlsock_init(). This
exposed a window during initialization where auth_enable was writable
before net->sctp.ctl_sock existed, and a teardown window where auth_enable
stayed writable after inet_ctl_sock_destroy() had released the control
socket.
Move the per-net SCTP sysctl registration into sctp_ctrlsock_init() after
sctp_ctl_sock_init() succeeds, and unregister the sysctl table before
destroying the control socket in sctp_ctrlsock_exit(). If sysctl
registration fails after the control socket was created, destroy the
control socket in the same init path.
Make sctp_sysctl_net_unregister() tolerate a missing header and clear the
saved pointer so init-error and exit paths can safely share the unregister
helper.
Fixes: 15649fd5415e ("sctp: sysctl: auth_enable: avoid using current->nsproxy")
Cc: stable@vger.kernel.org
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Co-developed-by: Qi Tang <tpluszz77@gmail.com>
Signed-off-by: Qi Tang <tpluszz77@gmail.com>
Signed-off-by: Zhiling Zou <roxy520tt@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
Acked-by: Xin Long <lucien.xin@gmail.com>
Link: https://patch.msgid.link/390cd5e91ed60eea27b0b64d0468301a9e73b808.1784033357.git.roxy520tt@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/sctp/protocol.c | 20 ++++++++++++--------
net/sctp/sysctl.c | 9 +++++++--
2 files changed, 19 insertions(+), 10 deletions(-)
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -1397,10 +1397,6 @@ static int __net_init sctp_defaults_init
net->sctp.l3mdev_accept = 1;
#endif
- status = sctp_sysctl_net_register(net);
- if (status)
- goto err_sysctl_register;
-
/* Allocate and initialise sctp mibs. */
status = init_sctp_mibs(net);
if (status)
@@ -1434,8 +1430,6 @@ err_init_proc:
cleanup_sctp_mibs(net);
#endif
err_init_mibs:
- sctp_sysctl_net_unregister(net);
-err_sysctl_register:
return status;
}
@@ -1450,7 +1444,6 @@ static void __net_exit sctp_defaults_exi
net->sctp.proc_net_sctp = NULL;
#endif
cleanup_sctp_mibs(net);
- sctp_sysctl_net_unregister(net);
}
static struct pernet_operations sctp_defaults_ops = {
@@ -1464,16 +1457,27 @@ static int __net_init sctp_ctrlsock_init
/* Initialize the control inode/socket for handling OOTB packets. */
status = sctp_ctl_sock_init(net);
- if (status)
+ if (status) {
pr_err("Failed to initialize the SCTP control sock\n");
+ return status;
+ }
+
+ status = sctp_sysctl_net_register(net);
+ if (status) {
+ inet_ctl_sock_destroy(net->sctp.ctl_sock);
+ net->sctp.ctl_sock = NULL;
+ }
return status;
}
static void __net_exit sctp_ctrlsock_exit(struct net *net)
{
+ sctp_sysctl_net_unregister(net);
+
/* Free the control endpoint. */
inet_ctl_sock_destroy(net->sctp.ctl_sock);
+ net->sctp.ctl_sock = NULL;
}
static struct pernet_operations sctp_ctrlsock_ops = {
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -626,11 +626,16 @@ int sctp_sysctl_net_register(struct net
void sctp_sysctl_net_unregister(struct net *net)
{
+ struct ctl_table_header *header = net->sctp.sysctl_header;
const struct ctl_table *table;
- table = net->sctp.sysctl_header->ctl_table_arg;
- unregister_net_sysctl_table(net->sctp.sysctl_header);
+ if (!header)
+ return;
+
+ table = header->ctl_table_arg;
+ unregister_net_sysctl_table(header);
kfree(table);
+ net->sctp.sysctl_header = NULL;
}
static struct ctl_table_header *sctp_sysctl_header;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 388/602] sctp: close UDP tunnel sockets during netns teardown
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (386 preceding siblings ...)
2026-07-30 14:12 ` [PATCH 6.12 387/602] sctp: avoid auth_enable sysctl UAF during netns teardown Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 389/602] ceph: add owner/capability checks for CEPH_IOC_SET_LAYOUT* Greg Kroah-Hartman
` (217 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sashiko, Zhiling Zou, Ren Wei,
Xin Long, Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhiling Zou <roxy520tt@gmail.com>
commit ffb2bd7ade36ec4da32c46a6eddbf4515316d08c upstream.
proc_sctp_do_udp_port() starts per-net SCTP UDP tunneling sockets when
net.sctp.udp_port is set, and stops/restarts them when the sysctl value
changes. The netns exit path does not stop these sockets, so a namespace
can be torn down while its SCTP UDP tunnel sockets are still installed.
Close the UDP tunnel sockets from sctp_ctrlsock_exit() after unregistering
the per-net sysctl table. This prevents new sysctl writes from racing in
while the sockets are being released, and closes the sockets before the
control socket is destroyed.
Fixes: 046c052b475e ("sctp: enable udp tunneling socks")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/b9f1f02b0780ad6a719e2413f5f0bb8eb7702d94.1782585631.git.roxy520tt%40gmail.com
Signed-off-by: Zhiling Zou <roxy520tt@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
Acked-by: Xin Long <lucien.xin@gmail.com>
Link: https://patch.msgid.link/6dab75f22855cb219e2e30a5497cab03b970ab91.1784033357.git.roxy520tt@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/sctp/protocol.c | 1 +
1 file changed, 1 insertion(+)
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -1474,6 +1474,7 @@ static int __net_init sctp_ctrlsock_init
static void __net_exit sctp_ctrlsock_exit(struct net *net)
{
sctp_sysctl_net_unregister(net);
+ sctp_udp_sock_stop(net);
/* Free the control endpoint. */
inet_ctl_sock_destroy(net->sctp.ctl_sock);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 389/602] ceph: add owner/capability checks for CEPH_IOC_SET_LAYOUT*
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (387 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 388/602] sctp: close UDP tunnel sockets " Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 17:40 ` Ilya Dryomov
2026-07-30 14:13 ` [PATCH 6.12 390/602] ceph: fix pre-auth out-of-bounds read on snaptrace in ceph_handle_caps() Greg Kroah-Hartman
` (216 subsequent siblings)
605 siblings, 1 reply; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Max Kellermann, Xiubo Li,
Ilya Dryomov
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Max Kellermann <max.kellermann@ionos.com>
commit cee38bbf5556a8e0a232ccae41649580827d7806 upstream.
These permission checks were already missing in the initial
impementation of these ioctls. This Ceph allows any user who owns a
file descriptor to manipulate the layout of any file, even if they
don't have write permissions.
It might be a good idea to guard other ioctls with permission checks
as well or even disallow regular users (even if they own the file) to
manipulate layout settings completely, as this may be abused to DoS
the Ceph servers, but right now, I find it most urgent to have setter
checks at all.
Cc: stable@vger.kernel.org
Fixes: 8f4e91dee2a2 ("ceph: ioctls")
Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
Reviewed-by: Xiubo Li <xiubo.li@clyso.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/ceph/ioctl.c | 6 ++++++
1 file changed, 6 insertions(+)
--- a/fs/ceph/ioctl.c
+++ b/fs/ceph/ioctl.c
@@ -72,6 +72,9 @@ static long ceph_ioctl_set_layout(struct
struct ceph_ioctl_layout nl;
int err;
+ if (!inode_owner_or_capable(&nop_mnt_idmap, inode))
+ return -EACCES;
+
if (copy_from_user(&l, arg, sizeof(l)))
return -EFAULT;
@@ -142,6 +145,9 @@ static long ceph_ioctl_set_layout_policy
int err;
struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
+ if (!inode_owner_or_capable(&nop_mnt_idmap, inode))
+ return -EACCES;
+
/* copy and validate */
if (copy_from_user(&l, arg, sizeof(l)))
return -EFAULT;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 390/602] ceph: fix pre-auth out-of-bounds read on snaptrace in ceph_handle_caps()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (388 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 389/602] ceph: add owner/capability checks for CEPH_IOC_SET_LAYOUT* Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 391/602] ceph: fix refcount leak in ceph_readdir() Greg Kroah-Hartman
` (215 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Bryam Vargas, Viacheslav Dubeyko,
Ilya Dryomov
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <hexlabsecurity@proton.me>
commit 4dbc71bcaf9a30abf3920a4e2cc4ed33bba78c02 upstream.
ceph_handle_caps() reads snap_trace_len from the wire-format
ceph_mds_caps header and uses it unconditionally to build a fake
end pointer (snaptrace + snaptrace_len) that is later handed to
ceph_update_snap_trace() in the CEPH_CAP_OP_IMPORT case:
snaptrace = h + 1;
snaptrace_len = le32_to_cpu(h->snap_trace_len);
p = snaptrace + snaptrace_len;
...
case CEPH_CAP_OP_IMPORT:
if (snaptrace_len) {
...
if (ceph_update_snap_trace(mdsc, snaptrace,
snaptrace + snaptrace_len,
false, &realm)) { ... }
ceph_update_snap_trace() then decodes a struct ceph_mds_snap_realm
from snaptrace using ceph_decode_need(&p, e, sizeof(*ri), bad)
with the attacker-supplied fake end e == snaptrace + snaptrace_len.
With snaptrace_len == 0xFFFFFFFF the bound check is trivially
satisfied, ri = p reads sizeof(struct ceph_mds_snap_realm) past
the legitimate msg->front buffer, and ri->num_snaps /
ri->num_prior_parent_snaps then drive further out-of-bounds
reads of the encoded snap arrays.
The eleven msg_version >= 2 .. msg_version >= 12 decoder blocks
above the op switch each catch this OOB through their
ceph_decode_*_safe() / ceph_decode_need() helpers, but they sit
behind a hdr.version-gated if, so a malicious or compromised
MDS that sets msg->hdr.version = 1 reaches the IMPORT path with
no version-gated decoder having validated snap_trace_len. The
shape has been present since ceph_handle_caps() was introduced.
Validate snap_trace_len against the message front buffer before
consuming it, using the canonical ceph_decode_need() / ceph_has_room()
helper. The helper bounds the length with subtraction (n <= end - p,
guarded by end >= p) rather than pointer addition, so it is wrap-safe
for the attacker-controlled u32 length on 32-bit builds where
p + snap_trace_len could overflow the address space. This matches the
rest of the ceph decode path (e.g. the pool_ns_len check a few lines
below), and the existing goto bad cleanup already covers this exit
path.
Cc: stable@vger.kernel.org
Fixes: a8599bd821d0 ("ceph: capability management")
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
Reviewed-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/ceph/caps.c | 1 +
1 file changed, 1 insertion(+)
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -4378,6 +4378,7 @@ void ceph_handle_caps(struct ceph_mds_se
snaptrace = h + 1;
snaptrace_len = le32_to_cpu(h->snap_trace_len);
+ ceph_decode_need(&snaptrace, end, snaptrace_len, bad);
p = snaptrace + snaptrace_len;
if (msg_version >= 2) {
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 391/602] ceph: fix refcount leak in ceph_readdir()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (389 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 390/602] ceph: fix pre-auth out-of-bounds read on snaptrace in ceph_handle_caps() Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 392/602] libceph: bound get_version reply decode to front len Greg Kroah-Hartman
` (214 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, WenTao Liang, Viacheslav Dubeyko,
Alex Markuze, Ilya Dryomov
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: WenTao Liang <vulab@iscas.ac.cn>
commit c3e64079d8b9663e3998d0caac9aba915b6b93ae upstream.
The ceph_readdir() function allocates a ceph_mds_request via
ceph_mdsc_create_request() and stores it in dfi->last_readdir. In
the directory entry processing loop, if the entry's offset is less
than ctx->pos or if the inode pointer is unexpectedly NULL, the
function returns -EIO without releasing the reference held by
dfi->last_readdir, causing a refcount leak.
Fix this by adding ceph_mdsc_put_request(dfi->last_readdir) before
returning on these error paths. Also set dfi->last_readdir to NULL
for safety, matching the cleanup done at the normal exit.
Cc: stable@vger.kernel.org
Fixes: af9ffa6df7e3 ("ceph: add support to readdir for encrypted names")
Signed-off-by: WenTao Liang <vulab@iscas.ac.cn>
Reviewed-by: Viacheslav Dubeyko <slava@dubeyko.com>
Reviewed-by: Alex Markuze <amarkuze@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/ceph/dir.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -546,11 +546,16 @@ more:
pr_warn_client(cl,
"%p %llx.%llx rde->offset 0x%llx ctx->pos 0x%llx\n",
inode, ceph_vinop(inode), rde->offset, ctx->pos);
+ ceph_mdsc_put_request(dfi->last_readdir);
+ dfi->last_readdir = NULL;
return -EIO;
}
- if (WARN_ON_ONCE(!rde->inode.in))
+ if (WARN_ON_ONCE(!rde->inode.in)) {
+ ceph_mdsc_put_request(dfi->last_readdir);
+ dfi->last_readdir = NULL;
return -EIO;
+ }
ctx->pos = rde->offset;
doutc(cl, "%p %llx.%llx (%d/%d) -> %llx '%.*s' %p\n", inode,
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 392/602] libceph: bound get_version reply decode to front len
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (390 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 391/602] ceph: fix refcount leak in ceph_readdir() Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 393/602] libceph: Fix multiplication overflow in decode_new_up_state_weight() Greg Kroah-Hartman
` (213 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yuan Tan, Zhengchuan Liang, Xin Liu,
Douya Le, Ren Wei, Viacheslav Dubeyko, Ilya Dryomov
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Douya Le <ldy3087146292@gmail.com>
commit d3c32939fa0e3ee9b883b9a0fd1972c5c444e3d0 upstream.
handle_get_version_reply() uses msg->front_alloc_len as the decode
boundary for MON_GET_VERSION_REPLY. That is the size of the reused
reply buffer, not the number of bytes actually received.
A truncated reply can therefore pass ceph_decode_need() and decode the
second u64 from stale tail bytes left in the buffer by an earlier
message, causing an uninitialized memory read.
Use msg->front.iov_len as the receive-side decode boundary, matching
other libceph reply handlers and limiting decoding to the bytes that
were actually read from the wire.
Cc: stable@vger.kernel.org
Fixes: 513a8243d67f ("libceph: mon_get_version request infrastructure")
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Assisted-by: Codex:GPT-5.4
Signed-off-by: Douya Le <ldy3087146292@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
Reviewed-by: Viacheslav Dubeyko <slava@dubeyko.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ceph/mon_client.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/net/ceph/mon_client.c
+++ b/net/ceph/mon_client.c
@@ -821,7 +821,7 @@ static void handle_get_version_reply(str
struct ceph_mon_generic_request *req;
u64 tid = le64_to_cpu(msg->hdr.tid);
void *p = msg->front.iov_base;
- void *end = p + msg->front_alloc_len;
+ void *const end = p + msg->front.iov_len;
u64 handle;
dout("%s msg %p tid %llu\n", __func__, msg, tid);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 393/602] libceph: Fix multiplication overflow in decode_new_up_state_weight()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (391 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 392/602] libceph: bound get_version reply decode to front len Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 394/602] libceph: guard missing CRUSH type name lookup Greg Kroah-Hartman
` (212 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Raphael Zimmer, Viacheslav Dubeyko,
Ilya Dryomov
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
commit 98917a499ec7064c14fc56d180a4fd636fc2784c upstream.
If a message of type CEPH_MSG_OSD_MAP contains a (maliciously) corrupted
osdmap, out-of-bounds memory accesses may occur in
decode_new_up_state_weight(). This happens because the bounds check for
the new_state part is based on calculating its length depending on a len
value read from the incoming message. This calculation may overflow
leading to an incorrect bounds check. Subsequently, out-of-bounds reads
may occur when decoding this part.
This patch switches the multiplication to use check_mul_overflow() to
abort processing the osdmap if an overflow occurred. Therefore,
osdmaps/messages containing large values for len that result in a
multiplication overflow are treated as invalid.
[ idryomov: rename new_state_len -> new_state_item_size, formatting ]
Cc: stable@vger.kernel.org
Fixes: 930c53286977 ("libceph: apply new_state before new_up_client on incrementals")
Signed-off-by: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
Reviewed-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ceph/osdmap.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
--- a/net/ceph/osdmap.c
+++ b/net/ceph/osdmap.c
@@ -1844,6 +1844,8 @@ static int decode_new_up_state_weight(vo
void *new_up_client;
void *new_state;
void *new_weight_end;
+ const u32 new_state_item_size =
+ sizeof(u32) + (struct_v >= 5 ? sizeof(u32) : sizeof(u8));
u32 len;
int ret;
int i;
@@ -1864,7 +1866,8 @@ static int decode_new_up_state_weight(vo
new_state = *p;
ceph_decode_32_safe(p, end, len, e_inval);
- len *= sizeof(u32) + (struct_v >= 5 ? sizeof(u32) : sizeof(u8));
+ if (check_mul_overflow(len, new_state_item_size, &len))
+ goto e_inval;
ceph_decode_need(p, end, len, e_inval);
*p += len;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 394/602] libceph: guard missing CRUSH type name lookup
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (392 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 393/602] libceph: Fix multiplication overflow in decode_new_up_state_weight() Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 395/602] libceph: refresh auth->authorizer_buf{,_len} after authorizer update Greg Kroah-Hartman
` (211 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yuan Tan, Zhengchuan Liang, Xin Liu,
Zhao Zhang, Ren Wei, Viacheslav Dubeyko, Ilya Dryomov
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhao Zhang <zzhan461@ucr.edu>
commit bbeae12fda3384a90fbebc8a19ba9d33f85b5361 upstream.
Localized read selection can walk a parent bucket whose name exists in
the CRUSH map while its type has no matching entry in type_names.
get_immediate_parent() then dereferences a NULL type_cn and passes an
invalid pointer into strcmp(), causing a null-ptr-deref.
Skip such malformed parent buckets unless both the bucket name and type
name metadata are present. This keeps malformed hierarchy data from
crashing locality lookup and safely falls back to "not local".
[ idryomov: add WARN_ON_ONCE ]
Cc: stable@vger.kernel.org
Fixes: 117d96a04f00 ("libceph: support for balanced and localized reads")
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Assisted-by: Codex:GPT-5.4
Signed-off-by: Zhao Zhang <zzhan461@ucr.edu>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
Reviewed-by: Viacheslav Dubeyko <slava@dubeyko.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ceph/osdmap.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
--- a/net/ceph/osdmap.c
+++ b/net/ceph/osdmap.c
@@ -3060,8 +3060,11 @@ static int get_immediate_parent(struct c
if (b->items[j] != id)
continue;
- *parent_type_id = b->type;
type_cn = lookup_crush_name(&c->type_names, b->type);
+ if (WARN_ON_ONCE(!type_cn))
+ continue;
+
+ *parent_type_id = b->type;
parent_loc->cl_type_name = type_cn->cn_name;
parent_loc->cl_name = cn->cn_name;
return b->id;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 395/602] libceph: refresh auth->authorizer_buf{,_len} after authorizer update
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (393 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 394/602] libceph: guard missing CRUSH type name lookup Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 396/602] libceph: Reject monmaps advertising zero monitors Greg Kroah-Hartman
` (210 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Shuangpeng Bai, Alex Markuze,
Ilya Dryomov
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shuangpeng Bai <shuangpeng.kernel@gmail.com>
commit 937d61f86d377a3aa578adae7a3dfcecdddf9d89 upstream.
ceph_x_create_authorizer() caches au->buf->vec.iov_base and
au->buf->vec.iov_len in struct ceph_auth_handshake. These
cached values are then used by the messenger connect code when
sending the authorizer.
ceph_x_update_authorizer() can rebuild the authorizer when a newer
service ticket is available. If the rebuilt authorizer no longer
fits in the existing buffer, ceph_x_build_authorizer() drops its
reference to au->buf and allocates a new one. If this is the final
reference, ceph_buffer_put() frees the old ceph_buffer and its
vec.iov_base, but auth->authorizer_buf still points at that freed
memory.
A subsequent msgr1 reconnect can therefore queue the stale pointer
and trigger a KASAN slab-use-after-free in _copy_from_iter() while
tcp_sendmsg() copies the authorizer.
Refresh auth->authorizer_buf and auth->authorizer_buf_len after a
successful authorizer rebuild so the messenger sends the current
buffer.
Cc: stable@vger.kernel.org
Fixes: 0bed9b5c523d ("libceph: add update_authorizer auth method")
Closes: https://lore.kernel.org/all/E378850E-106C-427B-A241-970EB2D054D7@gmail.com/
Signed-off-by: Shuangpeng Bai <shuangpeng.kernel@gmail.com>
Reviewed-by: Alex Markuze <amarkuze@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ceph/auth_x.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
--- a/net/ceph/auth_x.c
+++ b/net/ceph/auth_x.c
@@ -781,9 +781,16 @@ static int ceph_x_update_authorizer(
au = (struct ceph_x_authorizer *)auth->authorizer;
if (au->secret_id < th->secret_id) {
+ int ret;
+
dout("ceph_x_update_authorizer service %u secret %llu < %llu\n",
au->service, au->secret_id, th->secret_id);
- return ceph_x_build_authorizer(ac, th, au);
+ ret = ceph_x_build_authorizer(ac, th, au);
+ if (ret)
+ return ret;
+
+ auth->authorizer_buf = au->buf->vec.iov_base;
+ auth->authorizer_buf_len = au->buf->vec.iov_len;
}
return 0;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 396/602] libceph: Reject monmaps advertising zero monitors
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (394 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 395/602] libceph: refresh auth->authorizer_buf{,_len} after authorizer update Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 397/602] libceph: reject zero bucket types in crush_decode Greg Kroah-Hartman
` (209 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Raphael Zimmer, Ilya Dryomov
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
commit 40480eee361ed9676b3f844d532ac28b47251634 upstream.
A message of type CEPH_MSG_MON_MAP contains a monmap that is sent from a
monitor to the client. This monmap contains information about the
existing monitors in the cluster. Currently, a monmap indicating that
there are zero monitors in the cluster is treated as valid. However, it
is impossible to have zero monitors in the cluster and still receive a
valid monmap from a monitor. Therefore, such a monmap must be corrupted
and should be treated as invalid. Furthermore, a monmap with a monitor
count of zero can subsequently crash the client when attempting to open
a session with a monitor in __open_session(). This happens because the
"BUG_ON(monc->monmap->num_mon < 1)" assertion in pick_new_mon() is
triggered.
This patch extends a check in ceph_monmap_decode() to also reject
arriving mon_maps with num_mon == 0 rather than only with
num_mon > CEPH_MAX_MON.
[ idryomov: drop "log output for unusual values of num_mon" part ]
Cc: stable@vger.kernel.org
Signed-off-by: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ceph/mon_client.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/net/ceph/mon_client.c
+++ b/net/ceph/mon_client.c
@@ -114,7 +114,7 @@ static struct ceph_monmap *ceph_monmap_d
dout("%s fsid %pU epoch %u num_mon %u\n", __func__, &fsid, epoch,
num_mon);
- if (num_mon > CEPH_MAX_MON)
+ if (num_mon == 0 || num_mon > CEPH_MAX_MON)
goto e_inval;
monmap = kmalloc(struct_size(monmap, mon_inst, num_mon), GFP_NOIO);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 397/602] libceph: reject zero bucket types in crush_decode
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (395 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 396/602] libceph: Reject monmaps advertising zero monitors Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 398/602] libceph: remove debugfs files before client teardown Greg Kroah-Hartman
` (208 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yuan Tan, Zhengchuan Liang, Xin Liu,
Douya Le, Ren Wei, Ilya Dryomov
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Douya Le <ldy3087146292@gmail.com>
commit 05f90284223381005d6bcddab3fda4a97f9c3401 upstream.
CRUSH bucket type 0 is reserved for devices. The mapper relies on
that invariant and uses type 0 to identify leaf devices.
If crush_decode() accepts a bucket with type 0, a malformed CRUSH map
can make the mapper treat a negative bucket ID as a device and pass it
to is_out(), which then indexes the OSD weight array with a negative
value.
Reject zero bucket types while decoding the CRUSH map so the invalid
state never reaches the mapper.
Cc: stable@vger.kernel.org
Fixes: f24e9980eb86 ("ceph: OSD client")
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Assisted-by: Codex:GPT-5.4
Signed-off-by: Douya Le <ldy3087146292@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ceph/osdmap.c | 2 ++
1 file changed, 2 insertions(+)
--- a/net/ceph/osdmap.c
+++ b/net/ceph/osdmap.c
@@ -520,6 +520,8 @@ static struct crush_map *crush_decode(vo
ceph_decode_need(p, end, 4*sizeof(u32), bad);
b->id = ceph_decode_32(p);
b->type = ceph_decode_16(p);
+ if (b->type == 0)
+ goto bad;
b->alg = ceph_decode_8(p);
if (b->alg != alg) {
b->alg = 0;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 398/602] libceph: remove debugfs files before client teardown
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (396 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 397/602] libceph: reject zero bucket types in crush_decode Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 399/602] amt: fix use-after-free in AMT delayed works Greg Kroah-Hartman
` (207 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yuan Tan, Zhengchuan Liang, Xin Liu,
Douya Le, Ren Wei, Viacheslav Dubeyko, Ilya Dryomov
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Douya Le <ldy3087146292@gmail.com>
commit e4c804726c4afce3ba648b982d564f6af2cfa328 upstream.
ceph_destroy_client() tears down the monitor client before removing
the per-client debugfs files. A concurrent read of the monmap debugfs
file can enter monmap_show() after ceph_monc_stop() has freed
monc->monmap, triggering a use-after-free.
Remove the debugfs files before stopping the OSD and monitor clients.
debugfs_remove() drains active handlers and prevents new accesses, so
the debugfs callbacks can no longer race the rest of client teardown.
Cc: stable@vger.kernel.org
Fixes: 76aa844d5b2f ("ceph: debugfs")
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Assisted-by: Codex:GPT-5.4
Signed-off-by: Douya Le <ldy3087146292@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
Reviewed-by: Viacheslav Dubeyko <slava@dubeyko.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ceph/ceph_common.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/net/ceph/ceph_common.c
+++ b/net/ceph/ceph_common.c
@@ -763,13 +763,13 @@ void ceph_destroy_client(struct ceph_cli
atomic_set(&client->msgr.stopping, 1);
+ ceph_debugfs_client_cleanup(client);
+
/* unmount */
ceph_osdc_stop(&client->osdc);
ceph_monc_stop(&client->monc);
ceph_messenger_fini(&client->msgr);
- ceph_debugfs_client_cleanup(client);
-
ceph_destroy_options(client->options);
kfree(client);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 399/602] amt: fix use-after-free in AMT delayed works
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (397 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 398/602] libceph: remove debugfs files before client teardown Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 400/602] ASoC: fsl_sai: Fix spurious BCLK on resume by clearing BYP Greg Kroah-Hartman
` (206 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Shihuang Liu, Simon Horman,
Taehee Yoo, Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shihuang Liu <shlomojune6@gmail.com>
commit ea20c44935d6142daecfa9b39d635033a7553e1b upstream.
When an AMT device is removed, pending delayed works can still access
the freed amt_dev structure, which may result in kernel crashes or
memory corruption.
amt_dev_stop() cancels req_wq and discovery_wq with
cancel_delayed_work_sync(), but these works can be scheduled again
from event_wq after the cancellation. This allows delayed works to
access the freed amt_dev structure after the netdev has been released.
The following is a simple race scenario:
CPU0 CPU1
amt_dev_stop()
cancel_delayed_work_sync()
amt_event_work()
mod_delayed_work(req_wq)
free netdev
req_wq accesses freed amt_dev
Use disable_delayed_work_sync() in amt_dev_stop() to prevent req_wq and
discovery_wq from being queued again and wait for running work items
to complete.
The delayed works are disabled after initialization in
amt_newlink() and enabled only when the device is successfully opened.
This keeps the delayed work lifecycle synchronized with the lifetime
of the AMT device.
Fixes: cbc21dc1cfe9 ("amt: add data plane of amt interface")
Cc: stable@vger.kernel.org
Signed-off-by: Shihuang Liu <shlomojune6@gmail.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Reviewed-by: Taehee Yoo <ap420073@gmail.com>
Link: https://patch.msgid.link/20260722113919.7723-1-shlomojune6@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/amt.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
--- a/drivers/net/amt.c
+++ b/drivers/net/amt.c
@@ -3029,9 +3029,15 @@ static int amt_dev_open(struct net_devic
amt->event_idx = 0;
amt->nr_events = 0;
+ enable_delayed_work(&amt->discovery_wq);
+ enable_delayed_work(&amt->req_wq);
+
err = amt_socket_create(amt);
- if (err)
+ if (err) {
+ disable_delayed_work(&amt->req_wq);
+ disable_delayed_work(&amt->discovery_wq);
return err;
+ }
amt->req_cnt = 0;
amt->remote_ip = 0;
@@ -3057,8 +3063,8 @@ static int amt_dev_stop(struct net_devic
struct sk_buff *skb;
int i;
- cancel_delayed_work_sync(&amt->req_wq);
- cancel_delayed_work_sync(&amt->discovery_wq);
+ disable_delayed_work_sync(&amt->req_wq);
+ disable_delayed_work_sync(&amt->discovery_wq);
cancel_delayed_work_sync(&amt->secret_wq);
/* shutdown */
@@ -3313,6 +3319,8 @@ static int amt_newlink(struct net *net,
INIT_DELAYED_WORK(&amt->req_wq, amt_req_work);
INIT_DELAYED_WORK(&amt->secret_wq, amt_secret_work);
INIT_WORK(&amt->event_wq, amt_event_work);
+ disable_delayed_work(&amt->req_wq);
+ disable_delayed_work(&amt->discovery_wq);
INIT_LIST_HEAD(&amt->tunnel_list);
return 0;
err:
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 400/602] ASoC: fsl_sai: Fix spurious BCLK on resume by clearing BYP
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (398 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 399/602] amt: fix use-after-free in AMT delayed works Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 401/602] binfmt_elf_fdpic: only honour the first PT_INTERP Greg Kroah-Hartman
` (205 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Chancel Liu, Shengjiu Wang,
Mark Brown
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chancel Liu <chancel.liu@nxp.com>
commit d091132889c1378dd0944a72f86eae3e4da1e4fa upstream.
When the BCLK divider ratio is 1:1, fsl_sai_set_bclk() enables bypass
mode by setting BYP, but never clears the bit. The BYP=1 value remains
in the regcache, and is restored by regcache_sync() on the next runtime
resume.
Since BYP=1 combined with BCD=1 immediately outputs the ungated MCLK
as BCLK without waiting for BCE/TE/RE to be enabled, the clock is
driven prematurely before the stream is fully configured, causing
noise on some codecs.
Fix this by clearing BYP and BCI in fsl_sai_hw_free() taking into
account sync mode and the opposite stream's state, so that the regcache
holds BYP=0 before runtime suspend and regcache_sync() on resume will
not restore bypass mode prematurely.
Fixes: a50b7926d015 ("ASoC: fsl_sai: implement 1:1 bclk:mclk ratio support")
Cc: stable@vger.kernel.org
Signed-off-by: Chancel Liu <chancel.liu@nxp.com>
Reviewed-by: Shengjiu Wang <shengjiu.wang@gmail.com>
Link: https://patch.msgid.link/20260710070835.3749817-1-chancel.liu@oss.nxp.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
sound/soc/fsl/fsl_sai.c | 29 +++++++++++++++++++++++++----
1 file changed, 25 insertions(+), 4 deletions(-)
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -725,6 +725,8 @@ static int fsl_sai_hw_free(struct snd_pc
struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
unsigned int ofs = sai->soc_data->reg_offset;
+ int adir = tx ? RX : TX;
+ int dir = tx ? TX : RX;
/* Clear xMR to avoid channel swap with mclk_with_tere enabled case */
regmap_write(sai->regmap, FSL_SAI_xMR(tx), 0);
@@ -732,10 +734,29 @@ static int fsl_sai_hw_free(struct snd_pc
regmap_update_bits(sai->regmap, FSL_SAI_xCR3(tx, ofs),
FSL_SAI_CR3_TRCE_MASK, 0);
- if (!sai->is_consumer_mode[tx] &&
- sai->mclk_streams & BIT(substream->stream)) {
- clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[tx]]);
- sai->mclk_streams &= ~BIT(substream->stream);
+ if (!sai->is_consumer_mode[tx]) {
+ bool adir_active = !!(sai->mclk_streams & BIT(!substream->stream));
+ /*
+ * If opposite stream provides clocks for synchronous mode and
+ * it is inactive, Clear BYP and BCI
+ */
+ if (fsl_sai_dir_is_synced(sai, adir) && !adir_active)
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR2(!tx, ofs),
+ FSL_SAI_CR2_BCI | FSL_SAI_CR2_BYP, 0);
+ /*
+ * Clear BYP and BCI of current stream if either of:
+ * 1. current stream doesn't provide clocks for synchronous mode
+ * 2. current stream provides clocks for synchronous mode but no
+ * more stream is active.
+ */
+ if (!fsl_sai_dir_is_synced(sai, dir) || !adir_active)
+ regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
+ FSL_SAI_CR2_BCI | FSL_SAI_CR2_BYP, 0);
+
+ if (sai->mclk_streams & BIT(substream->stream)) {
+ clk_disable_unprepare(sai->mclk_clk[sai->mclk_id[tx]]);
+ sai->mclk_streams &= ~BIT(substream->stream);
+ }
}
return 0;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 401/602] binfmt_elf_fdpic: only honour the first PT_INTERP
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (399 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 400/602] ASoC: fsl_sai: Fix spurious BCLK on resume by clearing BYP Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 402/602] fs: preserve ACL_DONT_CACHE state in forget_cached_acl() Greg Kroah-Hartman
` (204 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jori Koolstra,
Christian Brauner (Amutable)
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Brauner <brauner@kernel.org>
commit 3349ef6a366a61d631f6a263d12cea240957719d upstream.
The program header scan handles PT_INTERP from a switch nested in the
scan loop, so its break leaves the switch and not the loop. A binary
carrying more than one PT_INTERP runs the case again and overwrites both
interpreter_name and interpreter. The previous name allocation leaks and
so does the previous interpreter reference, along with the write denial
open_exec() took on it. The denial is never released, so the file stays
unwritable for as long as the system runs.
An unprivileged caller reaches this with a crafted binary and repeats it
at will. binfmt_elf stops at the first PT_INTERP. Do the same here.
The flaw dates back to the driver's introduction in the pre-git history
tree introduced in v2.6.11 by 91808d6ebe39 ("[PATCH] FRV: Add FDPIC ELF
binary format driver").
Link: https://patch.msgid.link/20260721-gezittert-medium-kreide-b41fc1f0277e@brauner
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Reviewed-by: Jori Koolstra <jkoolstra@xs4all.nl>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/binfmt_elf_fdpic.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -231,6 +231,10 @@ static int load_elf_fdpic_binary(struct
for (i = 0; i < exec_params.hdr.e_phnum; i++, phdr++) {
switch (phdr->p_type) {
case PT_INTERP:
+ /* elf ABI allows only one interpreter */
+ if (interpreter_name)
+ continue;
+
retval = -ENOMEM;
if (phdr->p_filesz > PATH_MAX)
goto error;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 402/602] fs: preserve ACL_DONT_CACHE state in forget_cached_acl()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (400 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 401/602] binfmt_elf_fdpic: only honour the first PT_INTERP Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 403/602] fscrypt: Add missing superblock check in find_or_insert_direct_key() Greg Kroah-Hartman
` (203 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Amir Goldstein, Luis Henriques,
Christian Brauner (Amutable)
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amir Goldstein <amir73il@gmail.com>
commit 4b9a5458d02e214ef2b384124ca626e3e381d778 upstream.
The ACL_DONT_CACHE state is meant to be a constant state for the inode
for filesystems that want to opt out of posix acl caching.
Commit facd61053cff1 ("fuse: fixes after adapting to new posix acl api")
used this facility to opt out of posix acl caching for fuse inodes with
fuse server that does not negotiate FUSE_POSIX_ACL (fc->posix_acl).
The commit also takes care to gate the forget_all_cached_acls() call in
fuse_set_acl() on fc->posix_acl because there is no need for it, but
there are other placed in fuse code which call forget_all_cached_acls()
unconditional to fc->posix_acl and those cause the loss of the
ACL_DONT_CACHE state.
This is not only a functional bug. Properly timed, a get_acl() from this
fuse filesystem can return a stale cached value, as was observed in tests,
because set_acl() does not invalidate the unintentional acl cache.
We could fix this in fuse, but it actually makes no sense for the vfs
helper forget_cached_acl() to invalidate the ACL_DONT_CACHE state, so
let it not do that to fix fuse and future users of ACL_DONT_CACHE.
Fixes: facd61053cff1 ("fuse: fixes after adapting to new posix acl api")
Cc: stable@vger.kernel.org
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Link: https://patch.msgid.link/20260713220932.413004-2-amir73il@gmail.com
Reviewed-by: Luis Henriques <luis@igalia.com>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/posix_acl.c | 7 +++++++
1 file changed, 7 insertions(+)
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -93,6 +93,13 @@ static void __forget_cached_acl(struct p
{
struct posix_acl *old;
+ /*
+ * ACL_DONT_CACHE is expected to be a "const" value and xchg it with
+ * ACL_NOT_CACHED would enable acl caching for the inode -
+ * clearly not what the caller has intended.
+ */
+ if (READ_ONCE(*p) == ACL_DONT_CACHE)
+ return;
old = xchg(p, ACL_NOT_CACHED);
if (!is_uncached_acl(old))
posix_acl_release(old);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 403/602] fscrypt: Add missing superblock check in find_or_insert_direct_key()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (401 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 402/602] fs: preserve ACL_DONT_CACHE state in forget_cached_acl() Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 404/602] ftrace: Add global mutex to serialize trace_parser access Greg Kroah-Hartman
` (202 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sashiko, Christoph Hellwig,
Eric Biggers
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Biggers <ebiggers@kernel.org>
commit b5fa40226e71c17847b9ff2816c6ca4133d0d994 upstream.
The legacy 'fscrypt_direct_keys' table caches master keys that are used
by v1 encryption policies that have FSCRYPT_POLICY_FLAG_DIRECT_KEY.
It's just a global table for all filesystems (since the keys can be
provided by the legacy process-subscribed keyrings mechanism, which
makes it difficult to reuse super_block::s_master_keys).
The entries in it ('struct fscrypt_direct_key') do contain a super_block
pointer, though, for passing to fscrypt_destroy_inline_crypt_key() when
the last inode that references the key is evicted.
However, when finding the fscrypt_direct_key for an inode, we weren't
actually comparing the super_block pointer. As a result, inodes with
different super_blocks could point to the same fscrypt_direct_key. That
could extend the lifetime of a fscrypt_direct_key beyond the
super_block it points to, causing a use-after-free later.
Fix this by creating distinct fscrypt_direct_key structs for distinct
super_block structs.
Note that this problem doesn't exist in the v2 policy equivalent
("per-mode keys"), since the data structures there are per super_block.
Fixes: 22e9947a4b2b ("fscrypt: stop holding extra request_queue references")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260717044303.425265-1-ebiggers%40kernel.org
Reviewed-by: Christoph Hellwig <hch@lst.de>
Link: https://patch.msgid.link/20260719033120.122120-1-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/crypto/keysetup_v1.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
--- a/fs/crypto/keysetup_v1.c
+++ b/fs/crypto/keysetup_v1.c
@@ -200,13 +200,19 @@ find_or_insert_direct_key(struct fscrypt
if (memcmp(ci->ci_policy.v1.master_key_descriptor,
dk->dk_descriptor, FSCRYPT_KEY_DESCRIPTOR_SIZE) != 0)
continue;
+ /* The sb is used at eviction time, so it must be the same. */
+ if (ci->ci_inode->i_sb != dk->dk_sb)
+ continue;
if (ci->ci_mode != dk->dk_mode)
continue;
if (!fscrypt_is_key_prepared(&dk->dk_key, ci))
continue;
if (crypto_memneq(raw_key, dk->dk_raw, ci->ci_mode->keysize))
continue;
- /* using existing tfm with same (descriptor, mode, raw_key) */
+ /*
+ * Use an existing prepared key with the same (descriptor, sb,
+ * mode, inlinecrypt, raw_key) combination.
+ */
refcount_inc(&dk->dk_refcount);
spin_unlock(&fscrypt_direct_keys_lock);
free_direct_key(to_insert);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 404/602] ftrace: Add global mutex to serialize trace_parser access
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (402 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 403/602] fscrypt: Add missing superblock check in find_or_insert_direct_key() Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 405/602] iomap: fix out-of-bounds bitmap_set() with zero-length range Greg Kroah-Hartman
` (201 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Tengda Wu, Steven Rostedt
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tengda Wu <wutengda@huaweicloud.com>
commit 7720b63bcef3f54c7fe288774b720a227d54a306 upstream.
In ftrace, the trace_parser structure is allocated and initialized when
a trace file is opened, and is subsequently used across write and release
handlers to parse user input.
The affected handler paths and their specific functions are:
- Open paths: ftrace_regex_open(), ftrace_graph_open()
- Write paths: ftrace_regex_write(), ftrace_graph_write()
- Release paths: ftrace_regex_release(), ftrace_graph_release()
If userspace opens a trace file descriptor and shares it across multiple
threads, concurrent write calls will race on the parser's internal state,
specifically the 'idx', 'cont', and 'buffer' fields, leading to corrupted
input or undefined behavior.
Fix this by adding a global mutex, parser_lock, to serialize all access
to trace_parser across write and release paths, preventing concurrent
corruption of parser state.
Fixes: e704eff3ff51 ("ftrace: Have set_graph_function handle multiple functions in one write")
Fixes: 689fd8b65d66 ("tracing: trace parser support for function and graph")
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260725024721.1983675-1-wutengda@huaweicloud.com
Signed-off-by: Tengda Wu <wutengda@huaweicloud.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
kernel/trace/ftrace.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -1073,6 +1073,12 @@ struct ftrace_ops global_ops = {
};
/*
+ * parser_lock - Protects trace_parser state against concurrent operations.
+ * Held across trace_get_user() and subsequent buffer parsing to prevent races.
+ */
+static DEFINE_MUTEX(parser_lock);
+
+/*
* Used by the stack unwinder to know about dynamic ftrace trampolines.
*/
struct ftrace_ops *ftrace_ops_trampoline(unsigned long addr)
@@ -5730,6 +5736,8 @@ ftrace_regex_write(struct file *file, co
/* iter->hash is a local copy, so we don't need regex_lock */
parser = &iter->parser;
+
+ guard(mutex)(&parser_lock);
read = trace_get_user(parser, ubuf, cnt, ppos);
if (read >= 0 && trace_parser_loaded(parser) &&
@@ -6453,12 +6461,14 @@ int ftrace_regex_release(struct inode *i
iter = file->private_data;
parser = &iter->parser;
+ mutex_lock(&parser_lock);
if (trace_parser_loaded(parser)) {
int enable = !(iter->flags & FTRACE_ITER_NOTRACE);
ftrace_process_regex(iter, parser->buffer,
parser->idx, enable);
}
+ mutex_unlock(&parser_lock);
trace_parser_put(parser);
@@ -6790,10 +6800,12 @@ ftrace_graph_release(struct inode *inode
parser = &fgd->parser;
+ mutex_lock(&parser_lock);
if (trace_parser_loaded((parser))) {
ret = ftrace_graph_set_hash(fgd->new_hash,
parser->buffer);
}
+ mutex_unlock(&parser_lock);
trace_parser_put(parser);
@@ -6913,6 +6925,7 @@ ftrace_graph_write(struct file *file, co
parser = &fgd->parser;
+ guard(mutex)(&parser_lock);
read = trace_get_user(parser, ubuf, cnt, ppos);
if (read >= 0 && trace_parser_loaded(parser) &&
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 405/602] iomap: fix out-of-bounds bitmap_set() with zero-length range
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (403 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 404/602] ftrace: Add global mutex to serialize trace_parser access Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 406/602] iommu/vt-d: Disallow SVA if page walk is not coherent Greg Kroah-Hartman
` (200 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Zhang Yi, Joanne Koong,
Darrick J. Wong, Christoph Hellwig, Christian Brauner (Amutable)
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Yi <yi.zhang@huawei.com>
commit 9c7d8f7c8994c790fca501dc45ce66e7356cbe05 upstream.
ifs_set_range_dirty() and ifs_set_range_uptodate() compute last_blk
as (off + len - 1) >> i_blkbits. When off is 0 and len is 0, the
unsigned subtraction underflows to SIZE_MAX, producing a huge
last_blk and nr_blks value that causes bitmap_set() to write far
beyond the ifs->state allocation.
Regarding ifs_set_range_uptodate(), it is temporarily safe because len
cannot be passed in as 0. However, for ifs_set_range_dirty() this is
reachable from __iomap_write_end(): when copy_folio_from_iter_atomic()
returns 0 (e.g. user buffer fault) and the folio is already uptodate,
the guard at the top of __iomap_write_end() does not trigger because
!folio_test_uptodate() is false, and iomap_set_range_dirty() is called
with copied == 0.
Add a !len guard to both functions before the computation, so that a
zero-length range is a no-op.
Fixes: 4ce02c679722 ("iomap: Add per-block dirty state tracking to improve performance")
Cc: stable@vger.kernel.org # v6.6
Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
Link: https://patch.msgid.link/20260714082325.325163-5-yi.zhang@huaweicloud.com
Reviewed-by: Joanne Koong <joannelkoong@gmail.com>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/iomap/buffered-io.c | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -60,11 +60,13 @@ static bool ifs_set_range_uptodate(struc
struct iomap_folio_state *ifs, size_t off, size_t len)
{
struct inode *inode = folio->mapping->host;
- unsigned int first_blk = off >> inode->i_blkbits;
- unsigned int last_blk = (off + len - 1) >> inode->i_blkbits;
- unsigned int nr_blks = last_blk - first_blk + 1;
+ unsigned int first_blk, last_blk;
- bitmap_set(ifs->state, first_blk, nr_blks);
+ if (len) {
+ first_blk = off >> inode->i_blkbits;
+ last_blk = (off + len - 1) >> inode->i_blkbits;
+ bitmap_set(ifs->state, first_blk, last_blk - first_blk + 1);
+ }
return ifs_is_fully_uptodate(folio, ifs);
}
@@ -164,13 +166,17 @@ static void ifs_set_range_dirty(struct f
{
struct inode *inode = folio->mapping->host;
unsigned int blks_per_folio = i_blocks_per_folio(inode, folio);
- unsigned int first_blk = (off >> inode->i_blkbits);
- unsigned int last_blk = (off + len - 1) >> inode->i_blkbits;
- unsigned int nr_blks = last_blk - first_blk + 1;
+ unsigned int first_blk, last_blk;
unsigned long flags;
+ if (!len)
+ return;
+
+ first_blk = off >> inode->i_blkbits;
+ last_blk = (off + len - 1) >> inode->i_blkbits;
spin_lock_irqsave(&ifs->state_lock, flags);
- bitmap_set(ifs->state, first_blk + blks_per_folio, nr_blks);
+ bitmap_set(ifs->state, first_blk + blks_per_folio,
+ last_blk - first_blk + 1);
spin_unlock_irqrestore(&ifs->state_lock, flags);
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 406/602] iommu/vt-d: Disallow SVA if page walk is not coherent
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (404 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 405/602] iomap: fix out-of-bounds bitmap_set() with zero-length range Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 407/602] phonet: pep: fix use-after-free in pep_get_sb() Greg Kroah-Hartman
` (199 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Lu Baolu, Kevin Tian,
Samiullah Khawaja, Jason Gunthorpe, Will Deacon
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lu Baolu <baolu.lu@linux.intel.com>
commit 780dfed688622ea01be3c9c2c55eec2207f05e04 upstream.
Hardware implementations report Scalable-Mode Page-walk Coherency Support
via the SMPWCS field in the extended capability register. If the hardware
does not support page-walk coherency, a clflush is required every time
the page table entries (which are walked by the IOMMU hardware) are
updated.
In the SVA case, page tables are managed by the CPU mm core, not by the
IOMMU driver. Because the IOMMU driver has no way of knowing whether the
CPU page table management code has ensured coherency via clflush, the
driver must deny SVA if the hardware does not support coherent paging.
Fixes: ff3dc6521f78 ("iommu/vt-d: Fix CPU and IOMMU SVM feature matching checks")
Cc: stable@vger.kernel.org
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Samiullah Khawaja <skhawaja@google.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/iommu/intel/svm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/iommu/intel/svm.c
+++ b/drivers/iommu/intel/svm.c
@@ -27,7 +27,7 @@
void intel_svm_check(struct intel_iommu *iommu)
{
- if (!pasid_supported(iommu))
+ if (!pasid_supported(iommu) || !ecap_smpwc(iommu->ecap))
return;
if (cpu_feature_enabled(X86_FEATURE_GBPAGES) &&
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 407/602] phonet: pep: fix use-after-free in pep_get_sb()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (405 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 406/602] iommu/vt-d: Disallow SVA if page walk is not coherent Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 408/602] vxlan: require CAP_NET_ADMIN in the device netns for changelink Greg Kroah-Hartman
` (198 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Breno Leitao, Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Breno Leitao <leitao@debian.org>
commit 0f71f852a96af9685858ce59fda34ecbf85c283d upstream.
pep_get_sb() doesn't consider that pskb_may_pull() might have relocated
the skb data, and continue to access the older pointer, causing UAF.
Reproduced under KASAN:
BUG: KASAN: slab-use-after-free in pep_get_sb+0x234/0x3b0
Read of size 1 at addr ff11000105510f50 by task repro/157
pep_get_sb+0x234/0x3b0
pipe_handler_do_rcv+0x5f7/0xa10
pep_do_rcv+0x203/0x410
__sk_receive_skb+0x471/0x4a0
phonet_rcv+0x5b3/0x6c0
__netif_receive_skb+0xcc/0x1d0
Refetch the header with skb_header_pointer() after pskb_may_pull(), so
the possibly stale pointer is no longer dereferenced. There are better
ways to solve this, but, this is the less instrusive one.
Fixes: 9641458d3ec4 ("Phonet: Pipe End Point for Phonet Pipes protocol")
Cc: stable@vger.kernel.org
Signed-off-by: Breno Leitao <leitao@debian.org>
Link: https://patch.msgid.link/20260721-phonet_get_sb_uaf-v1-1-95fd7881cc4e@debian.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/phonet/pep.c | 2 ++
1 file changed, 2 insertions(+)
--- a/net/phonet/pep.c
+++ b/net/phonet/pep.c
@@ -55,6 +55,8 @@ static unsigned char *pep_get_sb(struct
ph = skb_header_pointer(skb, 0, 2, &h);
if (ph == NULL || ph->sb_len < 2 || !pskb_may_pull(skb, ph->sb_len))
return NULL;
+ /* pskb_may_pull() may have reallocated the head; refetch ph. */
+ ph = skb_header_pointer(skb, 0, 2, &h);
ph->sb_len -= 2;
*ptype = ph->sb_type;
*plen = ph->sb_len;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 408/602] vxlan: require CAP_NET_ADMIN in the device netns for changelink
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (406 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 407/602] phonet: pep: fix use-after-free in pep_get_sb() Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 409/602] net: slip: serialize receive against buffer reallocation Greg Kroah-Hartman
` (197 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Doruk Tan Ozturk,
Fernando Fernandez Mancera, Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Doruk Tan Ozturk <doruk@0sec.ai>
commit 3a61bd9637f3d929aa846e4eb3d98b48c26fcb0e upstream.
A tunnel changelink() operates on at most two netns, dev_net(dev) and
the sticky underlay netns vxlan->net. They differ once the device is
created in or moved to a netns other than the one the request runs in.
The rtnl changelink path checks CAP_NET_ADMIN only against dev_net(dev),
so a caller privileged there but not in vxlan->net can rewrite a vxlan
device whose underlay lives in vxlan->net.
vxlan_changelink() validates and applies the new configuration against
vxlan->net (vxlan_config_validate(vxlan->net, ...)) and can reopen the
underlay socket in that netns, so the same reasoning as the tunnel
changelink series applies here.
Gate vxlan_changelink() with rtnl_dev_link_net_capable(), at the top of
the op before any attribute is parsed, matching ipgre_changelink() and
the rest of the "require CAP_NET_ADMIN in the device netns for
changelink" series.
Found by 0sec automated security-research tooling (https://0sec.ai).
Fixes: 8bcdc4f3a20b ("vxlan: add changelink support")
Cc: stable@vger.kernel.org
Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
Link: https://patch.msgid.link/20260716203500.70573-2-doruk@0sec.ai
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/vxlan/vxlan_core.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -4381,6 +4381,9 @@ static int vxlan_changelink(struct net_d
struct vxlan_rdst *dst;
int err;
+ if (!rtnl_dev_link_net_capable(dev, vxlan->net))
+ return -EPERM;
+
dst = &vxlan->default_dst;
err = vxlan_nl2conf(tb, data, dev, &conf, true, extack);
if (err)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 409/602] net: slip: serialize receive against buffer reallocation
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (407 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 408/602] vxlan: require CAP_NET_ADMIN in the device netns for changelink Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 410/602] geneve: require CAP_NET_ADMIN in the device netns for changelink Greg Kroah-Hartman
` (196 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Sungmin Kang, Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sungmin Kang <726ksm@gmail.com>
commit ee7f9bb9320add61f7b367d7e6cd55e3a3a4d65d upstream.
sl_realloc_bufs() replaces rbuff and updates buffsize while holding
sl->lock. slip_receive_buf() reads those fields and writes through rbuff
without holding the lock.
An MTU change can therefore race with receive processing. An MTU shrink
can expose the new smaller rbuff with the old larger bound, causing an
out-of-bounds write. A receive callback which already loaded the old
rbuff can instead continue writing after that buffer has been freed.
Serialize receive processing with sl_realloc_bufs() by holding sl->lock
while consuming each receive batch.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Sungmin Kang <726ksm@gmail.com>
Link: https://patch.msgid.link/20260718073631.1674-1-726ksm@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/slip/slip.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/drivers/net/slip/slip.c
+++ b/drivers/net/slip/slip.c
@@ -693,6 +693,8 @@ static void slip_receive_buf(struct tty_
if (!sl || sl->magic != SLIP_MAGIC || !netif_running(sl->dev))
return;
+ spin_lock_bh(&sl->lock);
+
/* Read the characters out of the buffer */
while (count--) {
if (fp && *fp++) {
@@ -708,6 +710,8 @@ static void slip_receive_buf(struct tty_
#endif
slip_unesc(sl, *cp++);
}
+
+ spin_unlock_bh(&sl->lock);
}
/************************************
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 410/602] geneve: require CAP_NET_ADMIN in the device netns for changelink
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (408 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 409/602] net: slip: serialize receive against buffer reallocation Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 411/602] net/af_iucv: fix NULL deref in afiucv_hs_callback_syn() Greg Kroah-Hartman
` (195 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Doruk Tan Ozturk,
Fernando Fernandez Mancera, Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Doruk Tan Ozturk <doruk@0sec.ai>
commit 8efb8f8bbb353b8f2fdf4f37534c6d96c9f69e01 upstream.
A tunnel changelink() operates on at most two netns, dev_net(dev) and
the sticky underlay netns geneve->net. They differ once the device is
created in or moved to a netns other than the one the request runs in.
The rtnl changelink path checks CAP_NET_ADMIN only against dev_net(dev),
so a caller privileged there but not in geneve->net can rewrite a geneve
device whose underlay lives in geneve->net.
geneve_changelink() applies the new configuration against geneve->net:
geneve_link_config() and the geneve_quiesce()/geneve_unquiesce() pair
reopen the underlay sockets in that netns (geneve_sock_add() uses
geneve->net), so the same reasoning as the tunnel changelink series
applies here.
Gate geneve_changelink() with rtnl_dev_link_net_capable(), at the top of
the op before any attribute is parsed, matching ipgre_changelink() and
the rest of the "require CAP_NET_ADMIN in the device netns for
changelink" series.
Found by 0sec automated security-research tooling (https://0sec.ai).
Fixes: 5b861f6baa3a ("geneve: add rtnl changelink support")
Cc: stable@vger.kernel.org
Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
Reviewed-by: Fernando Fernandez Mancera <fmancera@suse.de>
Link: https://patch.msgid.link/20260716203500.70573-3-doruk@0sec.ai
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/geneve.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -1694,6 +1694,9 @@ static int geneve_changelink(struct net_
struct geneve_config cfg;
int err;
+ if (!rtnl_dev_link_net_capable(dev, geneve->net))
+ return -EPERM;
+
/* If the geneve device is configured for metadata (or externally
* controlled, for example, OVS), then nothing can be changed.
*/
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 411/602] net/af_iucv: fix NULL deref in afiucv_hs_callback_syn()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (409 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 410/602] geneve: require CAP_NET_ADMIN in the device netns for changelink Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 412/602] net/iucv: fix use-after-free of a severed iucv_path Greg Kroah-Hartman
` (194 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Alexandra Winter, Hidayath Khan,
Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hidayath Khan <hidayath@linux.ibm.com>
commit 47a5116e56a6b6fe1e909f244e39cd0fc26ceee4 upstream.
afiucv_hs_callback_syn() allocates the child socket with GFP_ATOMIC.
If the allocation fails, nsk is NULL.
The connection-refused path is entered when the listen state check
fails, the accept backlog is full, or nsk is NULL. The code
unconditionally calls iucv_sock_kill(nsk) in that path.
iucv_sock_kill() does not accept a NULL socket pointer and immediately
dereferences sk via sock_flag(sk, SOCK_ZAPPED). When nsk is NULL,
calling iucv_sock_kill(nsk) results in a NULL pointer dereference.
Only call iucv_sock_kill() when a child socket was successfully
allocated.
Fixes: 3881ac441f64 ("af_iucv: add HiperSockets transport")
Cc: stable@vger.kernel.org
Reviewed-by: Alexandra Winter <wintera@linux.ibm.com>
Signed-off-by: Hidayath Khan <hidayath@linux.ibm.com>
Link: https://patch.msgid.link/20260709191732.124092-1-hidayath@linux.ibm.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/iucv/af_iucv.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -1871,7 +1871,8 @@ static int afiucv_hs_callback_syn(struct
afiucv_swap_src_dest(skb);
trans_hdr->flags = AF_IUCV_FLAG_SYN | AF_IUCV_FLAG_FIN;
err = dev_queue_xmit(skb);
- iucv_sock_kill(nsk);
+ if (nsk)
+ iucv_sock_kill(nsk);
bh_unlock_sock(sk);
goto out;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 412/602] net/iucv: fix use-after-free of a severed iucv_path
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (410 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 411/602] net/af_iucv: fix NULL deref in afiucv_hs_callback_syn() Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 413/602] net/mlx5e: Use sender devcom for MPV master-up Greg Kroah-Hartman
` (193 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Bryam Vargas, Paolo Abeni
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <hexlabsecurity@proton.me>
commit be7cc4656eb1f54029610e82d1f0fdd3f9b5ec0a upstream.
af_iucv queues not-yet-received message notifications on iucv->message_q,
each holding a raw pointer to the connection's iucv_path. When the peer
severs the connection, iucv_sever_path() frees that path with
iucv_path_free() but leaves the notifications queued. A later recvmsg()
drains message_q via iucv_process_message_q() and hands the stale path to
message_receive() -- a use-after-free of the freed iucv_path.
Drop the queued notifications when the path is severed; once the path is
gone they can no longer be received. This also frees the notifications
leaked when a socket is closed with messages still queued.
Fixes: f0703c80e515 ("[AF_IUCV]: postpone receival of iucv-packets")
Closes: https://sashiko.dev/#/patchset/20260705-b4-disp-fc79c0dc-v1-1-d2cdcb57afa9@proton.me?part=1
Cc: stable@vger.kernel.org
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
Link: https://patch.msgid.link/20260707-b4-disp-783fedbb-v1-1-463b9dbda2ea@proton.me
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/iucv/af_iucv.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -334,6 +334,7 @@ static void iucv_sever_path(struct sock
unsigned char user_data[16];
struct iucv_sock *iucv = iucv_sk(sk);
struct iucv_path *path = iucv->path;
+ struct sock_msg_q *p, *n;
/* Whoever resets the path pointer, must sever and free it. */
if (xchg(&iucv->path, NULL)) {
@@ -345,6 +346,19 @@ static void iucv_sever_path(struct sock
} else
pr_iucv->path_sever(path, NULL);
iucv_path_free(path);
+
+ /*
+ * Message notifications queued on message_q still reference
+ * the now freed path; drop them, otherwise a later recvmsg()
+ * would pass the freed iucv_path to message_receive() via
+ * iucv_process_message_q().
+ */
+ spin_lock_bh(&iucv->message_q.lock);
+ list_for_each_entry_safe(p, n, &iucv->message_q.list, list) {
+ list_del(&p->list);
+ kfree(p);
+ }
+ spin_unlock_bh(&iucv->message_q.lock);
}
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 413/602] net/mlx5e: Use sender devcom for MPV master-up
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (411 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 412/602] net/iucv: fix use-after-free of a severed iucv_path Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 414/602] net/x25: fix use-after-free in x25_kill_by_neigh() Greg Kroah-Hartman
` (192 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Manjunath Patil, Tariq Toukan,
Paolo Abeni
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Manjunath Patil <manjunath.b.patil@oracle.com>
commit e32649b4bad90a6216d8e93cd7dd050af8ac9740 upstream.
After PCIe DPC recovery, mlx5 reloads the affected functions and
replays multiport affiliation events. In the reported failure, the
first relevant device error was:
pcieport 0000:10:01.1: DPC: containment event
pcieport 0000:10:01.1: PCIe Bus Error: severity=Uncorrected (Fatal)
pcieport 0000:10:01.1: [ 5] SDES (First)
mlx5 recovered the PCI functions and resumed 0000:11:00.1. During
that resume, RDMA multiport binding replayed
MLX5_DRIVER_EVENT_AFFILIATION_DONE and mlx5e sent
MPV_DEVCOM_MASTER_UP. The host then panicked with:
BUG: kernel NULL pointer dereference, address: 0000000000000010
RIP: mlx5_devcom_comp_set_ready+0x5/0x40 [mlx5_core]
RDI: 0000000000000000
Call trace included:
mlx5_devcom_comp_set_ready
mlx5e_devcom_event_mpv
mlx5_devcom_send_event
mlx5_ib_bind_slave_port
mlx5r_mp_probe
mlx5_pci_resume
MPV devcom registration publishes mlx5e private data to the component
peer list before mlx5e_devcom_init_mpv() stores the returned component
device in priv->devcom. A concurrent master-up event can therefore
reach a peer whose private data is visible but whose priv->devcom
backpointer is still NULL.
MPV_DEVCOM_MASTER_UP already carries the sender/master mlx5e private
data as event_data. The ready bit is stored on the shared devcom
component, not on an individual peer. Use the sender devcom when
marking the MPV component ready.
This preserves the readiness transition while avoiding a NULL
dereference of the peer devcom pointer during affiliation replay after
PCI error recovery.
Fixes: bf11485f8419 ("net/mlx5: Register mlx5e priv to devcom in MPV mode")
Assisted-by: Codex:gpt-5
Signed-off-by: Manjunath Patil <manjunath.b.patil@oracle.com>
Cc: stable@vger.kernel.org # 6.7+
Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260707233911.3651139-1-manjunath.b.patil@oracle.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -206,11 +206,11 @@ static void mlx5e_disable_async_events(s
static int mlx5e_devcom_event_mpv(int event, void *my_data, void *event_data)
{
- struct mlx5e_priv *slave_priv = my_data;
+ struct mlx5e_priv *master_priv = event_data;
switch (event) {
case MPV_DEVCOM_MASTER_UP:
- mlx5_devcom_comp_set_ready(slave_priv->devcom, true);
+ mlx5_devcom_comp_set_ready(master_priv->devcom, true);
break;
case MPV_DEVCOM_MASTER_DOWN:
/* no need for comp set ready false since we unregister after
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 414/602] net/x25: fix use-after-free in x25_kill_by_neigh()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (412 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 413/602] net/mlx5e: Use sender devcom for MPV master-up Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 415/602] net: gro: fix double aggregation of flush-marked skbs Greg Kroah-Hartman
` (191 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, David Lee, Martin Schiller,
Paolo Abeni
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Lee <david.lee@trailofbits.com>
commit 5499e0602d2faafd42c580d25f615903c3fbe11b upstream.
x25_kill_by_neigh() walks the global X.25 socket list looking for sockets
attached to a terminating neighbour. x25_list_lock protects list membership
while the lookup is in progress, but it does not pin a socket's lifetime
after the lock is dropped.
The function currently drops x25_list_lock before calling lock_sock(s). A
concurrent close can run x25_release(), remove the same socket from
x25_list, and drop the last socket reference in that window. The neighbour
teardown path can then lock or inspect a freed struct sock/struct x25_sock.
Take sock_hold(s) while x25_list_lock still proves that the list entry is
live, then drop the temporary reference after the socket has been locked,
rechecked, and released. Recheck x25_sk(s)->neighbour after lock_sock(),
because another path may have disconnected the socket before this path
acquired the socket lock. Restart the list walk after each disconnect
because the list lock was dropped and the previous iterator state may no
longer be valid.
A QEMU/KASAN run against origin/master reproduced a slab-use-after-free in
x25_kill_by_neigh().
Fixes: 7781607938c8 ("net/x25: Fix null-ptr-deref caused by x25_disconnect")
Cc: stable@vger.kernel.org
Signed-off-by: David Lee <david.lee@trailofbits.com>
Assisted-by: Codex:gpt-5.5
Acked-by: Martin Schiller <ms@dev.tdt.de>
Link: https://patch.msgid.link/20260713104752.241175-1-david.lee@trailofbits.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/x25/af_x25.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -1772,15 +1772,19 @@ void x25_kill_by_neigh(struct x25_neigh
{
struct sock *s;
+again:
write_lock_bh(&x25_list_lock);
sk_for_each(s, &x25_list) {
if (x25_sk(s)->neighbour == nb) {
+ sock_hold(s);
write_unlock_bh(&x25_list_lock);
lock_sock(s);
- x25_disconnect(s, ENETUNREACH, 0, 0);
+ if (x25_sk(s)->neighbour == nb)
+ x25_disconnect(s, ENETUNREACH, 0, 0);
release_sock(s);
- write_lock_bh(&x25_list_lock);
+ sock_put(s);
+ goto again;
}
}
write_unlock_bh(&x25_list_lock);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 415/602] net: gro: fix double aggregation of flush-marked skbs
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (413 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 414/602] net/x25: fix use-after-free in x25_kill_by_neigh() Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 416/602] net: hip04: fix RX buffer leak on build_skb failure Greg Kroah-Hartman
` (190 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Shiming Cheng, Willem de Bruijn,
Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shiming Cheng <shiming.cheng@mediatek.com>
commit e751256486d0ded20f5a9f9863467f1dce65142f upstream.
Commit 0ab03f353d36 ("net-gro: Fix GRO flush when receiving a GSO
packet.") added a flush check to skb_gro_receive(), but
skb_gro_receive_list() lacks the same validation.
As a result, packets marked with NAPI_GRO_CB(skb)->flush may still be
re-aggregated.
This allows already-GRO'd packets with existing frag_list to be
re-aggregated into a new GRO session, corrupting the frag_list chain
structure. When skb_segment() attempts to unpack these malformed packets,
it encounters invalid state and triggers a kernel panic.
Scenario (Tethering/Device forwarding):
1. Driver: Generated aggregated packet P1 via LRO with frag_list
2. Dev A: Receives aggregated fraglist packet and flush flag set
3. Dev A: Re-enters GRO, skb_gro_receive_list() is called
4. Missing flush check allows re-aggregation despite flush flag
5. Frag_list chain becomes corrupted (loops or dangling refs)
6. Dev B: TX path calls skb_segment(), crashes on corrupted frag_list
Root cause in skb_segment():
The check at line ~4891:
if (hsize <= 0 && i >= nfrags && skb_headlen(list_skb) &&
(skb_headlen(list_skb) == len || sg)) {
When frag_list is corrupted by double aggregation, when list_skb is
a NULL pointer from skb->next, skb_headlen(list_skb) dereference
NULL/corrupted pointers occurs.
Call Trace:
skb_headlen(NULL skb)
skb_segment
tcp_gso_segment
tcp4_gso_segment
inet_gso_segment
skb_mac_gso_segment
__skb_gso_segment
skb_gso_segment
validate_xmit_skb
validate_xmit_skb_list
sch_direct_xmit
qdisc_restart
__qdisc_run
qdisc_run
net_tx_action
Fix: Add NAPI_GRO_CB(skb)->flush validation to the early-return check in
skb_gro_receive_list(), matching the defensive programming pattern of
skb_gro_receive().
Fixes: 3a1296a38d0c ("net: Support GRO/GSO fraglist chaining.")
Cc: stable@vger.kernel.org
Signed-off-by: Shiming Cheng <shiming.cheng@mediatek.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20260709014704.3625-1-shiming.cheng@mediatek.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/core/gro.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/net/core/gro.c
+++ b/net/core/gro.c
@@ -230,7 +230,9 @@ done:
int skb_gro_receive_list(struct sk_buff *p, struct sk_buff *skb)
{
- if (unlikely(p->len + skb->len >= 65536))
+ /* make sure to check flush flag and to not merge */
+ if (unlikely(p->len + skb->len >= 65536 ||
+ NAPI_GRO_CB(skb)->flush))
return -E2BIG;
if (!pskb_may_pull(skb, skb_gro_offset(skb))) {
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 416/602] net: hip04: fix RX buffer leak on build_skb failure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (414 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 415/602] net: gro: fix double aggregation of flush-marked skbs Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 417/602] proc: Fix broken error paths for namespace links Greg Kroah-Hartman
` (189 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Fan Wu, Jacob Keller, Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fan Wu <fanwu01@zju.edu.cn>
commit 14fa65d10f5696b063a7d8d26e8291ea84a2c6ed upstream.
When build_skb() fails in hip04_rx_poll(), the driver jumps to the
refill path without releasing the current RX buffer and its DMA mapping.
Installing a replacement buffer then overwrites the slot references and
leaks both resources.
Keep the current slot intact and return budget so NAPI retries the same
buffer. Also free a newly allocated RX fragment when dma_map_single()
fails.
This issue was found by an in-house static analysis tool.
Fixes: 701a0fd52318 ("hip04_eth: fix missing error handle for build_skb failed")
Cc: stable@vger.kernel.org
Signed-off-by: Fan Wu <fanwu01@zju.edu.cn>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Link: https://patch.msgid.link/20260712142729.2057636-1-fanwu01@zju.edu.cn
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/hisilicon/hip04_eth.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
--- a/drivers/net/ethernet/hisilicon/hip04_eth.c
+++ b/drivers/net/ethernet/hisilicon/hip04_eth.c
@@ -594,7 +594,11 @@ static int hip04_rx_poll(struct napi_str
skb = build_skb(buf, priv->rx_buf_size);
if (unlikely(!skb)) {
net_dbg_ratelimited("build_skb failed\n");
- goto refill;
+ /* Retain the slot; return budget so NAPI retries this
+ * buffer. Refill would overwrite rx_buf[]/rx_phys[]
+ * and leak them.
+ */
+ return budget;
}
dma_unmap_single(priv->dev, priv->rx_phys[priv->rx_head],
@@ -622,14 +626,15 @@ static int hip04_rx_poll(struct napi_str
rx++;
}
-refill:
buf = netdev_alloc_frag(priv->rx_buf_size);
if (!buf)
goto done;
phys = dma_map_single(priv->dev, buf,
RX_BUF_SIZE, DMA_FROM_DEVICE);
- if (dma_mapping_error(priv->dev, phys))
+ if (dma_mapping_error(priv->dev, phys)) {
+ skb_free_frag(buf);
goto done;
+ }
priv->rx_buf[priv->rx_head] = buf;
priv->rx_phys[priv->rx_head] = phys;
hip04_set_recv_desc(priv, phys);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 417/602] proc: Fix broken error paths for namespace links
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (415 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 416/602] net: hip04: fix RX buffer leak on build_skb failure Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 418/602] ice: fix PTP Call Trace during PTP release Greg Kroah-Hartman
` (188 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Magnus Lindholm, Jann Horn,
Christian Brauner (Amutable)
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jann Horn <jannh@google.com>
commit 425224c2d700391729be7fe6929a88ef4e2d7a4e upstream.
Don't return the return value of down_read_killable() (0) when a ptrace
access check fails, return -EACCES as intended.
Reported-by: Magnus Lindholm <linmag7@gmail.com>
Closes: https://lore.kernel.org/r/20260706170735.2941493-1-linmag7@gmail.com
Fixes: 6650527444da ("proc: protect ptrace_may_access() with exec_update_lock (part 1)")
Cc: stable@vger.kernel.org
Signed-off-by: Jann Horn <jannh@google.com>
Link: https://patch.msgid.link/20260706-procfs-ns-eacces-fix-v1-1-a69ab14c02e6@google.com
Tested-by: Magnus Lindholm <linmag7@gmail.com>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/proc/namespaces.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/fs/proc/namespaces.c
+++ b/fs/proc/namespaces.c
@@ -46,7 +46,7 @@ static const char *proc_ns_get_link(stru
const struct proc_ns_operations *ns_ops = PROC_I(inode)->ns_ops;
struct task_struct *task;
struct path ns_path;
- int error = -EACCES;
+ int error;
if (!dentry)
return ERR_PTR(-ECHILD);
@@ -59,6 +59,7 @@ static const char *proc_ns_get_link(stru
if (error)
goto out_put_task;
+ error = -EACCES;
if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
goto out;
@@ -90,6 +91,7 @@ static int proc_ns_readlink(struct dentr
if (res)
goto out_put_task;
+ res = -EACCES;
if (ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) {
res = ns_get_name(name, sizeof(name), task, ns_ops);
if (res >= 0)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 418/602] ice: fix PTP Call Trace during PTP release
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (416 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 417/602] proc: Fix broken error paths for namespace links Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 419/602] selftests/ftrace: Reset triggers at top level before instance loop Greg Kroah-Hartman
` (187 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Paul Greenwalt, Aleksandr Loktionov,
Simon Horman, Tony Nguyen, Jakub Kicinski, Rinitha S
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul Greenwalt <paul.greenwalt@intel.com>
commit f6a7e00b81e35ef1325234925f2fe1e53b466f92 upstream.
If a PF reset occurs when the PTP state is ICE_PTP_UNINIT, then
ice_ptp_rebuild() will update the state to ICE_PTP_ERROR. This will
result in the following PTP release call trace during driver unload:
kernel BUG at lib/list_debug.c:52!
ice_ptp_release+0x332/0x3c0 [ice]
ice_deinit_features.part.0+0x10e/0x120 [ice]
ice_remove+0x100/0x220 [ice]
This was observed when passing PF1 through to a VM. ice_ptp_init()
fails because ctrl_pf is NULL and sets the state to ICE_PTP_UNINIT.
Fix by detecting the ICE_PTP_UNINIT state in ice_ptp_rebuild() and
returning without error, preventing the invalid state transition to
ICE_PTP_ERROR. The only valid path to ICE_PTP_ERROR is from
ICE_PTP_RESETTING after a failed rebuild.
Fixes: 8293e4cb2ff5 ("ice: introduce PTP state machine")
Cc: stable@vger.kernel.org
Signed-off-by: Paul Greenwalt <paul.greenwalt@intel.com>
Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Tested-by: Rinitha S <sx.rinitha@intel.com> (A Contingent worker at Intel)
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Link: https://patch.msgid.link/20260717185340.3595286-10-anthony.l.nguyen@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/intel/ice/ice_ptp.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -2886,6 +2886,11 @@ void ice_ptp_rebuild(struct ice_pf *pf,
struct ice_ptp *ptp = &pf->ptp;
int err;
+ if (ptp->state == ICE_PTP_UNINIT) {
+ dev_dbg(ice_pf_to_dev(pf), "PTP was not initialized, skipping rebuild\n");
+ return;
+ }
+
if (ptp->state == ICE_PTP_READY) {
ice_ptp_prepare_for_reset(pf, reset_type);
} else if (ptp->state != ICE_PTP_RESETTING) {
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 419/602] selftests/ftrace: Reset triggers at top level before instance loop
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (417 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 418/602] ice: fix PTP Call Trace during PTP release Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 420/602] rbd: Reset positive result codes to zero in object map update path Greg Kroah-Hartman
` (186 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Masami Hiramatsu (Google),
Steven Rostedt
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
commit 1a087033a6bad73b4140020b40e819b0933aafc3 upstream.
When running instance tests, 'ftracetest' creates a new ftrace instance
and runs the tests inside it. Before starting each test, it executes
'initialize_system()' to reset the ftrace state to initial-state.
However, since 'initialize_system()' is executed in the context of the
instance directory, it only cleans up triggers and filters of that
instance.
Any triggers or dynamic events left behind in the top-level instance by
previous failed top-level tests, are left completely untouched. These
top-level leftovers can cause subsequent instance-based tests to fail
or even crash the kernel.
Fix this by executing 'initialize_system()' in the top-level tracing
directory once before entering the instance loop.
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/178425671889.84440.9477850701738666404.stgit@devnote2
Fixes: b5b77be812de ("selftests: ftrace: Allow some tests to be run in a tracing instance")
Assisted-by: Antigravity:gemini-3.5-flash
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
tools/testing/selftests/ftrace/ftracetest | 1 +
1 file changed, 1 insertion(+)
--- a/tools/testing/selftests/ftrace/ftracetest
+++ b/tools/testing/selftests/ftrace/ftracetest
@@ -483,6 +483,7 @@ for t in $TEST_CASES; do
done
# Test on instance loop
+(cd $TRACING_DIR; initialize_system)
INSTANCE=" (instance) "
for t in $TEST_CASES; do
test_on_instance $t || continue
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 420/602] rbd: Reset positive result codes to zero in object map update path
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (418 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 419/602] selftests/ftrace: Reset triggers at top level before instance loop Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 421/602] ksmbd: defer destroy_previous_session() until after NTLM authentication Greg Kroah-Hartman
` (185 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Raphael Zimmer, Ilya Dryomov
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
commit a6c4250b81bd30beae94e1b7a4b26fa1193ad2e4 upstream.
In a reply message to an RBD request, a positive result code indicates
a data payload, which is not allowed for writes. While
rbd_osd_req_callback() already resets a positive result code for writes
to zero, rbd_object_map_callback() does not. This allows a corrupted
reply to an object map update to trigger the rbd_assert(*result < 0) in
__rbd_obj_handle_request(). This happens, because
rbd_object_map_callback() calls rbd_obj_handle_request() ->
__rbd_obj_handle_request() and passes this positive result code. From
__rbd_obj_handle_request(), rbd_obj_advance_write() is called, which
leaves the positive result code unchanged and returns true. Therefore,
the if(done && *result) branch is executed in __rbd_obj_handle_request()
and the assertion triggers.
This patch fixes the issue by adjusting the logic in the
rbd_object_map_callback() path. A positive result code for an object map
update is now reset to zero (similar to rbd_osd_req_callback()), and the
message is subsequently handled the same way as if the result code was
zero from the beginning. Additionally, a WARN_ON_ONCE() is added for
this case.
Cc: stable@vger.kernel.org
Fixes: 22e8bd51bb04 ("rbd: support for object-map and fast-diff")
Signed-off-by: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/block/rbd.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -1957,10 +1957,15 @@ static int rbd_object_map_update_finish(
bool has_current_state;
void *p;
- if (osd_req->r_result)
+ if (osd_req->r_result < 0)
return osd_req->r_result;
/*
+ * Writes aren't allowed to return a data payload.
+ */
+ WARN_ON_ONCE(osd_req->r_result > 0);
+
+ /*
* Nothing to do for a snapshot object map.
*/
if (osd_req->r_num_ops == 1)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 421/602] ksmbd: defer destroy_previous_session() until after NTLM authentication
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (419 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 420/602] rbd: Reset positive result codes to zero in object map update path Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 422/602] ice: reject out-of-range ptype in ice_parser_profile_init Greg Kroah-Hartman
` (184 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, James Montgomery, Namjae Jeon,
Steve French
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: James Montgomery <james_montgomery@disroot.org>
commit c74801ee524f477c174a1899782b6c3b6918d407 upstream.
In ntlm_authenticate(), destroy_previous_session() is called using a
user pointer resolved from the client-supplied NTLM blob username field
before the NTLMv2 response is validated. An authenticated attacker can
set the NTLM blob username to match a victim account and set
PreviousSessionId to the victim's session ID; destroy_previous_session()
destroys the victim's session while ksmbd_decode_ntlmssp_auth_blob()
subsequently rejects the request with -EPERM.
Move destroy_previous_session() and the prev_id assignment to after
ksmbd_decode_ntlmssp_auth_blob() returns success and use sess->user
rather than the pre-authentication lookup result. This matches the
ordering already used by krb5_authenticate(), where
destroy_previous_session() is called only after
ksmbd_krb5_authenticate() returns success.
Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3")
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/linux-cifs/20260702155449.3639773-1-james_montgomery@disroot.org/
Signed-off-by: James Montgomery <james_montgomery@disroot.org>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/smb/server/smb2pdu.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -1489,11 +1489,6 @@ static int ntlm_authenticate(struct ksmb
return -EPERM;
}
- /* Check for previous session */
- prev_id = le64_to_cpu(req->PreviousSessionId);
- if (prev_id && prev_id != sess->id)
- destroy_previous_session(conn, user, prev_id);
-
if (sess->state == SMB2_SESSION_VALID) {
/*
* Reuse session if anonymous try to connect
@@ -1531,6 +1526,10 @@ static int ntlm_authenticate(struct ksmb
}
}
+ prev_id = le64_to_cpu(req->PreviousSessionId);
+ if (prev_id && prev_id != sess->id)
+ destroy_previous_session(conn, sess->user, prev_id);
+
/*
* If session state is SMB2_SESSION_VALID, We can assume
* that it is reauthentication. And the user/password
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 422/602] ice: reject out-of-range ptype in ice_parser_profile_init
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (420 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 421/602] ksmbd: defer destroy_previous_session() until after NTLM authentication Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 423/602] ice: use READ_ONCE() to access cached PHC time Greg Kroah-Hartman
` (183 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Aleksandr Loktionov, Marcin Szycik,
Rafal Romanowski, Tony Nguyen, Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
commit 59abb87159c53605c063f6e2ceb215b5eba43ee6 upstream.
set_bit(rslt->ptype, prof->ptypes) operates on a DECLARE_BITMAP of
ICE_FLOW_PTYPE_MAX (1024) bits. Nothing prevents a malicious VF from
providing ptype >= 1024 through VIRTCHNL, resulting in a write past
the end of the bitmap and a kernel page fault.
Reproduced with a custom kernel module injecting a crafted
VIRTCHNL_OP_ADD_RSS_CFG on E810-C QSFP (8086:1592),
FW 4.91 0x800214af 1.3909.0, ICE COMMS DDP 1.3.53.0,
kernel 7.1.0-rc1.
crash_parser: ice_parser_profile_init @ ffffffffc0d61b60
crash_parser: setting ptype=0xffff (max valid=1023)
crash_parser: calling ice_parser_profile_init -- expect OOB crash!
BUG: kernel NULL pointer dereference, address: 0000000000000000
Oops: Oops: 0002 [#1] SMP NOPTI
CPU: 56 UID: 0 PID: 165011 Comm: insmod Kdump: loaded Tainted: G S U OE 7.1.0-rc1 #1
Hardware name: Intel Corporation S2600BPB/S2600BPB
RIP: 0010:ice_parser_profile_init+0x2d/0x1d0 [ice]
Call Trace:
<TASK>
? __pfx_ice_parser_profile_init+0x10/0x10 [ice]
crash_init+0x127/0xff0 [crash_parser]
do_one_initcall+0x45/0x310
do_init_module+0x64/0x270
init_module_from_file+0xcc/0xf0
idempotent_init_module+0x17b/0x280
__x64_sys_finit_module+0x6e/0xe0
Bail out early with -EINVAL when ptype is out of range.
Fixes: e312b3a1e209 ("ice: add API for parser profile initialization")
Cc: stable@vger.kernel.org
Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Reviewed-by: Marcin Szycik <marcin.szycik@linux.intel.com>
Tested-by: Rafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Link: https://patch.msgid.link/20260717185340.3595286-12-anthony.l.nguyen@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/intel/ice/ice_parser.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/net/ethernet/intel/ice/ice_parser.c
+++ b/drivers/net/ethernet/intel/ice/ice_parser.c
@@ -2368,6 +2368,9 @@ int ice_parser_profile_init(struct ice_p
u16 proto_off = 0;
u16 off;
+ if (rslt->ptype >= ICE_FLOW_PTYPE_MAX)
+ return -EINVAL;
+
memset(prof, 0, sizeof(*prof));
set_bit(rslt->ptype, prof->ptypes);
if (blk == ICE_BLK_SW) {
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 423/602] ice: use READ_ONCE() to access cached PHC time
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (421 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 422/602] ice: reject out-of-range ptype in ice_parser_profile_init Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 424/602] ila: reload IPv6 header after pskb_may_pull in checksum adjust Greg Kroah-Hartman
` (182 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sergey Temerkhanov,
Aleksandr Loktionov, Simon Horman, Tony Nguyen, Jakub Kicinski,
Rinitha S
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sergey Temerkhanov <sergey.temerkhanov@intel.com>
commit 2915681b89f817677ab9f1166d95b595bc144f5f upstream.
ptp.cached_phc_time is a 64-bit value updated by a periodic work item
on one CPU and read locklessly on another. On 32-bit or non-atomic
architectures this can result in a torn read. Use READ_ONCE() to
enforce a single atomic load.
Fixes: 77a781155a65 ("ice: enable receive hardware timestamping")
Cc: stable@vger.kernel.org
Signed-off-by: Sergey Temerkhanov <sergey.temerkhanov@intel.com>
Signed-off-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Tested-by: Rinitha S <sx.rinitha@intel.com> (A Contingent worker at Intel)
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Link: https://patch.msgid.link/20260717185340.3595286-9-anthony.l.nguyen@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/intel/ice/ice_ptp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -514,7 +514,7 @@ static u64 ice_ptp_extend_40b_ts(struct
return 0;
}
- return ice_ptp_extend_32b_ts(pf->ptp.cached_phc_time,
+ return ice_ptp_extend_32b_ts(READ_ONCE(pf->ptp.cached_phc_time),
(in_tstamp >> 8) & mask);
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 424/602] ila: reload IPv6 header after pskb_may_pull in checksum adjust
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (422 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 423/602] ice: use READ_ONCE() to access cached PHC time Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 425/602] mac802154: hold an interface reference across the scan worker Greg Kroah-Hartman
` (181 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Michael Bommarito, Simon Horman,
Antoine Tenart, Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <michael.bommarito@gmail.com>
commit 92d3817649df2b0b6a008a686c8275c88d7ef594 upstream.
ila_csum_adjust_transport() caches ip6h = ipv6_hdr(skb) before calling
pskb_may_pull(). On a non-linear skb whose transport header sits in a page
fragment, pskb_may_pull() can call __pskb_pull_tail() / pskb_expand_head()
and free the old skb head, leaving ip6h dangling; the following
get_csum_diff(ip6h, p) then reads freed memory. ila_update_ipv6_locator()
uses ip6h (and the iaddr derived from it) again after the csum-adjust
call and additionally writes the new locator through that pointer.
Impact: a remote IPv6 packet routed through a configured ILA
csum-adjust-transport route or receive-side mapping triggers a
slab-use-after-free in ila_update_ipv6_locator() (KASAN). The route or
mapping requires CAP_NET_ADMIN to configure, but trigger packets are
unauthenticated once it exists.
Reload ip6h after each pskb_may_pull() in ila_csum_adjust_transport()
before the csum-diff read. In ila_update_ipv6_locator() only the
ILA_CSUM_ADJUST_TRANSPORT case pulls the skb, so reload ip6h and iaddr in
that case alone before the destination-address write; the neutral-map
modes never pull and keep their cached pointers.
Fixes: 33f11d16142b ("ila: Create net/ipv6/ila directory")
Cc: stable@vger.kernel.org
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Reviewed-by: Antoine Tenart <atenart@kernel.org>
Link: https://patch.msgid.link/20260714114903.3763420-1-michael.bommarito@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ipv6/ila/ila_common.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
--- a/net/ipv6/ila/ila_common.c
+++ b/net/ipv6/ila/ila_common.c
@@ -84,6 +84,7 @@ static void ila_csum_adjust_transport(st
struct tcphdr *th = (struct tcphdr *)
(skb_network_header(skb) + nhoff);
+ ip6h = ipv6_hdr(skb);
diff = get_csum_diff(ip6h, p);
inet_proto_csum_replace_by_diff(&th->check, skb,
diff, true, true);
@@ -95,6 +96,7 @@ static void ila_csum_adjust_transport(st
(skb_network_header(skb) + nhoff);
if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) {
+ ip6h = ipv6_hdr(skb);
diff = get_csum_diff(ip6h, p);
inet_proto_csum_replace_by_diff(&uh->check, skb,
diff, true, true);
@@ -109,6 +111,7 @@ static void ila_csum_adjust_transport(st
struct icmp6hdr *ih = (struct icmp6hdr *)
(skb_network_header(skb) + nhoff);
+ ip6h = ipv6_hdr(skb);
diff = get_csum_diff(ip6h, p);
inet_proto_csum_replace_by_diff(&ih->icmp6_cksum, skb,
diff, true, true);
@@ -126,6 +129,15 @@ void ila_update_ipv6_locator(struct sk_b
switch (p->csum_mode) {
case ILA_CSUM_ADJUST_TRANSPORT:
ila_csum_adjust_transport(skb, p);
+ /*
+ * ila_csum_adjust_transport() calls pskb_may_pull(), which can
+ * reallocate the skb head and leave ip6h (and the iaddr derived
+ * from it) dangling; reload both before the write below. The
+ * other csum modes do not pull, so their cached pointers stay
+ * valid.
+ */
+ ip6h = ipv6_hdr(skb);
+ iaddr = ila_a2i(&ip6h->daddr);
break;
case ILA_CSUM_NEUTRAL_MAP:
if (sir2ila) {
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 425/602] mac802154: hold an interface reference across the scan worker
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (423 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 424/602] ila: reload IPv6 header after pskb_may_pull in checksum adjust Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 426/602] mac802154: llsec: reject frames shorter than the authentication tag Greg Kroah-Hartman
` (180 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Ibrahim Hashimov, Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ibrahim Hashimov <security@auditcode.ai>
commit 234e5e898b713bc0b3a631b6f002897f43d046c8 upstream.
mac802154_scan_worker() captures the scanning sub-interface under RCU
and then keeps dereferencing sdata->dev after rcu_read_unlock() and
outside the rtnl -- in the failure traces, in
mac802154_transmit_beacon_req() (skb->dev = sdata->dev), and in the
end_scan cleanup. Nothing keeps that netdev alive across the worker
iteration.
A concurrent DEL_INTERFACE or PHY removal can unregister the interface
once the worker drops the rtnl between its two drv_set_channel()
sections. unregister_netdevice() frees the netdev asynchronously from
netdev_run_todo() with the rtnl already dropped, so neither holding the
rtnl nor the per-PHY IEEE802154_IS_SCANNING flag prevents a stale worker
iteration from dereferencing the freed netdev -- a KASAN
slab-use-after-free, reachable by racing TRIGGER_SCAN against
DEL_INTERFACE (both CAP_NET_ADMIN).
Pin the netdev with netdev_hold() while the RCU read lock is still held,
and release it at every worker exit.
Fixes: 57588c71177f ("mac802154: Handle passive scanning")
Cc: stable@vger.kernel.org
Signed-off-by: Ibrahim Hashimov <security@auditcode.ai>
Link: https://patch.msgid.link/20260721211228.34578-1-security@auditcode.ai
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/mac802154/scan.c | 11 +++++++++++
1 file changed, 11 insertions(+)
--- a/net/mac802154/scan.c
+++ b/net/mac802154/scan.c
@@ -179,6 +179,7 @@ void mac802154_scan_worker(struct work_s
enum nl802154_scan_types scan_req_type;
struct ieee802154_sub_if_data *sdata;
unsigned int scan_duration = 0;
+ netdevice_tracker dev_tracker;
struct wpan_phy *wpan_phy;
u8 scan_req_duration;
u8 page, channel;
@@ -209,6 +210,14 @@ void mac802154_scan_worker(struct work_s
return;
}
+ /*
+ * sdata->dev is dereferenced below after rcu_read_unlock() and outside
+ * the rtnl, and a concurrent DEL_INTERFACE / PHY teardown can free it
+ * asynchronously from netdev_run_todo(). Pin it with a reference taken
+ * while the RCU read lock is still held, and drop it at every exit.
+ */
+ netdev_hold(sdata->dev, &dev_tracker, GFP_ATOMIC);
+
wpan_phy = scan_req->wpan_phy;
scan_req_type = scan_req->type;
scan_req_duration = scan_req->duration;
@@ -262,12 +271,14 @@ void mac802154_scan_worker(struct work_s
"Scan page %u channel %u for %ums\n",
page, channel, jiffies_to_msecs(scan_duration));
queue_delayed_work(local->mac_wq, &local->scan_work, scan_duration);
+ netdev_put(sdata->dev, &dev_tracker);
return;
end_scan:
rtnl_lock();
mac802154_scan_cleanup_locked(local, sdata, false);
rtnl_unlock();
+ netdev_put(sdata->dev, &dev_tracker);
}
int mac802154_trigger_scan_locked(struct ieee802154_sub_if_data *sdata,
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 426/602] mac802154: llsec: reject frames shorter than the authentication tag
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (424 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 425/602] mac802154: hold an interface reference across the scan worker Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 427/602] mctp: serial: handle zero-length frames to prevent rx buffer overflow Greg Kroah-Hartman
` (179 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Simon Horman, Doruk Tan Ozturk,
Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Doruk Tan Ozturk <doruk@0sec.ai>
commit fd3a3f28ed60c6af4b2a39933b151d6b27842c3b upstream.
llsec_do_decrypt_auth() computes the associated-data length for the
AEAD request as
assoclen += datalen - authlen;
where datalen is the number of bytes after the MAC header and authlen
(4, 8 or 16) is the length of the authentication tag. Nothing verifies
that the frame actually carries at least authlen payload bytes. A
secured frame whose payload is shorter than the tag makes
datalen - authlen negative; assoclen is then passed to
aead_request_set_ad() as an unsigned value close to 4 GiB, so
crypto_aead_decrypt() walks far off the end of the scatterlist that
only spans the real frame.
The frame is fully attacker-controlled and reaches this path from any
IEEE 802.15.4 peer in radio range. Reject frames whose payload is
shorter than the authentication tag before the subtraction.
Dynamically reproduced on a KASAN kernel as a general-protection-fault
in the AEAD scatterwalk, and the fix confirmed.
Fixes: 4c14a2fb5d14 ("mac802154: add llsec decryption method")
Cc: stable@vger.kernel.org
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
Link: https://patch.msgid.link/20260716193423.32498-1-doruk@0sec.ai
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/mac802154/llsec.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/net/mac802154/llsec.c
+++ b/net/mac802154/llsec.c
@@ -891,6 +891,11 @@ llsec_do_decrypt_auth(struct sk_buff *sk
data = skb_mac_header(skb) + skb->mac_len;
datalen = skb_tail_pointer(skb) - data;
+ if (datalen < authlen) {
+ kfree_sensitive(req);
+ return -EBADMSG;
+ }
+
sg_init_one(&sg, skb_mac_header(skb), assoclen + datalen);
if (!(hdr->sec.level & IEEE802154_SCF_SECLEVEL_ENC)) {
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 427/602] mctp: serial: handle zero-length frames to prevent rx buffer overflow
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (425 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 426/602] mac802154: llsec: reject frames shorter than the authentication tag Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 428/602] openvswitch: fix GSO userspace truncation underflow Greg Kroah-Hartman
` (178 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jeremy Kerr, Doruk Tan Ozturk,
Simon Horman, Paolo Abeni
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Doruk Tan Ozturk <doruk@0sec.ai>
commit 793b9b729f1e8de57be8c8daf1a9838be96cabed upstream.
The MCTP serial receive state machine reads a frame length byte in
mctp_serial_push_header() case 2 and validates it upper-bound-only:
if (c > MCTP_SERIAL_FRAME_MTU) {
dev->rxstate = STATE_ERR;
} else {
dev->rxlen = c;
dev->rxpos = 0;
dev->rxstate = STATE_DATA;
...
}
A length of zero passes this check, so rxlen is set to 0 and the state
machine advances to STATE_DATA. In mctp_serial_push() STATE_DATA, the
incoming byte is stored and rxpos incremented before the terminator is
tested:
dev->rxbuf[dev->rxpos] = c;
dev->rxpos++;
dev->rxstate = STATE_DATA;
if (dev->rxpos == dev->rxlen) {
dev->rxpos = 0;
dev->rxstate = STATE_TRAILER;
}
With rxlen == 0 the "rxpos == rxlen" terminator can never fire (rxpos is
already 1 on the first data byte), so subsequent bytes are written past
the end of the fixed 74-byte rxbuf, which is the last member of the
netdev private area. Every following data byte is an attacker-controlled
1-byte out-of-bounds heap write, and the overflow continues until a
frame (0x7e) or escape byte resets the parser -- effectively unbounded.
Reaching this requires CAP_NET_ADMIN to attach the N_MCTP line
discipline and bring the resulting mctpserialN netdev up, after which
the bytes arrive via the tty receive path.
Route a zero-length frame straight to STATE_TRAILER instead of
STATE_DATA. The trailer/framing bytes are still consumed, and the frame
resolves to a zero-length skb that the MCTP core rejects; the parser
never enters STATE_DATA with rxlen == 0, so the out-of-bounds write can
no longer occur.
KASAN, on a frame of 0x7e 0x01 0x00 followed by data bytes (before this
change):
UBSAN: array-index-out-of-bounds in drivers/net/mctp/mctp-serial.c:370
index 74 is out of range for type 'u8 [74]'
BUG: KASAN: slab-out-of-bounds in mctp_serial_tty_receive_buf
Write of size 1 at addr ... by task kworker/u16:0
mctp_serial_tty_receive_buf
tty_ldisc_receive_buf
flush_to_ldisc
Allocated by task 152:
alloc_netdev_mqs
mctp_serial_open
v2: route zero-length frames to STATE_TRAILER instead of STATE_ERR so
the trailer/framing bytes are still consumed (Jeremy Kerr).
Found by 0sec automated security-research tooling (https://0sec.ai).
Fixes: a0c2ccd9b5ad ("mctp: Add MCTP-over-serial transport binding")
Cc: stable@vger.kernel.org
Suggested-by: Jeremy Kerr <jk@codeconstruct.com.au>
Assisted-by: 0sec:multi-model
Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260715082021.46315-1-doruk@0sec.ai
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/mctp/mctp-serial.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/mctp/mctp-serial.c
+++ b/drivers/net/mctp/mctp-serial.c
@@ -317,7 +317,7 @@ static void mctp_serial_push_header(stru
} else {
dev->rxlen = c;
dev->rxpos = 0;
- dev->rxstate = STATE_DATA;
+ dev->rxstate = c > 0 ? STATE_DATA : STATE_TRAILER;
dev->rxfcs = crc_ccitt_byte(dev->rxfcs, c);
}
break;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 428/602] openvswitch: fix GSO userspace truncation underflow
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (426 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 427/602] mctp: serial: handle zero-length frames to prevent rx buffer overflow Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 429/602] pppoe: reload header pointer after dev_hard_header() Greg Kroah-Hartman
` (177 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Kyle Zeng, Ilya Maximets,
Aaron Conole, Paolo Abeni
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kyle Zeng <kylebot@openai.com>
commit 4032f8ed10fcb84d41c508dfb04be96589f78dfe upstream.
OVS_ACTION_ATTR_TRUNC currently stores a delta from the original skb
length in OVS_CB(skb)->cutlen. When a later userspace action segments a
GSO skb, queue_gso_packets() reuses that delta for each smaller segment.
A segment can then reach queue_userspace_packet() with cutlen greater
than skb->len, underflowing the length passed to skb_zerocopy().
Store the maximum preserved length instead and bound each consumer
against the current skb length. Use U32_MAX as the no-truncation
sentinel so the value remains valid if skb geometry changes before a
consumer handles it.
Fixes: f2a4d086ed4c ("openvswitch: Add packet truncation support.")
Cc: stable@vger.kernel.org
Assisted-by: Codex:gpt-5.5
Signed-off-by: Kyle Zeng <kylebot@openai.com>
Reviewed-by: Ilya Maximets <i.maximets@ovn.org>
Reviewed-by: Aaron Conole <aconole@redhat.com>
Link: https://patch.msgid.link/20260707221635.27489-1-kylebot@openai.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/openvswitch/actions.c | 19 +++++++------------
net/openvswitch/datapath.c | 25 ++++++++++++++-----------
net/openvswitch/datapath.h | 2 +-
net/openvswitch/vport.c | 2 +-
4 files changed, 23 insertions(+), 25 deletions(-)
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -877,12 +877,8 @@ static void do_output(struct datapath *d
u16 mru = OVS_CB(skb)->mru;
u32 cutlen = OVS_CB(skb)->cutlen;
- if (unlikely(cutlen > 0)) {
- if (skb->len - cutlen > ovs_mac_header_len(key))
- pskb_trim(skb, skb->len - cutlen);
- else
- pskb_trim(skb, ovs_mac_header_len(key));
- }
+ if (unlikely(cutlen < skb->len))
+ pskb_trim(skb, max(cutlen, ovs_mac_header_len(key)));
if (likely(!mru ||
(skb->len <= mru + vport->dev->hard_header_len))) {
@@ -1272,7 +1268,7 @@ static void execute_psample(struct datap
psample_group.net = ovs_dp_get_net(dp);
md.in_ifindex = OVS_CB(skb)->input_vport->dev->ifindex;
- md.trunc_size = skb->len - OVS_CB(skb)->cutlen;
+ md.trunc_size = min(skb->len, OVS_CB(skb)->cutlen);
md.rate_as_probability = 1;
rate = OVS_CB(skb)->probability ? OVS_CB(skb)->probability : U32_MAX;
@@ -1322,22 +1318,21 @@ static int do_execute_actions(struct dat
clone = skb_clone(skb, GFP_ATOMIC);
if (clone)
do_output(dp, clone, port, key);
- OVS_CB(skb)->cutlen = 0;
+ OVS_CB(skb)->cutlen = U32_MAX;
break;
}
case OVS_ACTION_ATTR_TRUNC: {
struct ovs_action_trunc *trunc = nla_data(a);
- if (skb->len > trunc->max_len)
- OVS_CB(skb)->cutlen = skb->len - trunc->max_len;
+ OVS_CB(skb)->cutlen = trunc->max_len;
break;
}
case OVS_ACTION_ATTR_USERSPACE:
output_userspace(dp, skb, key, a, attr,
len, OVS_CB(skb)->cutlen);
- OVS_CB(skb)->cutlen = 0;
+ OVS_CB(skb)->cutlen = U32_MAX;
if (nla_is_last(a, rem)) {
consume_skb(skb);
return 0;
@@ -1491,7 +1486,7 @@ static int do_execute_actions(struct dat
case OVS_ACTION_ATTR_PSAMPLE:
execute_psample(dp, skb, a);
- OVS_CB(skb)->cutlen = 0;
+ OVS_CB(skb)->cutlen = U32_MAX;
if (nla_is_last(a, rem)) {
consume_skb(skb);
return 0;
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -272,7 +272,7 @@ void ovs_dp_process_packet(struct sk_buf
upcall.portid = ovs_vport_find_upcall_portid(p, skb);
upcall.mru = OVS_CB(skb)->mru;
- error = ovs_dp_upcall(dp, skb, key, &upcall, 0);
+ error = ovs_dp_upcall(dp, skb, key, &upcall, U32_MAX);
switch (error) {
case 0:
case -EAGAIN:
@@ -437,7 +437,8 @@ static int queue_userspace_packet(struct
struct sk_buff *nskb = NULL;
struct sk_buff *user_skb = NULL; /* to be queued to userspace */
struct nlattr *nla;
- size_t len;
+ size_t msg_size;
+ size_t skb_len;
unsigned int hlen;
int err, dp_ifindex;
u64 hash;
@@ -458,7 +459,8 @@ static int queue_userspace_packet(struct
skb = nskb;
}
- if (nla_attr_size(skb->len) > USHRT_MAX) {
+ skb_len = min(skb->len, cutlen);
+ if (nla_attr_size(skb_len) > USHRT_MAX) {
err = -EFBIG;
goto out;
}
@@ -473,13 +475,13 @@ static int queue_userspace_packet(struct
* padding logic. Only perform zerocopy if padding is not required.
*/
if (dp->user_features & OVS_DP_F_UNALIGNED)
- hlen = skb_zerocopy_headlen(skb);
+ hlen = min(skb_zerocopy_headlen(skb), cutlen);
else
- hlen = skb->len;
+ hlen = skb_len;
- len = upcall_msg_size(upcall_info, hlen - cutlen,
- OVS_CB(skb)->acts_origlen);
- user_skb = genlmsg_new(len, GFP_ATOMIC);
+ msg_size = upcall_msg_size(upcall_info, hlen,
+ OVS_CB(skb)->acts_origlen);
+ user_skb = genlmsg_new(msg_size, GFP_ATOMIC);
if (!user_skb) {
err = -ENOMEM;
goto out;
@@ -540,7 +542,7 @@ static int queue_userspace_packet(struct
}
/* Add OVS_PACKET_ATTR_LEN when packet is truncated */
- if (cutlen > 0 &&
+ if (skb_len < skb->len &&
nla_put_u32(user_skb, OVS_PACKET_ATTR_LEN, skb->len)) {
err = -ENOBUFS;
goto out;
@@ -565,9 +567,9 @@ static int queue_userspace_packet(struct
err = -ENOBUFS;
goto out;
}
- nla->nla_len = nla_attr_size(skb->len - cutlen);
+ nla->nla_len = nla_attr_size(skb_len);
- err = skb_zerocopy(user_skb, skb, skb->len - cutlen, hlen);
+ err = skb_zerocopy(user_skb, skb, skb_len, hlen);
if (err)
goto out;
@@ -624,6 +626,7 @@ static int ovs_packet_cmd_execute(struct
packet->ignore_df = 1;
}
OVS_CB(packet)->mru = mru;
+ OVS_CB(packet)->cutlen = U32_MAX;
if (a[OVS_PACKET_ATTR_HASH]) {
hash = nla_get_u64(a[OVS_PACKET_ATTR_HASH]);
--- a/net/openvswitch/datapath.h
+++ b/net/openvswitch/datapath.h
@@ -114,7 +114,7 @@ struct datapath {
* @mru: The maximum received fragement size; 0 if the packet is not
* fragmented.
* @acts_origlen: The netlink size of the flow actions applied to this skb.
- * @cutlen: The number of bytes from the packet end to be removed.
+ * @cutlen: The number of bytes in the packet to preserve on output.
* @probability: The sampling probability that was applied to this skb; 0 means
* no sampling has occurred; U32_MAX means 100% probability.
*/
--- a/net/openvswitch/vport.c
+++ b/net/openvswitch/vport.c
@@ -503,7 +503,7 @@ int ovs_vport_receive(struct vport *vpor
OVS_CB(skb)->input_vport = vport;
OVS_CB(skb)->mru = 0;
- OVS_CB(skb)->cutlen = 0;
+ OVS_CB(skb)->cutlen = U32_MAX;
OVS_CB(skb)->probability = 0;
if (unlikely(dev_net(skb->dev) != ovs_dp_get_net(vport->dp))) {
u32 mark;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 429/602] pppoe: reload header pointer after dev_hard_header()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (427 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 428/602] openvswitch: fix GSO userspace truncation underflow Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 430/602] rtase: Workaround for TX hang caused by hardware packet parsing Greg Kroah-Hartman
` (176 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Asim Viladi Oglu Manizada,
Vadim Fedorenko, Eric Dumazet, Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Asim Viladi Oglu Manizada <manizada@pm.me>
commit e9c238f6fe42fb1b4dba3a578277de32cb487937 upstream.
pppoe_sendmsg() saves a pointer to the PPPoE header before calling
dev_hard_header(). Device header callbacks are allowed to reallocate the
skb head, invalidating pointers into it.
This can happen when a send is blocked in copy_from_user() while the first
non-Ethernet port is added to an empty team device. The team's delegated
GRE header callback then expands the skb head. PPPoE subsequently writes
six bytes through the stale pointer into the freed head.
Reload the PPPoE header through the skb's network-header offset after
device header creation. pskb_expand_head() updates that offset when it
relocates the head.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Asim Viladi Oglu Manizada <manizada@pm.me>
Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260722093814.3017176-1-manizada@pm.me
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ppp/pppoe.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/net/ppp/pppoe.c
+++ b/drivers/net/ppp/pppoe.c
@@ -900,6 +900,7 @@ static int pppoe_sendmsg(struct socket *
dev_hard_header(skb, dev, ETH_P_PPP_SES,
po->pppoe_pa.remote, NULL, total_len);
+ ph = pppoe_hdr(skb);
memcpy(ph, &hdr, sizeof(struct pppoe_hdr));
ph->length = htons(total_len);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 430/602] rtase: Workaround for TX hang caused by hardware packet parsing
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (428 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 429/602] pppoe: reload header pointer after dev_hard_header() Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 431/602] tcp: initialize standalone TCP-AO response padding Greg Kroah-Hartman
` (175 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Justin Lai, Simon Horman,
Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Justin Lai <justinlai0215@realtek.com>
commit 1c50efa1faf3a1a96e100b07ec7a2f3164d90bee upstream.
The hardware performs packet parsing before packet transmission.
Parsing incomplete IPv4, IPv6, TCP, or UDP headers may trigger a TX
hang because the hardware parser expects additional protocol header
data that is not present in the packet.
The hardware performs additional PTP parsing on UDP packets identified
by destination ports 319/320 at the expected UDP destination port
offset.
If such a packet has transport data smaller than RTASE_MIN_PAD_LEN,
the hardware parser expects additional packet data and may trigger a
TX hang.
To avoid these hardware issues, the driver applies the following
workarounds.
Drop malformed packets that may trigger this hardware issue before
transmission.
For IPv4 non-initial fragments, the hardware does not check the
fragment offset before parsing the expected transport header location.
As a result, these packets are still subject to transport header
parsing even though they do not contain a transport header. If the
transport data is shorter than the minimum transport header required
by the hardware parser, pad the transport data to the minimum
transport header length required by the hardware parser. Packets that
also match the hardware PTP parsing conditions continue to follow the
corresponding workaround.
For IPv6 fragmented packets, neither of the above hardware issues
occurs because the hardware only continues packet parsing when the
IPv6 Base Header Next Header field directly indicates UDP. Packets
carrying a Fragment Header do not continue through the subsequent
packet parsing stages.
For packets identified for hardware PTP parsing, pad the transport
data so it reaches RTASE_MIN_PAD_LEN before transmission.
Fixes: d6e882b89fdf ("rtase: Implement .ndo_start_xmit function")
Cc: stable@vger.kernel.org
Signed-off-by: Justin Lai <justinlai0215@realtek.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260709103456.83789-1-justinlai0215@realtek.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/realtek/rtase/rtase.h | 8
drivers/net/ethernet/realtek/rtase/rtase_main.c | 197 ++++++++++++++++++++++++
2 files changed, 205 insertions(+)
--- a/drivers/net/ethernet/realtek/rtase/rtase.h
+++ b/drivers/net/ethernet/realtek/rtase/rtase.h
@@ -186,6 +186,12 @@ enum rtase_sw_flag_content {
RTASE_SWF_MSIX_ENABLED = BIT(2),
};
+enum rtase_parse_result {
+ RTASE_PARSE_OK,
+ RTASE_PARSE_SKIP,
+ RTASE_PARSE_DROP,
+};
+
#define RSVD_MASK 0x3FFFC000
struct rtase_tx_desc {
@@ -342,4 +348,6 @@ struct rtase_private {
#define RTASE_MSS_MASK GENMASK(28, 18)
+#define RTASE_MIN_PAD_LEN 47
+
#endif /* RTASE_H */
--- a/drivers/net/ethernet/realtek/rtase/rtase_main.c
+++ b/drivers/net/ethernet/realtek/rtase/rtase_main.c
@@ -61,6 +61,7 @@
#include <linux/pci.h>
#include <linux/pm_runtime.h>
#include <linux/prefetch.h>
+#include <linux/ptp_classify.h>
#include <linux/rtnetlink.h>
#include <linux/tcp.h>
#include <asm/irq.h>
@@ -1238,6 +1239,199 @@ static u32 rtase_tx_csum(struct sk_buff
return csum_cmd;
}
+static enum rtase_parse_result rtase_get_l3_proto(struct sk_buff *skb,
+ __be16 *proto,
+ u32 *network_offset)
+{
+ struct vlan_hdr *vh, _vh;
+ struct ethhdr *eh, _eh;
+ u32 offset = ETH_HLEN;
+
+ eh = skb_header_pointer(skb, 0, sizeof(_eh), &_eh);
+ if (!eh)
+ return RTASE_PARSE_DROP;
+
+ *proto = eh->h_proto;
+
+ while (eth_type_vlan(*proto)) {
+ vh = skb_header_pointer(skb, offset, sizeof(_vh), &_vh);
+ if (!vh)
+ return RTASE_PARSE_DROP;
+
+ *proto = vh->h_vlan_encapsulated_proto;
+ offset += VLAN_HLEN;
+ }
+
+ *network_offset = offset;
+
+ return RTASE_PARSE_OK;
+}
+
+static bool rtase_pad_to_transport_len(struct sk_buff *skb,
+ u32 transport_offset,
+ u32 pad_to_len)
+{
+ u32 trans_data_len;
+ u32 pad_len;
+
+ trans_data_len = skb->len - transport_offset;
+ if (trans_data_len >= pad_to_len)
+ return true;
+
+ if (skb_is_nonlinear(skb)) {
+ if (skb_linearize(skb))
+ return false;
+ }
+
+ pad_len = pad_to_len - trans_data_len;
+ if (__skb_put_padto(skb, skb->len + pad_len, false))
+ return false;
+
+ return true;
+}
+
+static enum rtase_parse_result rtase_get_transport_offset(struct sk_buff *skb,
+ u32 *transport_offset,
+ u8 *transport_proto,
+ u32 *pad_to_len)
+{
+ enum rtase_parse_result ret;
+ struct ipv6hdr *i6h, _i6h;
+ struct iphdr *ih, _ih;
+ bool non_first_frag;
+ __be16 proto;
+ u32 offset;
+ u32 no;
+
+ ret = rtase_get_l3_proto(skb, &proto, &no);
+ if (ret != RTASE_PARSE_OK)
+ return ret;
+
+ switch (proto) {
+ case htons(ETH_P_IP):
+ ih = skb_header_pointer(skb, no, sizeof(_ih), &_ih);
+ if (!ih)
+ return RTASE_PARSE_DROP;
+
+ if (ih->ihl < 5)
+ return RTASE_PARSE_DROP;
+
+ offset = no + ih->ihl * 4;
+ if (offset > skb->len)
+ return RTASE_PARSE_DROP;
+
+ non_first_frag = ntohs(ih->frag_off) & IP_OFFSET;
+
+ if (ih->protocol == IPPROTO_TCP) {
+ if (skb->len - offset < sizeof(struct tcphdr)) {
+ if (non_first_frag) {
+ *transport_offset = offset;
+ *transport_proto = IPPROTO_TCP;
+ *pad_to_len = sizeof(struct tcphdr);
+
+ return RTASE_PARSE_OK;
+ }
+
+ return RTASE_PARSE_DROP;
+ }
+
+ return RTASE_PARSE_SKIP;
+ }
+
+ if (ih->protocol != IPPROTO_UDP)
+ return RTASE_PARSE_SKIP;
+
+ *transport_offset = offset;
+ *transport_proto = IPPROTO_UDP;
+
+ if (skb->len - offset < sizeof(struct udphdr)) {
+ if (non_first_frag) {
+ *pad_to_len = sizeof(struct udphdr);
+
+ return RTASE_PARSE_OK;
+ }
+
+ return RTASE_PARSE_DROP;
+ }
+
+ return RTASE_PARSE_OK;
+
+ case htons(ETH_P_IPV6):
+ i6h = skb_header_pointer(skb, no, sizeof(_i6h), &_i6h);
+ if (!i6h)
+ return RTASE_PARSE_DROP;
+
+ offset = no + sizeof(*i6h);
+
+ if (i6h->nexthdr == IPPROTO_TCP) {
+ if (skb->len - offset < sizeof(struct tcphdr))
+ return RTASE_PARSE_DROP;
+
+ return RTASE_PARSE_SKIP;
+ }
+
+ if (i6h->nexthdr != IPPROTO_UDP)
+ return RTASE_PARSE_SKIP;
+
+ if (skb->len - offset < sizeof(struct udphdr))
+ return RTASE_PARSE_DROP;
+
+ *transport_offset = offset;
+ *transport_proto = IPPROTO_UDP;
+
+ return RTASE_PARSE_OK;
+
+ default:
+ return RTASE_PARSE_SKIP;
+ }
+}
+
+static bool rtase_skb_pad(struct sk_buff *skb)
+{
+ enum rtase_parse_result ret;
+ u32 transport_offset;
+ __be16 *dest, _dest;
+ u32 trans_data_len;
+ u32 pad_to_len = 0;
+ u8 transport_proto;
+ u16 dest_port;
+
+ ret = rtase_get_transport_offset(skb, &transport_offset,
+ &transport_proto, &pad_to_len);
+ if (ret == RTASE_PARSE_SKIP) {
+ return true;
+ } else if (ret == RTASE_PARSE_DROP) {
+ netdev_dbg(skb->dev, "drop malformed packet\n");
+ return false;
+ }
+
+ if (pad_to_len &&
+ !rtase_pad_to_transport_len(skb, transport_offset, pad_to_len))
+ return false;
+
+ if (transport_proto != IPPROTO_UDP)
+ return true;
+
+ trans_data_len = skb->len - transport_offset;
+ if (trans_data_len < offsetof(struct udphdr, len) ||
+ trans_data_len >= RTASE_MIN_PAD_LEN)
+ return true;
+
+ dest = skb_header_pointer(skb,
+ transport_offset +
+ offsetof(struct udphdr, dest),
+ sizeof(_dest), &_dest);
+ if (!dest)
+ return true;
+
+ dest_port = ntohs(*dest);
+ if (dest_port != PTP_EV_PORT && dest_port != PTP_GEN_PORT)
+ return true;
+
+ return rtase_pad_to_transport_len(skb, transport_offset,
+ RTASE_MIN_PAD_LEN);
+}
+
static int rtase_xmit_frags(struct rtase_ring *ring, struct sk_buff *skb,
u32 opts1, u32 opts2)
{
@@ -1351,6 +1545,9 @@ static netdev_tx_t rtase_start_xmit(stru
opts2 |= rtase_tx_csum(skb, dev);
}
+ if (!rtase_skb_pad(skb))
+ goto err_dma_0;
+
frags = rtase_xmit_frags(ring, skb, opts1, opts2);
if (unlikely(frags < 0))
goto err_dma_0;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 431/602] tcp: initialize standalone TCP-AO response padding
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (429 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 430/602] rtase: Workaround for TX hang caused by hardware packet parsing Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 432/602] tipc: clear sock->sk on the failed-insert path in tipc_sk_create() Greg Kroah-Hartman
` (174 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yizhou Zhao, Yuxiang Yang, Ao Wang,
Xuewei Feng, Qi Li, Ke Xu, Eric Dumazet, Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
commit e1a9d3cc11829c5414a75eb39c704f461936eb24 upstream.
tcp_v4_send_ack() and tcp_v6_send_response() construct standalone TCP
responses with TCP-AO options. The option length carries the actual MAC
length, but the TCP header length includes the option rounded up to a
four-byte boundary.
tcp_ao_hash_hdr() writes the MAC only. Thus, when the MAC length is not
four-byte aligned, the one to three bytes after the MAC are left
uninitialized and may be transmitted. For the normal TCP-AO hashing
mode, those bytes also have to be initialized before computing the MAC.
Initialize only the alignment padding in the TCP-AO branches, before
hashing the header. Use TCPOPT_NOP, as in the normal TCP-AO output path.
This avoids adding work to non-AO TCP responses while preserving a valid
authenticated header.
Fixes: decde2586b34 ("net/tcp: Add TCP-AO sign to twsk")
Fixes: da7dfaa6d6f7 ("net/tcp: Consistently align TCP-AO option in the header")
Cc: stable@vger.kernel.org
Reported-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
Reported-by: Yuxiang Yang <yangyx22@mails.tsinghua.edu.cn>
Reported-by: Ao Wang <wangao@seu.edu.cn>
Reported-by: Xuewei Feng <fengxw06@126.com>
Reported-by: Qi Li <qli01@tsinghua.edu.cn>
Reported-by: Ke Xu <xuke@tsinghua.edu.cn>
Suggested-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260713105631.8616-1-zhaoyz24@mails.tsinghua.edu.cn
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ipv4/tcp_ipv4.c | 3 +++
net/ipv6/tcp_ipv6.c | 2 ++
2 files changed, 5 insertions(+)
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -993,6 +993,9 @@ static void tcp_v4_send_ack(const struct
key->rcv_next);
arg.iov[0].iov_len += tcp_ao_len_aligned(key->ao_key);
rep.th.doff = arg.iov[0].iov_len / 4;
+ memset((u8 *)&rep.opt[offset] + tcp_ao_maclen(key->ao_key),
+ TCPOPT_NOP, tcp_ao_len_aligned(key->ao_key) -
+ tcp_ao_len(key->ao_key));
tcp_ao_hash_hdr(AF_INET, (char *)&rep.opt[offset],
key->ao_key, key->traffic_key,
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -936,6 +936,8 @@ static void tcp_v6_send_response(const s
(tcp_ao_len(key->ao_key) << 16) |
(key->ao_key->sndid << 8) |
(key->rcv_next));
+ memset((u8 *)topt + tcp_ao_maclen(key->ao_key), TCPOPT_NOP,
+ tcp_ao_len_aligned(key->ao_key) - tcp_ao_len(key->ao_key));
tcp_ao_hash_hdr(AF_INET6, (char *)topt, key->ao_key,
key->traffic_key,
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 432/602] tipc: clear sock->sk on the failed-insert path in tipc_sk_create()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (430 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 431/602] tcp: initialize standalone TCP-AO response padding Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 433/602] vsock/virtio: collapse receive queue under memory pressure Greg Kroah-Hartman
` (173 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Tung Nguyen, Breno Leitao,
Daehyeon Ko, Simon Horman, Paolo Abeni
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daehyeon Ko <4ncienth@gmail.com>
commit ba0533fc163f905fe817cfabdf8ed4058da44800 upstream.
When tipc_sk_create() fails to insert the new socket (tipc_sk_insert()
returns non-zero), its error path frees the sk with sk_free() but leaves
sock->sk pointing at the freed object:
if (tipc_sk_insert(tsk)) {
sk_free(sk);
pr_warn("Socket create failed; port number exhausted\n");
return -EINVAL;
}
This is harmless for plain socket(): the syscall layer clears sock->ops
before releasing, so tipc_release() is never called. It is not harmless
on the accept() path. tipc_accept() creates the pre-allocated child
socket with tipc_sk_create(net, new_sock, 0, kern); on failure it leaves
new_sock->sk dangling and new_sock->ops non-NULL, and do_accept() then
fput()s the new file, so __sock_release() -> tipc_release() runs
lock_sock(new_sock->sk) on the freed sk -- a use-after-free write of the
sk_lock spinlock.
tipc_release() already guards this exact "failed accept() releases a
pre-allocated child" case with "if (sk == NULL) return 0;", but the
guard is bypassed because tipc_sk_create() left sock->sk non-NULL
(dangling) rather than NULL.
Clear sock->sk on the failed-insert path so the existing tipc_release()
NULL check fires and the use-after-free is avoided.
The tipc_sk_insert() failure is reached when the per-netns socket
rhashtable hits its max_size (tsk_rht_params.max_size = 1048576, ~2M
elements) -- i.e. once a netns holds ~2M TIPC sockets every insert
returns -E2BIG.
BUG: KASAN: slab-use-after-free in lock_sock_nested (net/core/sock.c:3839)
Write of size 8 at addr ffff8880047cdc38 by task init/1
lock_sock_nested (net/core/sock.c:3839)
tipc_release (net/tipc/socket.c:638)
__sock_release (net/socket.c:710)
sock_close (net/socket.c:1501)
__fput (fs/file_table.c:512)
Allocated by task 1:
sk_alloc (net/core/sock.c:2308)
tipc_sk_create (net/tipc/socket.c:487)
tipc_accept (net/tipc/socket.c:2744)
do_accept (net/socket.c:2034)
Freed by task 1:
__sk_destruct (net/core/sock.c:2391)
tipc_sk_create (net/tipc/socket.c:504)
tipc_accept (net/tipc/socket.c:2744)
do_accept (net/socket.c:2034)
Fixes: 00aff3590fc0 ("net: tipc: fix possible refcount leak in tipc_sk_create()")
Cc: stable@vger.kernel.org
Reviewed-by: Tung Nguyen <tung.quang.nguyen@est.tech>
Reviewed-by: Breno Leitao <leitao@debian.org>
Signed-off-by: Daehyeon Ko <4ncienth@gmail.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260714131939.1255974-1-4ncienth@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/tipc/socket.c | 1 +
1 file changed, 1 insertion(+)
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -501,6 +501,7 @@ static int tipc_sk_create(struct net *ne
tipc_set_sk_state(sk, TIPC_OPEN);
if (tipc_sk_insert(tsk)) {
sk_free(sk);
+ sock->sk = NULL;
pr_warn("Socket create failed; port number exhausted\n");
return -EINVAL;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 433/602] vsock/virtio: collapse receive queue under memory pressure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (431 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 432/602] tipc: clear sock->sk on the failed-insert path in tipc_sk_create() Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 434/602] vxlan: mdb: Fix source list corruption on a failed replace Greg Kroah-Hartman
` (172 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Brien Oberstein, Stefano Garzarella,
Michael S. Tsirkin, Bobby Eshleman, Paolo Abeni
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefano Garzarella <sgarzare@redhat.com>
commit 2a12c05aef213ff304ecc9e2f351de20731946b8 upstream.
When many small packets accumulate in the receive queue, the skb overhead
can exceed buf_alloc even while the payload is within bounds. This causes
virtio_transport_inc_rx_pkt() to reject packets, leading to connection
resets during large transfers under backpressure.
The issue was reported by Brien, who has a reproducer, but it is also
easily reproducible with iperf-vsock [1] using a small packet size:
iperf3 --vsock -c $CID -l 129
which fails immediately without this patch but with commit 059b7dbd20a6
("vsock/virtio: fix potential unbounded skb queue").
Inspired by TCP's tcp_collapse() which solves a similar problem, add
virtio_transport_collapse_rx_queue() that walks the receive queue and
re-copies data into compact linear skbs to reduce the overhead.
The collapse is triggered proactively from when the number of skb queued
is close to exceeding the overhead budget.
A pre-scan counts the eligible bytes to size each allocation precisely,
avoiding waste for isolated small packets. Partially consumed skbs are
kept as-is to preserve buf_used/fwd_cnt accounting, EOM-marked skbs to
maintain SEQPACKET message boundaries, and skbs already larger than the
collapse target because they already have a good data-to-overhead ratio.
Walking a large queue may take a significant amount of time and cache
misses, causing traffic burstiness. To limit this, the collapse stops
once enough room is freed for this packet and the next one, but may
opportunistically free more to fill each collapsed skb to capacity.
[1] https://github.com/stefano-garzarella/iperf-vsock
Fixes: 059b7dbd20a6 ("vsock/virtio: fix potential unbounded skb queue")
Cc: stable@vger.kernel.org
Reported-by: Brien Oberstein <brienpub@gmail.com>
Closes: https://lore.kernel.org/netdev/618701dd023e$063de350$12b9a9f0$@gmail.com/
Tested-by: Brien Oberstein <brienpub@gmail.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Reviewed-by: Bobby Eshleman <bobbyeshleman@meta.com>
Link: https://patch.msgid.link/20260708102904.50732-2-sgarzare@redhat.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/vmw_vsock/virtio_transport_common.c | 165 +++++++++++++++++++++++++++++++-
1 file changed, 164 insertions(+), 1 deletion(-)
--- a/net/vmw_vsock/virtio_transport_common.c
+++ b/net/vmw_vsock/virtio_transport_common.c
@@ -26,6 +26,13 @@
/* Threshold for detecting small packets to copy */
#define GOOD_COPY_LEN 128
+/* Max payload that can be collapsed into a single linear skb, using the same
+ * allocation threshold as virtio_vsock_alloc_skb() to avoid adding pressure
+ * on the page allocator.
+ */
+#define MAX_COLLAPSE_LEN \
+ SKB_MAX_ORDER(VIRTIO_VSOCK_SKB_HEADROOM, PAGE_ALLOC_COSTLY_ORDER)
+
static void virtio_transport_cancel_close_work(struct vsock_sock *vsk,
bool cancel_timeout);
static s64 virtio_transport_has_space(struct virtio_vsock_sock *vvs);
@@ -423,6 +430,145 @@ static int virtio_transport_send_pkt_inf
return ret;
}
+static bool virtio_transport_can_collapse(struct sk_buff *skb)
+{
+ /* skbs that are partially consumed, mark a SEQPACKET message boundary,
+ * or are already large enough should not be collapsed: they either
+ * need special accounting, carry protocol state, or already have a
+ * good data-to-overhead ratio.
+ */
+ if (VIRTIO_VSOCK_SKB_CB(skb)->offset)
+ return false;
+ if (le32_to_cpu(virtio_vsock_hdr(skb)->flags) & VIRTIO_VSOCK_SEQ_EOM)
+ return false;
+ if (skb->len >= MAX_COLLAPSE_LEN)
+ return false;
+ return true;
+}
+
+/* Iterate through the packets in the queue starting from the current skb to
+ * count the number of bytes we can collapse.
+ */
+static unsigned int
+virtio_transport_collapse_size(struct sk_buff *skb, struct sk_buff_head *queue)
+{
+ unsigned int target = skb->len - VIRTIO_VSOCK_SKB_CB(skb)->offset;
+
+ while ((skb = skb_peek_next(skb, queue)) &&
+ virtio_transport_can_collapse(skb)) {
+ unsigned int len = skb->len - VIRTIO_VSOCK_SKB_CB(skb)->offset;
+
+ if (len > MAX_COLLAPSE_LEN - target)
+ return target;
+
+ target += len;
+ }
+
+ return target;
+}
+
+/* Called under lock_sock to compact the receive queue by merging small skbs.
+ * @min_to_free: minimum number of skbs to eliminate from the queue. May free
+ * more to fill each collapsed skb to capacity.
+ */
+static void
+virtio_transport_collapse_rx_queue(struct virtio_vsock_sock *vvs,
+ u32 min_to_free)
+{
+ struct sk_buff *skb, *next_skb, *new_skb = NULL;
+ struct sk_buff_head new_queue;
+ u32 saved = 0;
+
+ __skb_queue_head_init(&new_queue);
+
+ skb_queue_walk_safe(&vvs->rx_queue, skb, next_skb) {
+ struct virtio_vsock_hdr *hdr = virtio_vsock_hdr(skb);
+ u32 src_off = VIRTIO_VSOCK_SKB_CB(skb)->offset;
+ u32 src_len = skb->len - src_off;
+ bool keep;
+
+ keep = !virtio_transport_can_collapse(skb);
+ if (keep) {
+ /* Finalize pending collapsed skb to preserve packet
+ * ordering.
+ */
+ if (new_skb) {
+ __skb_queue_tail(&new_queue, new_skb);
+ new_skb = NULL;
+ saved--;
+ }
+ goto next;
+ }
+
+ /* Finalize if this packet won't fit in the remaining tailroom,
+ * so we can allocate a right-sized new_skb.
+ */
+ if (new_skb && src_len > skb_tailroom(new_skb)) {
+ __skb_queue_tail(&new_queue, new_skb);
+ new_skb = NULL;
+ saved--;
+ }
+
+ if (!new_skb) {
+ unsigned int alloc_size;
+
+ /* Check after finalizing to opportunistically fill
+ * each collapsed skb to capacity, merging more skbs
+ * than strictly required.
+ */
+ if (saved >= min_to_free)
+ break;
+
+ alloc_size = virtio_transport_collapse_size(skb, &vvs->rx_queue);
+
+ /* Only this skb's data is eligible, nothing to merge
+ * with. Keep as-is.
+ */
+ if (alloc_size <= src_len) {
+ keep = true;
+ goto next;
+ }
+
+ new_skb = virtio_vsock_alloc_linear_skb(alloc_size +
+ VIRTIO_VSOCK_SKB_HEADROOM, GFP_KERNEL);
+ if (!new_skb)
+ break;
+
+ memcpy(virtio_vsock_hdr(new_skb), hdr,
+ sizeof(struct virtio_vsock_hdr));
+ virtio_vsock_hdr(new_skb)->len = 0;
+ }
+
+ /* Cannot fail since src_off/src_len are within bounds, but if
+ * it does, discard new_skb to avoid queuing corrupted data.
+ */
+ if (WARN_ON_ONCE(skb_copy_bits(skb, src_off,
+ skb_put(new_skb, src_len),
+ src_len))) {
+ kfree_skb(new_skb);
+ new_skb = NULL;
+ break;
+ }
+
+ le32_add_cpu(&virtio_vsock_hdr(new_skb)->len, src_len);
+ virtio_vsock_hdr(new_skb)->flags |= hdr->flags;
+
+next:
+ __skb_unlink(skb, &vvs->rx_queue);
+ if (keep) {
+ __skb_queue_tail(&new_queue, skb);
+ } else {
+ consume_skb(skb);
+ saved++;
+ }
+ }
+
+ if (new_skb)
+ __skb_queue_tail(&new_queue, new_skb);
+
+ skb_queue_splice(&new_queue, &vvs->rx_queue);
+}
+
static bool virtio_transport_inc_rx_pkt(struct virtio_vsock_sock *vvs,
u32 len)
{
@@ -1359,12 +1505,29 @@ virtio_transport_recv_enqueue(struct vso
{
struct virtio_vsock_sock *vvs = vsk->trans;
bool can_enqueue, free_pkt = false;
+ u32 len, queue_max, queue_len;
struct virtio_vsock_hdr *hdr;
- u32 len;
hdr = virtio_vsock_hdr(skb);
len = le32_to_cpu(hdr->len);
+ /* virtio_transport_inc_rx_pkt() rejects packets when the per-skb
+ * overhead (skb_queue_len * SKB_TRUESIZE(0)) exceeds buf_alloc.
+ * Proactively collapse the queue before that happens.
+ * No rx_lock needed: lock_sock is held by caller, preventing
+ * concurrent enqueue or dequeue.
+ */
+ queue_max = vvs->buf_alloc / SKB_TRUESIZE(0);
+ queue_len = skb_queue_len(&vvs->rx_queue);
+ if (queue_len >= queue_max) {
+ /* Walking a large queue may take a significant amount of time
+ * and cache misses, causing traffic burstiness. Limit the
+ * collapse to freeing room for this packet and the next one.
+ * It may free more to fill each collapsed skb to capacity.
+ */
+ virtio_transport_collapse_rx_queue(vvs, queue_len + 2 - queue_max);
+ }
+
spin_lock_bh(&vvs->rx_lock);
can_enqueue = virtio_transport_inc_rx_pkt(vvs, len);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 434/602] vxlan: mdb: Fix source list corruption on a failed replace
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (432 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 433/602] vsock/virtio: collapse receive queue under memory pressure Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 435/602] drm/amd/pm: fix amdgpu_pm_info power display units Greg Kroah-Hartman
` (171 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, James Raphael Tiovalen, Ido Schimmel,
Antoine Tenart, Nikolay Aleksandrov, Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: James Raphael Tiovalen <jamestiotio@gmail.com>
commit dcd9b465965422b9654f6026e8a2fa8984f74c3c upstream.
When replacing the source list of an MDB remote entry, all existing
sources are first marked for deletion and vxlan_mdb_remote_srcs_add()
is then called to add the new source list. Sources present in the new
list have their deletion mark cleared, and any sources left marked
afterwards are removed.
If vxlan_mdb_remote_srcs_add() fails partway through, its error path
deletes all entries on the remote's source list. That rollback is only
correct for its other caller, vxlan_mdb_remote_add(), where the remote
was just allocated and the list contains solely entries added during
the call. On the replace path the list also holds pre-existing sources,
so a failed replace tears them down together with their (S, G)
forwarding entries instead of leaving the entry unchanged.
This is reachable from an existing (*, G) remote. An EXCLUDE filter
that loses sources starts forwarding traffic that should be blocked,
while an INCLUDE filter that loses sources drops traffic that should be
forwarded.
Mark entries created during the current pass with a new
VXLAN_SGRP_F_NEW flag. On failure, delete only those entries and clear
the deletion mark on the pre-existing ones, so a failed replace leaves
the source list untouched. Retain the flag until the whole operation
succeeds and then clear it. Also stop vxlan_mdb_remote_src_add() from
deleting a pre-existing entry it only looked up when adding that
entry's forwarding entry fails.
Fixes: a3a48de5eade ("vxlan: mdb: Add MDB control path support")
Cc: stable@vger.kernel.org
Signed-off-by: James Raphael Tiovalen <jamestiotio@gmail.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Reviewed-by: Antoine Tenart <atenart@kernel.org>
Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
Link: https://patch.msgid.link/20260720160428.249356-1-jamestiotio@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/vxlan/vxlan_mdb.c | 30 ++++++++++++++++++------------
1 file changed, 18 insertions(+), 12 deletions(-)
--- a/drivers/net/vxlan/vxlan_mdb.c
+++ b/drivers/net/vxlan/vxlan_mdb.c
@@ -42,6 +42,7 @@ struct vxlan_mdb_remote {
};
#define VXLAN_SGRP_F_DELETE BIT(0)
+#define VXLAN_SGRP_F_NEW BIT(1)
struct vxlan_mdb_src_entry {
struct hlist_node node;
@@ -844,6 +845,7 @@ vxlan_mdb_remote_src_add(const struct vx
ent = vxlan_mdb_remote_src_entry_add(remote, &src->addr);
if (!ent)
return -ENOMEM;
+ ent->flags |= VXLAN_SGRP_F_NEW;
} else if (!(cfg->nlflags & NLM_F_REPLACE)) {
NL_SET_ERR_MSG_MOD(extack, "Source entry already exists");
return -EEXIST;
@@ -853,15 +855,16 @@ vxlan_mdb_remote_src_add(const struct vx
if (err)
goto err_src_del;
- /* Clear flags in case source entry was marked for deletion as part of
- * replace flow.
+ /* Clear the deletion mark so the entry survives the replace sweep.
+ * The new mark is retained until the whole operation succeeds.
*/
- ent->flags = 0;
+ ent->flags &= ~VXLAN_SGRP_F_DELETE;
return 0;
err_src_del:
- vxlan_mdb_remote_src_entry_del(ent);
+ if (ent->flags & VXLAN_SGRP_F_NEW)
+ vxlan_mdb_remote_src_entry_del(ent);
return err;
}
@@ -889,11 +892,19 @@ static int vxlan_mdb_remote_srcs_add(con
goto err_src_del;
}
+ hlist_for_each_entry(ent, &remote->src_list, node)
+ ent->flags &= ~VXLAN_SGRP_F_NEW;
+
return 0;
err_src_del:
- hlist_for_each_entry_safe(ent, tmp, &remote->src_list, node)
- vxlan_mdb_remote_src_del(cfg->vxlan, &cfg->group, remote, ent);
+ hlist_for_each_entry_safe(ent, tmp, &remote->src_list, node) {
+ if (ent->flags & VXLAN_SGRP_F_NEW)
+ vxlan_mdb_remote_src_del(cfg->vxlan, &cfg->group, remote,
+ ent);
+ else
+ ent->flags &= ~VXLAN_SGRP_F_DELETE;
+ }
return err;
}
@@ -1069,7 +1080,7 @@ vxlan_mdb_remote_srcs_replace(const stru
err = vxlan_mdb_remote_srcs_add(cfg, remote, extack);
if (err)
- goto err_clear_delete;
+ return err;
hlist_for_each_entry_safe(ent, tmp, &remote->src_list, node) {
if (ent->flags & VXLAN_SGRP_F_DELETE)
@@ -1078,11 +1089,6 @@ vxlan_mdb_remote_srcs_replace(const stru
}
return 0;
-
-err_clear_delete:
- hlist_for_each_entry(ent, &remote->src_list, node)
- ent->flags &= ~VXLAN_SGRP_F_DELETE;
- return err;
}
static int vxlan_mdb_remote_replace(const struct vxlan_mdb_config *cfg,
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 435/602] drm/amd/pm: fix amdgpu_pm_info power display units
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (433 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 434/602] vxlan: mdb: Fix source list corruption on a failed replace Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 436/602] drm/amd/pm: make pp_features read-only when scpm is enabled Greg Kroah-Hartman
` (170 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Yang Wang, Asad Kamal, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yang Wang <kevinyang.wang@amd.com>
commit 238baca26a6279e688d1a156bd031390b82eb578 upstream.
amdgpu_pm_info displayed power sensor readings with the wrong fractional unit.
It treated the low byte of the raw sensor value as the decimal part of watts,
while that field represents milliwatts in the decoded value. As a result,
debugfs could report misleading SoC power when the remainder was not already
a two-digit centiwatt value.
Example with query = 0x00000354:
raw field value
---------------------
query >> 8 3 W
query & 0xff 84 mW
decoded power 3084 mW
output value
---------------------
before 3.84 W
after 3.08 W
Fixes: f0b8f65b4825 ("drm/amd/amdgpu: fix the GPU power print error in pm info")
Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Asad Kamal <asad.kamal@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 01992b121fb652c753d37e0c1427a2d1a557d2b1)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/pm/amdgpu_pm.c | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
--- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
@@ -40,6 +40,8 @@
#define DEVICE_ATTR_IS(_name) (attr_id == device_attr_id__##_name)
+#define power_2_mwatt(power) (((power) >> 8) * 1000 + ((power) & 0xff))
+
struct od_attribute {
struct kobj_attribute attribute;
struct list_head entry;
@@ -3200,7 +3202,6 @@ static int amdgpu_hwmon_get_power(struct
enum amd_pp_sensors sensor)
{
struct amdgpu_device *adev = dev_get_drvdata(dev);
- unsigned int uw;
u32 query = 0;
int r;
@@ -3209,9 +3210,7 @@ static int amdgpu_hwmon_get_power(struct
return r;
/* convert to microwatts */
- uw = (query >> 8) * 1000000 + (query & 0xff) * 1000;
-
- return uw;
+ return power_2_mwatt(query) * 1000;
}
static ssize_t amdgpu_hwmon_show_power_avg(struct device *dev,
@@ -4607,7 +4606,7 @@ static int amdgpu_debugfs_pm_info_pp(str
{
uint32_t mp1_ver = amdgpu_ip_version(adev, MP1_HWIP, 0);
uint32_t gc_ver = amdgpu_ip_version(adev, GC_HWIP, 0);
- uint32_t value;
+ uint32_t value, mwatt, centiwatt;
uint64_t value64 = 0;
uint32_t query = 0;
int size;
@@ -4632,17 +4631,21 @@ static int amdgpu_debugfs_pm_info_pp(str
seq_printf(m, "\t%u mV (VDDNB)\n", value);
size = sizeof(uint32_t);
if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_AVG_POWER, (void *)&query, &size)) {
+ mwatt = power_2_mwatt(query);
+ centiwatt = DIV_ROUND_CLOSEST(mwatt, 10);
if (adev->flags & AMD_IS_APU)
- seq_printf(m, "\t%u.%02u W (average SoC including CPU)\n", query >> 8, query & 0xff);
+ seq_printf(m, "\t%u.%02u W (average SoC including CPU)\n", centiwatt / 100, centiwatt % 100);
else
- seq_printf(m, "\t%u.%02u W (average SoC)\n", query >> 8, query & 0xff);
+ seq_printf(m, "\t%u.%02u W (average SoC)\n", centiwatt / 100, centiwatt % 100);
}
size = sizeof(uint32_t);
if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_INPUT_POWER, (void *)&query, &size)) {
+ mwatt = power_2_mwatt(query);
+ centiwatt = DIV_ROUND_CLOSEST(mwatt, 10);
if (adev->flags & AMD_IS_APU)
- seq_printf(m, "\t%u.%02u W (current SoC including CPU)\n", query >> 8, query & 0xff);
+ seq_printf(m, "\t%u.%02u W (current SoC including CPU)\n", centiwatt / 100, centiwatt % 100);
else
- seq_printf(m, "\t%u.%02u W (current SoC)\n", query >> 8, query & 0xff);
+ seq_printf(m, "\t%u.%02u W (current SoC)\n", centiwatt / 100, centiwatt % 100);
}
size = sizeof(value);
seq_printf(m, "\n");
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 436/602] drm/amd/pm: make pp_features read-only when scpm is enabled
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (434 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 435/602] drm/amd/pm: fix amdgpu_pm_info power display units Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 437/602] drm/amdgpu/gfx10: replace BUG_ON() with WARN_ON() Greg Kroah-Hartman
` (169 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Yang Wang, Asad Kamal, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yang Wang <kevinyang.wang@amd.com>
commit 53c78ab388bfc1a4d72e756815d0db0a842c812e upstream.
SCPM owns power feature control when enabled.
Make pp_features read-only during sysfs setup by clearing its write bits
and store callback.
Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Asad Kamal <asad.kamal@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 6a5786e191fdce36c5db170e5209cf609e8f0087)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/pm/amdgpu_pm.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
@@ -2509,6 +2509,11 @@ static int default_attr_update(struct am
gc_ver != IP_VERSION(9, 4, 3)) ||
gc_ver < IP_VERSION(9, 0, 0))
*states = ATTR_STATE_UNSUPPORTED;
+
+ if (adev->scpm_enabled) {
+ dev_attr->attr.mode &= ~S_IWUGO;
+ dev_attr->store = NULL;
+ }
} else if (DEVICE_ATTR_IS(gpu_metrics)) {
if (gc_ver < IP_VERSION(9, 1, 0))
*states = ATTR_STATE_UNSUPPORTED;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 437/602] drm/amdgpu/gfx10: replace BUG_ON() with WARN_ON()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (435 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 436/602] drm/amd/pm: make pp_features read-only when scpm is enabled Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 438/602] drm/amdgpu/gfx11: " Greg Kroah-Hartman
` (168 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Vitaly Prosyak, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <alexander.deucher@amd.com>
commit d06c4173a7c38c7a39e98859f839ce714c7af2c9 upstream.
There's no need to crash the kernel for these cases.
Reviewed-by: Vitaly Prosyak <vitaly.prosyak@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit ac6f00beb658239bced4aaed9efbb04a35348d48)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
@@ -3934,7 +3934,7 @@ static void gfx_v10_0_wait_reg_mem(struc
WAIT_REG_MEM_ENGINE(eng_sel)));
if (mem_space)
- BUG_ON(addr0 & 0x3); /* Dword align */
+ WARN_ON(addr0 & 0x3); /* Dword align */
amdgpu_ring_write(ring, addr0);
amdgpu_ring_write(ring, addr1);
amdgpu_ring_write(ring, ref);
@@ -8565,7 +8565,7 @@ static void gfx_v10_0_ring_emit_ib_gfx(s
}
amdgpu_ring_write(ring, header);
- BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
+ WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
amdgpu_ring_write(ring,
#ifdef __BIG_ENDIAN
(2 << 0) |
@@ -8600,7 +8600,7 @@ static void gfx_v10_0_ring_emit_ib_compu
}
amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
- BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
+ WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
amdgpu_ring_write(ring,
#ifdef __BIG_ENDIAN
(2 << 0) |
@@ -8633,9 +8633,9 @@ static void gfx_v10_0_ring_emit_fence(st
* aligned if only send 32bit data low (discard data high)
*/
if (write64bit)
- BUG_ON(addr & 0x7);
+ WARN_ON(addr & 0x7);
else
- BUG_ON(addr & 0x3);
+ WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -8683,9 +8683,6 @@ static void gfx_v10_0_ring_emit_fence_ki
{
struct amdgpu_device *adev = ring->adev;
- /* we only allocate 32bit for each seq wb address */
- BUG_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
-
/* write fence seq to the "addr" */
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 438/602] drm/amdgpu/gfx11: replace BUG_ON() with WARN_ON()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (436 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 437/602] drm/amdgpu/gfx10: replace BUG_ON() with WARN_ON() Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 439/602] drm/amdgpu/gfx12: " Greg Kroah-Hartman
` (167 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Vitaly Prosyak, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <alexander.deucher@amd.com>
commit 0eebcab1ea2a77f086a04108f386f82ee3496022 upstream.
There's no need to crash the kernel for these cases.
Reviewed-by: Vitaly Prosyak <vitaly.prosyak@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit daa62107452d2451787c4248ca38fa2d1a0cbefd)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -496,7 +496,7 @@ static void gfx_v11_0_wait_reg_mem(struc
WAIT_REG_MEM_ENGINE(eng_sel)));
if (mem_space)
- BUG_ON(addr0 & 0x3); /* Dword align */
+ WARN_ON(addr0 & 0x3); /* Dword align */
amdgpu_ring_write(ring, addr0);
amdgpu_ring_write(ring, addr1);
amdgpu_ring_write(ring, ref);
@@ -5673,7 +5673,7 @@ static void gfx_v11_0_ring_emit_ib_gfx(s
control |= 0x400000;
amdgpu_ring_write(ring, header);
- BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
+ WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
amdgpu_ring_write(ring,
#ifdef __BIG_ENDIAN
(2 << 0) |
@@ -5712,7 +5712,7 @@ static void gfx_v11_0_ring_emit_ib_compu
}
amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
- BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
+ WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
amdgpu_ring_write(ring,
#ifdef __BIG_ENDIAN
(2 << 0) |
@@ -5745,9 +5745,9 @@ static void gfx_v11_0_ring_emit_fence(st
* aligned if only send 32bit data low (discard data high)
*/
if (write64bit)
- BUG_ON(addr & 0x7);
+ WARN_ON(addr & 0x7);
else
- BUG_ON(addr & 0x3);
+ WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -5805,9 +5805,6 @@ static void gfx_v11_0_ring_emit_fence_ki
{
struct amdgpu_device *adev = ring->adev;
- /* we only allocate 32bit for each seq wb address */
- BUG_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
-
/* write fence seq to the "addr" */
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 439/602] drm/amdgpu/gfx12: replace BUG_ON() with WARN_ON()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (437 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 438/602] drm/amdgpu/gfx11: " Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 440/602] drm/amdgpu/gfx8: drop unecessary BUG_ON() Greg Kroah-Hartman
` (166 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Vitaly Prosyak, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <alexander.deucher@amd.com>
commit cd3b3efa1ced05528d9128755338baa62a6b562d upstream.
There's no need to crash the kernel for these cases.
Reviewed-by: Vitaly Prosyak <vitaly.prosyak@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit f952076f76d62f783e8ba4995a7c400d39354ccf)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
@@ -409,7 +409,7 @@ static void gfx_v12_0_wait_reg_mem(struc
WAIT_REG_MEM_ENGINE(eng_sel)));
if (mem_space)
- BUG_ON(addr0 & 0x3); /* Dword align */
+ WARN_ON(addr0 & 0x3); /* Dword align */
amdgpu_ring_write(ring, addr0);
amdgpu_ring_write(ring, addr1);
amdgpu_ring_write(ring, ref);
@@ -4338,7 +4338,7 @@ static void gfx_v12_0_ring_emit_ib_gfx(s
control |= 0x400000;
amdgpu_ring_write(ring, header);
- BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
+ WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
amdgpu_ring_write(ring,
#ifdef __BIG_ENDIAN
(2 << 0) |
@@ -4361,7 +4361,7 @@ static void gfx_v12_0_ring_emit_ib_compu
control |= 0x40000000;
amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
- BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
+ WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
amdgpu_ring_write(ring,
#ifdef __BIG_ENDIAN
(2 << 0) |
@@ -4392,9 +4392,9 @@ static void gfx_v12_0_ring_emit_fence(st
* aligned if only send 32bit data low (discard data high)
*/
if (write64bit)
- BUG_ON(addr & 0x7);
+ WARN_ON(addr & 0x7);
else
- BUG_ON(addr & 0x3);
+ WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -4446,9 +4446,6 @@ static void gfx_v12_0_ring_emit_fence_ki
{
struct amdgpu_device *adev = ring->adev;
- /* we only allocate 32bit for each seq wb address */
- BUG_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
-
/* write fence seq to the "addr" */
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 440/602] drm/amdgpu/gfx8: drop unecessary BUG_ON()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (438 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 439/602] drm/amdgpu/gfx12: " Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 441/602] drm/amdgpu/gfx9.4.3: replace BUG_ON() with WARN_ON() Greg Kroah-Hartman
` (165 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Vitaly Prosyak, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <alexander.deucher@amd.com>
commit 84a1a8a952ab4b8c23c5dd1f2eea4049cb4914f5 upstream.
There's no need to crash the kernel for this case.
Reviewed-by: Vitaly Prosyak <vitaly.prosyak@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 4d7c25208ca612b754f3bf39e9f16e725b828891)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 3 ---
1 file changed, 3 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -6272,9 +6272,6 @@ static void gfx_v8_0_ring_emit_fence_com
static void gfx_v8_0_ring_emit_fence_kiq(struct amdgpu_ring *ring, u64 addr,
u64 seq, unsigned int flags)
{
- /* we only allocate 32bit for each seq wb address */
- BUG_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
-
/* write fence seq to the "addr" */
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 441/602] drm/amdgpu/gfx9.4.3: replace BUG_ON() with WARN_ON()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (439 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 440/602] drm/amdgpu/gfx8: drop unecessary BUG_ON() Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 442/602] drm/amdgpu/gfx9: " Greg Kroah-Hartman
` (164 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Vitaly Prosyak, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <alexander.deucher@amd.com>
commit 00f4050f7c367d7bdce347ca279ce467c434cf15 upstream.
There's no need to crash the kernel for these cases.
Reviewed-by: Vitaly Prosyak <vitaly.prosyak@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 5676593d08998d7a6d9e2d51d6b54b3820e3755c)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
@@ -409,7 +409,7 @@ static void gfx_v9_4_3_wait_reg_mem(stru
WAIT_REG_MEM_ENGINE(eng_sel)));
if (mem_space)
- BUG_ON(addr0 & 0x3); /* Dword align */
+ WARN_ON(addr0 & 0x3); /* Dword align */
amdgpu_ring_write(ring, addr0);
amdgpu_ring_write(ring, addr1);
amdgpu_ring_write(ring, ref);
@@ -2882,7 +2882,7 @@ static void gfx_v9_4_3_ring_emit_ib_comp
}
amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
- BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
+ WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
amdgpu_ring_write(ring,
#ifdef __BIG_ENDIAN
(2 << 0) |
@@ -2916,9 +2916,9 @@ static void gfx_v9_4_3_ring_emit_fence(s
* aligned if only send 32bit data low (discard data high)
*/
if (write64bit)
- BUG_ON(addr & 0x7);
+ WARN_ON(addr & 0x7);
else
- BUG_ON(addr & 0x3);
+ WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -2978,9 +2978,6 @@ static void gfx_v9_4_3_ring_emit_fence_k
{
struct amdgpu_device *adev = ring->adev;
- /* we only allocate 32bit for each seq wb address */
- BUG_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
-
/* write fence seq to the "addr" */
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 442/602] drm/amdgpu/gfx9: replace BUG_ON() with WARN_ON()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (440 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 441/602] drm/amdgpu/gfx9.4.3: replace BUG_ON() with WARN_ON() Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 443/602] drm/amdgpu/sdma4.4.2: " Greg Kroah-Hartman
` (163 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Vitaly Prosyak, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <alexander.deucher@amd.com>
commit 6302be10b521f5106ce01eb5a724b9e7945a5061 upstream.
There's no need to crash the kernel for these cases.
Reviewed-by: Vitaly Prosyak <vitaly.prosyak@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit b71604f8685b0eba07866f4e8dc30f93e1931054)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
@@ -1156,7 +1156,7 @@ static void gfx_v9_0_wait_reg_mem(struct
WAIT_REG_MEM_ENGINE(eng_sel)));
if (mem_space)
- BUG_ON(addr0 & 0x3); /* Dword align */
+ WARN_ON(addr0 & 0x3); /* Dword align */
amdgpu_ring_write(ring, addr0);
amdgpu_ring_write(ring, addr1);
amdgpu_ring_write(ring, ref);
@@ -5415,7 +5415,7 @@ static void gfx_v9_0_ring_emit_ib_gfx(st
}
amdgpu_ring_write(ring, header);
- BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
+ WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
amdgpu_ring_write(ring,
#ifdef __BIG_ENDIAN
(2 << 0) |
@@ -5527,7 +5527,7 @@ static void gfx_v9_0_ring_emit_ib_comput
}
amdgpu_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
- BUG_ON(ib->gpu_addr & 0x3); /* Dword align */
+ WARN_ON(ib->gpu_addr & 0x3); /* Dword align */
amdgpu_ring_write(ring,
#ifdef __BIG_ENDIAN
(2 << 0) |
@@ -5568,9 +5568,9 @@ static void gfx_v9_0_ring_emit_fence(str
* aligned if only send 32bit data low (discard data high)
*/
if (write64bit)
- BUG_ON(addr & 0x7);
+ WARN_ON(addr & 0x7);
else
- BUG_ON(addr & 0x3);
+ WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, lower_32_bits(seq));
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 443/602] drm/amdgpu/sdma4.4.2: replace BUG_ON() with WARN_ON()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (441 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 442/602] drm/amdgpu/gfx9: " Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 444/602] drm/amdgpu/vce: fix integer overflow in image size Greg Kroah-Hartman
` (162 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Vitaly Prosyak, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <alexander.deucher@amd.com>
commit 40cdbe9fa424cc6264a7aed93a04bd7d69109d9e upstream.
There's no need to crash the kernel for these cases.
Reviewed-by: Vitaly Prosyak <vitaly.prosyak@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit fa4f86a148271e325e95287630a3a15a9cd35fdc)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
@@ -450,7 +450,7 @@ static void sdma_v4_4_2_ring_emit_fence(
/* write the fence */
amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE));
/* zero in first two bits */
- BUG_ON(addr & 0x3);
+ WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, lower_32_bits(seq));
@@ -460,7 +460,7 @@ static void sdma_v4_4_2_ring_emit_fence(
addr += 4;
amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE));
/* zero in first two bits */
- BUG_ON(addr & 0x3);
+ WARN_ON(addr & 0x3);
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(seq));
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 444/602] drm/amdgpu/vce: fix integer overflow in image size
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (442 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 443/602] drm/amdgpu/sdma4.4.2: " Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 445/602] drm/amdgpu/vcn4: avoid rereading IB param length Greg Kroah-Hartman
` (161 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Boyuan Zhang, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Boyuan Zhang <boyuan.zhang@amd.com>
commit 186bfdc4e26d019b2e7570cb121964a1d89b2e5b upstream.
Fix a security vulnerability where malicious VCE command streams
with oversized dimensions (e.g. 65536×65536) cause 32-bit integer
overflow, wrapping the calculated buffer size to 0. This bypasses
validation and allows GPU firmware to perform out-of-bound memory
access.
The fix uses 64-bit arithmetic to detect overflow and rejects
invalid dimensions before they reach the hardware.
V2: remove redundant check
V3: modify max height value
V4: remove size64
Signed-off-by: Boyuan Zhang <boyuan.zhang@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit cbe408dba581755ad1279a487ec786d8927d778d)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
@@ -852,9 +852,20 @@ int amdgpu_vce_ring_parse_cs(struct amdg
goto out;
}
- *size = amdgpu_ib_get_value(ib, idx + 8) *
- amdgpu_ib_get_value(ib, idx + 10) *
- 8 * 3 / 2;
+ uint32_t width, height;
+ width = amdgpu_ib_get_value(ib, idx + 8);
+ height = amdgpu_ib_get_value(ib, idx + 10);
+
+ if (width == 0 || height == 0 ||
+ width > 4096 || height > 2304) {
+ DRM_ERROR("invalid VCE image size: %ux%u\n",
+ width, height);
+ r = -EINVAL;
+ goto out;
+ }
+
+ *size = width * height * 8 * 3 / 2;
+
break;
case 0x04000001: /* config extension */
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 445/602] drm/amdgpu/vcn4: avoid rereading IB param length
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (443 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 444/602] drm/amdgpu/vce: fix integer overflow in image size Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 446/602] drm/dp_mst: Handle torn-down topology gracefully in drm_dp_mst_topology_queue_probe() Greg Kroah-Hartman
` (160 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Boyuan Zhang, David Rosca,
Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Boyuan Zhang <boyuan.zhang@amd.com>
commit 3b4082fabc67c9780b06eb959e59dd92fa79c0f0 upstream.
Reuse the parameter length returned by
vcn_v4_0_enc_find_ib_param() instead of rereading it from
the IB.
This avoids a potential TOCTOU issue if the IB contents
change between reads.
Signed-off-by: Boyuan Zhang <boyuan.zhang@amd.com>
Reviewed-by: David Rosca <david.rosca@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit dbb02b4755f8c1f3773263f2d779872c1c0c073a)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -1868,14 +1868,17 @@ out:
#define RENCODE_IB_PARAM_SESSION_INIT 0x00000003
/* return the offset in ib if id is found, -1 otherwise */
-static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int start)
+static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int start, uint32_t *length)
{
int i;
uint32_t len;
for (i = start; (len = amdgpu_ib_get_value(ib, i)) >= 8; i += len / 4) {
- if (amdgpu_ib_get_value(ib, i + 1) == id)
+ if (amdgpu_ib_get_value(ib, i + 1) == id) {
+ if (length)
+ *length = len;
return i;
+ }
}
return -1;
}
@@ -1885,14 +1888,14 @@ static int vcn_v4_0_ring_patch_cs_in_pla
struct amdgpu_ib *ib)
{
struct amdgpu_ring *ring = amdgpu_job_ring(job);
- uint32_t val;
+ uint32_t val, len;
int idx = 0, sidx;
/* The first instance can decode anything */
if (!ring->me)
return 0;
- while ((idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, idx)) >= 0) {
+ while ((idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, idx, &len)) >= 0) {
val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */
if (val == RADEON_VCN_ENGINE_TYPE_DECODE) {
uint32_t valid_buf_flag = amdgpu_ib_get_value(ib, idx + 6);
@@ -1905,12 +1908,12 @@ static int vcn_v4_0_ring_patch_cs_in_pla
amdgpu_ib_get_value(ib, idx + 8);
return vcn_v4_0_dec_msg(p, job, msg_buffer_addr);
} else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) {
- sidx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, idx);
+ sidx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, idx, NULL);
if (sidx >= 0 &&
amdgpu_ib_get_value(ib, sidx + 2) == RENCODE_ENCODE_STANDARD_AV1)
return vcn_v4_0_limit_sched(p, job);
}
- idx += amdgpu_ib_get_value(ib, idx) / 4;
+ idx += len / 4;
}
return 0;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 446/602] drm/dp_mst: Handle torn-down topology gracefully in drm_dp_mst_topology_queue_probe()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (444 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 445/602] drm/amdgpu/vcn4: avoid rereading IB param length Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 447/602] drm/amdgpu: fix division by zero with invalid uvd dimensions Greg Kroah-Hartman
` (159 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Imre Deak, Lyude Paul, intel-gfx,
dri-devel, Jonas Emilsson, Luca Coelho, Maarten Lankhorst
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luca Coelho <luciano.coelho@intel.com>
commit 613059875958e7b217b250ed14c3b189f9488421 upstream.
A hotplug or link-loss event can tear down the MST topology
(setting mgr->mst_state = false and mgr->mst_primary = NULL) concurrently
with a caller invoking drm_dp_mst_topology_queue_probe(). Since the check
is already performed under mgr->lock, the condition is not a programming
error but a valid race -- the topology was valid when the caller decided
to call this function, but was torn down before the lock was acquired.
Replace the drm_WARN_ON() with a graceful early return. This eliminates
spurious kernel warnings and the resulting compositor crashes observed
when connecting/disconnecting DP MST monitors, while keeping the correct
behavior of doing nothing when MST is not active. A drm_dbg_mst() trace
is added so the skipped probe remains observable under MST debug logging.
The existing WARN_ON(mgr->mst_primary) in drm_dp_mst_topology_mgr_set_mst()
already catches the case where the topology is initialized twice, so no
diagnostic coverage is lost.
Fixes: dbaeef363ea5 ("drm/dp_mst: Add a helper to queue a topology probe")
Cc: Imre Deak <imre.deak@intel.com>
Cc: Lyude Paul <lyude@redhat.com>
Cc: stable@vger.kernel.org
Cc: intel-gfx@lists.freedesktop.org
Cc: dri-devel@lists.freedesktop.org
Signed-off-by: Jonas Emilsson <jonas.emilsson@gmail.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/all/20260503034533.1023686-1-jonas.emilsson@gmail.com
Acked-by: Imre Deak <imre.deak@intel.com>
Link: https://patch.msgid.link/20260622140532.526722-1-luciano.coelho@intel.com
Signed-off-by: Maarten Lankhorst <dev@lankhorst.se>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/display/drm_dp_mst_topology.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -3743,8 +3743,10 @@ void drm_dp_mst_topology_queue_probe(str
{
mutex_lock(&mgr->lock);
- if (drm_WARN_ON(mgr->dev, !mgr->mst_state || !mgr->mst_primary))
+ if (!mgr->mst_state || !mgr->mst_primary) {
+ drm_dbg_kms(mgr->dev, "queue_probe skipped: topology torn down\n");
goto out_unlock;
+ }
drm_dp_mst_topology_mgr_invalidate_mstb(mgr->mst_primary);
drm_dp_mst_queue_probe_work(mgr);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 447/602] drm/amdgpu: fix division by zero with invalid uvd dimensions
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (445 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 446/602] drm/dp_mst: Handle torn-down topology gracefully in drm_dp_mst_topology_queue_probe() Greg Kroah-Hartman
@ 2026-07-30 14:13 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 448/602] drm/amdgpu: invoke pm_genpd_remove() before freeing genpd Greg Kroah-Hartman
` (158 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:13 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Boyuan Zhang, Leo Liu, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Boyuan Zhang <boyuan.zhang@amd.com>
commit 0c01c811be47e6b146552dd59bfedbea8f09b8f4 upstream.
When width or height is less than 16, width_in_mb or height_in_mb
becomes 0, leading to fs_in_mb being 0. This causes a division by
zero when calculating num_dpb_buffer in H264 and H264 Perf decode
paths.
Add validation to reject frames with width < 16 or height < 16
before performing any calculations that depend on these values.
V2: Format change - move up all vaiable definitions.
V3: Use warn_once to avoid spam.
Signed-off-by: Boyuan Zhang <boyuan.zhang@amd.com>
Reviewed-by: Leo Liu <leo.liu@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 3e41d26c70b0a459d041cc19482a226c4b7423cb)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -654,6 +654,14 @@ static int amdgpu_uvd_cs_msg_decode(stru
unsigned int image_size, tmp, min_dpb_size, num_dpb_buffer;
unsigned int min_ctx_size = ~0;
+ /* Reject invalid dimensions to prevent division by zero */
+ if (width < 16 || height < 16) {
+ dev_WARN_ONCE(adev->dev, 1,
+ "Invalid UVD decoding dimensions (%dx%d)!\n",
+ width, height);
+ return -EINVAL;
+ }
+
image_size = width * height;
image_size += image_size / 2;
image_size = ALIGN(image_size, 1024);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 448/602] drm/amdgpu: invoke pm_genpd_remove() before freeing genpd
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (446 preceding siblings ...)
2026-07-30 14:13 ` [PATCH 6.12 447/602] drm/amdgpu: fix division by zero with invalid uvd dimensions Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 449/602] drm/amdgpu: fix aperture mapping leak Greg Kroah-Hartman
` (157 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Ce Sun, Tao Zhou, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ce Sun <cesun102@amd.com>
commit 28c9b3c5dc35cc790d11e26ca3fc6e068be63998 upstream.
Call pm_genpd_remove() to unregister from global list prior to releasing
acp_genpd memory, and clear the pointer after free.
Signed-off-by: Ce Sun <cesun102@amd.com>
Reviewed-by: Tao Zhou <tao.zhou1@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit cd8650d7a91ee8b768e202354672553faa5cc1f2)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
@@ -559,7 +559,9 @@ static int acp_hw_fini(void *handle)
mfd_remove_devices(adev->acp.parent);
kfree(adev->acp.acp_res);
+ pm_genpd_remove(&adev->acp.acp_genpd->gpd);
kfree(adev->acp.acp_genpd);
+ adev->acp.acp_genpd = NULL;
kfree(adev->acp.acp_cell);
return 0;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 449/602] drm/amdgpu: fix aperture mapping leak
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (447 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 448/602] drm/amdgpu: invoke pm_genpd_remove() before freeing genpd Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 450/602] drm/amd/pm: fix smu13 power limit range calculation Greg Kroah-Hartman
` (156 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Asad Kamal, Christian König,
Lijo Lazar, Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Asad Kamal <asad.kamal@amd.com>
commit ea772a440d56b285f4d491affac50ecd41f6b402 upstream.
amdgpu_pci_remove() calls drm_dev_unplug() before invoking the driver
fini routines. This causes drm_dev_enter() in amdgpu_ttm_fini() to
always return false, so iounmap(aper_base_kaddr) never runs on normal
driver unload, leaving an orphaned entry in the x86 PAT interval tree.
On connected_to_cpu hardware, the aperture is mapped write-back (WB) via
ioremap_cache(). On reload, IP discovery calls memremap(..., MEMREMAP_WC)
over the same range. The WC vs WB conflict causes:
ioremap error for 0x..., requested 0x1, got 0x0
amdgpu: discovery failed: -2
Fix by switching to devres-managed mappings so cleanup is guaranteed
regardless of drm_dev_enter() state:
- connected_to_cpu path: devm_memremap(MEMREMAP_WB). For
IORESOURCE_SYSTEM_RAM ranges this takes the try_ram_remap() shortcut,
returning __va(offset) from the existing kernel direct map. No new
ioremap VA or PAT entry is created, so there is nothing to orphan.
- dGPU path: devm_ioremap_wc() registers iounmap() as a devres action,
guaranteeing cleanup at device_del() time.
Also remove iounmap(aper_base_kaddr) from amdgpu_device_unmap_mmio()
since the mapping is now devres-owned.
v2: Remove redundant x86_64 guard (Lijo)
Fixes: 9d0af8b4def0 ("drm/amdgpu: pre-map device buffer as cached for A+A config")
Signed-off-by: Asad Kamal <asad.kamal@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit d871e99879cb5fd1fa798b006b4888887e63a17a)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 -
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 36 ++++++++++++-----------------
2 files changed, 16 insertions(+), 22 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -4635,8 +4635,6 @@ static void amdgpu_device_unmap_mmio(str
iounmap(adev->rmmio);
adev->rmmio = NULL;
- if (adev->mman.aper_base_kaddr)
- iounmap(adev->mman.aper_base_kaddr);
adev->mman.aper_base_kaddr = NULL;
/* Memory manager related */
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -1907,18 +1907,23 @@ int amdgpu_ttm_init(struct amdgpu_device
/* Change the size here instead of the init above so only lpfn is affected */
amdgpu_ttm_set_buffer_funcs_status(adev, false);
#ifdef CONFIG_64BIT
-#ifdef CONFIG_X86
- if (adev->gmc.xgmi.connected_to_cpu)
- adev->mman.aper_base_kaddr = ioremap_cache(adev->gmc.aper_base,
- adev->gmc.visible_vram_size);
-
- else if (adev->gmc.is_app_apu)
+ if (adev->gmc.xgmi.connected_to_cpu) {
+ void *kaddr = devm_memremap(adev->dev, adev->gmc.aper_base,
+ adev->gmc.visible_vram_size,
+ MEMREMAP_WB);
+ if (IS_ERR(kaddr))
+ return PTR_ERR(kaddr);
+ adev->mman.aper_base_kaddr = (__force void __iomem *)kaddr;
+ } else if (adev->gmc.is_app_apu) {
DRM_DEBUG_DRIVER(
"No need to ioremap when real vram size is 0\n");
- else
-#endif
- adev->mman.aper_base_kaddr = ioremap_wc(adev->gmc.aper_base,
- adev->gmc.visible_vram_size);
+ } else {
+ adev->mman.aper_base_kaddr = devm_ioremap_wc(adev->dev,
+ adev->gmc.aper_base,
+ adev->gmc.visible_vram_size);
+ if (!adev->mman.aper_base_kaddr)
+ return -ENOMEM;
+ }
#endif
/*
@@ -2053,8 +2058,6 @@ int amdgpu_ttm_init(struct amdgpu_device
*/
void amdgpu_ttm_fini(struct amdgpu_device *adev)
{
- int idx;
-
if (!adev->mman.initialized)
return;
@@ -2077,14 +2080,7 @@ void amdgpu_ttm_fini(struct amdgpu_devic
amdgpu_ttm_fw_reserve_vram_fini(adev);
amdgpu_ttm_drv_reserve_vram_fini(adev);
- if (drm_dev_enter(adev_to_drm(adev), &idx)) {
-
- if (adev->mman.aper_base_kaddr)
- iounmap(adev->mman.aper_base_kaddr);
- adev->mman.aper_base_kaddr = NULL;
-
- drm_dev_exit(idx);
- }
+ adev->mman.aper_base_kaddr = NULL;
amdgpu_vram_mgr_fini(adev);
amdgpu_gtt_mgr_fini(adev);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 450/602] drm/amd/pm: fix smu13 power limit range calculation
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (448 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 449/602] drm/amdgpu: fix aperture mapping leak Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 451/602] bpf: Fix same-register dst/src OOB read and pointer leak in sock_ops Greg Kroah-Hartman
` (155 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Yang Wang, Kenneth Feng,
Alex Deucher
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yang Wang <kevinyang.wang@amd.com>
commit 220f22e1d66c1cfb63387eb1c4210f92a357c2d9 upstream.
SMU13 reports SocketPowerLimitAc/Dc as the default power limit, but
MsgLimits.Power may carry a different firmware bound for the same PPT
throttler. Using only the socket limit for both min and max can therefore
expose an incorrect power range.
Keep the socket limit as the default, but derive the range from both values:
use the lower value for the min base and the higher value for the max base
before applying OD percentages. Keep the current limit query independent
from the cap calculation.
Fixes: 1eaf26db9590 ("drm/amd/pm: fix smu13 power limit default/cap calculation")
Closes: https://gitlab.freedesktop.org/drm/amd/-/work_items/5419
Signed-off-by: Yang Wang <kevinyang.wang@amd.com>
Reviewed-by: Kenneth Feng <kenneth.feng@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit f45bbf0f62f266ed8422d84f347d75d5fca846a7)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c | 11 +++++++----
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c | 15 ++++++++-------
2 files changed, 15 insertions(+), 11 deletions(-)
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
@@ -2396,11 +2396,14 @@ static int smu_v13_0_0_get_power_limit(s
uint32_t pp_limit = smu->adev->pm.ac_power ?
skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
- uint32_t power_limit = 0, od_percent_upper = 0, od_percent_lower = 0;
+ uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
+ uint32_t min_limit = min_t(uint32_t, pp_limit, msg_limit);
+ uint32_t max_limit = max_t(uint32_t, pp_limit, msg_limit);
+ uint32_t od_percent_upper = 0, od_percent_lower = 0;
int ret;
if (current_power_limit) {
- ret = smu_v13_0_get_current_power_limit(smu, &power_limit);
+ ret = smu_v13_0_get_current_power_limit(smu, current_power_limit);
if (ret)
*current_power_limit = pp_limit;
}
@@ -2423,12 +2426,12 @@ static int smu_v13_0_0_get_power_limit(s
od_percent_upper, od_percent_lower, pp_limit);
if (max_power_limit) {
- *max_power_limit = pp_limit * (100 + od_percent_upper);
+ *max_power_limit = max_limit * (100 + od_percent_upper);
*max_power_limit /= 100;
}
if (min_power_limit) {
- *min_power_limit = pp_limit * (100 - od_percent_lower);
+ *min_power_limit = min_limit * (100 - od_percent_lower);
*min_power_limit /= 100;
}
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
@@ -2357,15 +2357,16 @@ static int smu_v13_0_7_get_power_limit(s
uint32_t pp_limit = smu->adev->pm.ac_power ?
skutable->SocketPowerLimitAc[PPT_THROTTLER_PPT0] :
skutable->SocketPowerLimitDc[PPT_THROTTLER_PPT0];
- uint32_t power_limit = 0, od_percent_upper = 0, od_percent_lower = 0;
+ uint32_t msg_limit = skutable->MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
+ uint32_t min_limit = min_t(uint32_t, pp_limit, msg_limit);
+ uint32_t max_limit = max_t(uint32_t, pp_limit, msg_limit);
+ uint32_t od_percent_upper = 0, od_percent_lower = 0;
int ret;
if (current_power_limit) {
- ret = smu_v13_0_get_current_power_limit(smu, &power_limit);
+ ret = smu_v13_0_get_current_power_limit(smu, current_power_limit);
if (ret)
- power_limit = pp_limit;
-
- *current_power_limit = power_limit;
+ *current_power_limit = pp_limit;
}
if (default_power_limit)
@@ -2386,12 +2387,12 @@ static int smu_v13_0_7_get_power_limit(s
od_percent_upper, od_percent_lower, pp_limit);
if (max_power_limit) {
- *max_power_limit = pp_limit * (100 + od_percent_upper);
+ *max_power_limit = max_limit * (100 + od_percent_upper);
*max_power_limit /= 100;
}
if (min_power_limit) {
- *min_power_limit = pp_limit * (100 - od_percent_lower);
+ *min_power_limit = min_limit * (100 - od_percent_lower);
*min_power_limit /= 100;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 451/602] bpf: Fix same-register dst/src OOB read and pointer leak in sock_ops
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (449 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 450/602] drm/amd/pm: fix smu13 power limit range calculation Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 452/602] net: qrtr: ns: Raise node count limit to 512 Greg Kroah-Hartman
` (154 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Quan Sun, Yinhao Hu, Kaiyan Mei,
Dongliang Mu, Emil Tsalapatis, Jiayuan Chen, Martin KaFai Lau,
Jakub Kicinski, Sasha Levin, Jay Wang
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiayuan Chen <jiayuan.chen@linux.dev>
[ Upstream commit 10f86a2a5c91fc4c4d001960f1c21abe52545ef6 ]
When a BPF sock_ops program accesses ctx fields with dst_reg == src_reg,
the SOCK_OPS_GET_SK() and SOCK_OPS_GET_FIELD() macros fail to zero the
destination register in the !fullsock / !locked_tcp_sock path.
Both macros borrow a temporary register to check is_fullsock /
is_locked_tcp_sock when dst_reg == src_reg, because dst_reg holds the
ctx pointer. When the check is false (e.g., TCP_NEW_SYN_RECV state with
a request_sock), dst_reg should be zeroed but is not, leaving the stale
ctx pointer:
- SOCK_OPS_GET_SK: dst_reg retains the ctx pointer, passes NULL checks
as PTR_TO_SOCKET_OR_NULL, and can be used as a bogus socket pointer,
leading to stack-out-of-bounds access in helpers like
bpf_skc_to_tcp6_sock().
- SOCK_OPS_GET_FIELD: dst_reg retains the ctx pointer which the
verifier believes is a SCALAR_VALUE, leaking a kernel pointer.
Fix both macros by:
- Changing JMP_A(1) to JMP_A(2) in the fullsock path to skip the
added instruction.
- Adding BPF_MOV64_IMM(si->dst_reg, 0) after the temp register
restore in the !fullsock path, placed after the restore because
dst_reg == src_reg means we need src_reg intact to read ctx->temp.
Fixes: fd09af010788 ("bpf: sock_ops ctx access may stomp registers in corner case")
Fixes: 84f44df664e9 ("bpf: sock_ops sk access may stomp registers when dst_reg = src_reg")
Reported-by: Quan Sun <2022090917019@std.uestc.edu.cn>
Reported-by: Yinhao Hu <dddddd@hust.edu.cn>
Reported-by: Kaiyan Mei <M202472210@hust.edu.cn>
Reported-by: Dongliang Mu <dzm91@hust.edu.cn>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
Closes: https://lore.kernel.org/bpf/6fe1243e-149b-4d3b-99c7-fcc9e2f75787@std.uestc.edu.cn/T/#u
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
Acked-by: Martin KaFai Lau <martin.lau@kernel.org>
Link: https://patch.msgid.link/20260407022720.162151-2-jiayuan.chen@linux.dev
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Jay Wang <wanjay@amazon.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/core/filter.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/net/core/filter.c b/net/core/filter.c
index f54e7152d68798..90e396423eb7af 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -10483,10 +10483,11 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
si->dst_reg, si->dst_reg, \
offsetof(OBJ, OBJ_FIELD)); \
if (si->dst_reg == si->src_reg) { \
- *insn++ = BPF_JMP_A(1); \
+ *insn++ = BPF_JMP_A(2); \
*insn++ = BPF_LDX_MEM(BPF_DW, reg, si->src_reg, \
offsetof(struct bpf_sock_ops_kern, \
temp)); \
+ *insn++ = BPF_MOV64_IMM(si->dst_reg, 0); \
} \
} while (0)
@@ -10520,10 +10521,11 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
si->dst_reg, si->src_reg, \
offsetof(struct bpf_sock_ops_kern, sk));\
if (si->dst_reg == si->src_reg) { \
- *insn++ = BPF_JMP_A(1); \
+ *insn++ = BPF_JMP_A(2); \
*insn++ = BPF_LDX_MEM(BPF_DW, reg, si->src_reg, \
offsetof(struct bpf_sock_ops_kern, \
temp)); \
+ *insn++ = BPF_MOV64_IMM(si->dst_reg, 0); \
} \
} while (0)
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 452/602] net: qrtr: ns: Raise node count limit to 512
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (450 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 451/602] bpf: Fix same-register dst/src OOB read and pointer leak in sock_ops Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 453/602] ksmbd: validate num_subauth when copying ACE in set_ntacl_dacl Greg Kroah-Hartman
` (153 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Youssef Samir, Jakub Kicinski,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Youssef Samir <youssef.abdulrahman@oss.qualcomm.com>
commit ff194cffd586cbd4cc49eccb002c65f2a902a277 upstream.
The current node limit of 64 breaks the functionality for a number of AI200
deployments that have up to 384 nodes. Raise the limit to 512.
Fixes: 27d5e84e810b ("net: qrtr: ns: Limit the total number of nodes")
Cc: stable@vger.kernel.org
Signed-off-by: Youssef Samir <youssef.abdulrahman@oss.qualcomm.com>
Link: https://patch.msgid.link/20260713145901.212396-1-youssef.abdulrahman@oss.qualcomm.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Youssef Samir <youssef.abdulrahman@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/qrtr/ns.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/qrtr/ns.c b/net/qrtr/ns.c
index a10e8de4f7e105..e8e3ba1b3b8239 100644
--- a/net/qrtr/ns.c
+++ b/net/qrtr/ns.c
@@ -85,9 +85,9 @@ struct qrtr_node {
/* Max nodes limit is chosen based on the current platform requirements.
* If the requirement changes in the future, this value can be increased.
*/
-#define QRTR_NS_MAX_NODES 64
+#define QRTR_NS_MAX_NODES 512
-static u8 node_count;
+static u16 node_count;
static struct qrtr_node *node_get(unsigned int node_id)
{
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 453/602] ksmbd: validate num_subauth when copying ACE in set_ntacl_dacl
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (451 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 452/602] net: qrtr: ns: Raise node count limit to 512 Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 454/602] ksmbd: restore DACL size on check_add_overflow() to avoid malformed ACL Greg Kroah-Hartman
` (152 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Haofeng Li, ChenXiaoSong,
Namjae Jeon, Steve French, Wentao Guan, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haofeng Li <lihaofeng@kylinos.cn>
commit 47f0b34f6bc98ed85bfdc293e8f3e432ec24958d upstream.
set_ntacl_dacl() copies each ACE from the attacker-controlled stored
security descriptor verbatim into the response DACL without checking
sid.num_subauth. The ACE bytes (including an unchecked num_subauth)
originate from an authenticated SMB2_SET_INFO(SecInfo=DACL) that is
stored raw via ksmbd_vfs_set_sd_xattr(); parse_dacl() rejects a bad ACE
with `break` rather than an error, so parse_sec_desc() still returns
success and the malformed SD reaches the xattr intact.
On a subsequent SMB2_QUERY_INFO(SecInfo=DACL) for an inode carrying a
POSIX access ACL, build_sec_desc() -> set_ntacl_dacl() ->
set_posix_acl_entries_dacl() walks the copied ACEs and reads
ntace->sid.sub_auth[ntace->sid.num_subauth - 1]
with num_subauth taken straight from the stored SD. Since sub_auth[]
is fixed at SID_MAX_SUB_AUTHORITIES (15), a crafted num_subauth (e.g.
255) drives an out-of-bounds heap read of ~1 KB with an offset fully
controlled by an authenticated client.
The sibling functions already gate this field:
parse_dacl() -- num_subauth == 0 || > SID_MAX_SUB_AUTHORITIES
parse_sid() -- num_subauth > SID_MAX_SUB_AUTHORITIES
smb_copy_sid() -- min_t(u8, num_subauth, SID_MAX_SUB_AUTHORITIES)
set_ntacl_dacl() is the lone inconsistent path that omits the check.
Add the same num_subauth validation in set_ntacl_dacl() before copying
the ACE, matching the gate already enforced by parse_dacl().
Signed-off-by: Haofeng Li <lihaofeng@kylinos.cn>
Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
Suggested-by: Namjae Jeon <linkinjeon@kernel.org>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/smb/server/smbacl.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/fs/smb/server/smbacl.c b/fs/smb/server/smbacl.c
index b09bc8d9389a2a..173469d112f101 100644
--- a/fs/smb/server/smbacl.c
+++ b/fs/smb/server/smbacl.c
@@ -745,12 +745,18 @@ static void set_ntacl_dacl(struct mnt_idmap *idmap,
if (nt_ace_size > aces_size)
break;
+ if (ntace->sid.num_subauth == 0 ||
+ ntace->sid.num_subauth > SID_MAX_SUB_AUTHORITIES)
+ goto next_ace;
+
memcpy((char *)pndace + size, ntace, nt_ace_size);
if (check_add_overflow(size, nt_ace_size, &size))
break;
+ num_aces++;
+
+next_ace:
aces_size -= nt_ace_size;
ntace = (struct smb_ace *)((char *)ntace + nt_ace_size);
- num_aces++;
}
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 454/602] ksmbd: restore DACL size on check_add_overflow() to avoid malformed ACL
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (452 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 453/602] ksmbd: validate num_subauth when copying ACE in set_ntacl_dacl Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 455/602] ksmbd: bound DACL dedup walk to copied ACEs Greg Kroah-Hartman
` (151 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Wentao Guan, Namjae Jeon,
Steve French, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wentao Guan <guanwentao@uniontech.com>
commit bbf0a8e931204ecdab494a88d43b0a24a04285c5 upstream.
check_add_overflow() unconditionally writes the truncated sum into *d
even on overflow, per its contract in include/linux/overflow.h.
The four check_add_overflow() guards in set_posix_acl_entries_dacl()
and set_ntacl_dacl() break out of the ACE-building loops on overflow,
but the truncated *size is then consumed downstream at the end of
set_ntacl_dacl():
pndacl->size = cpu_to_le16(le16_to_cpu(pndacl->size) + size);
This produces an on-wire NT ACL whose pndacl->size under-reports the
bytes actually written by the preceding fill_ace_for_sid()/memcpy()
calls, yielding a malformed ACL that can trigger out-of-bounds reads
when re-parsed by clients or ksmbd itself.
Restore *size to its pre-addition value on each overflow branch (via
`*size -= ace_sz` / `size -= nt_ace_size`) so that after the break,
*size once again holds the cumulative size of the successfully-written
ACEs. The committed ACL is then truncated-but-self-consistent rather
than malformed.
The ksmbd DACL builders are the only check_add_overflow() sites found
where an overflow path breaks out of a loop and the destination value
is consumed afterward. The other nearby break-style cases either
return -EINVAL on overflow (transport_ipc.c) or break without
consuming the overflowed destination value afterward (buildid.c).
Fixes: 299f962c0b02 ("ksmbd: use check_add_overflow() to prevent u16 DACL size overflow")
Assisted-by: atomcode:glm-5.2
Assisted-by: Codex:gpt-5.5
Cc: stable@vger.kernel.org
Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/smb/server/smbacl.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/fs/smb/server/smbacl.c b/fs/smb/server/smbacl.c
index 173469d112f101..ca0e4aab6dd87f 100644
--- a/fs/smb/server/smbacl.c
+++ b/fs/smb/server/smbacl.c
@@ -649,6 +649,7 @@ static void set_posix_acl_entries_dacl(struct mnt_idmap *idmap,
ace_sz = fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, flags,
pace->e_perm, 0777);
if (check_add_overflow(*size, ace_sz, size)) {
+ *size -= ace_sz;
kfree(sid);
break;
}
@@ -663,6 +664,7 @@ static void set_posix_acl_entries_dacl(struct mnt_idmap *idmap,
ace_sz = fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED,
0x03, pace->e_perm, 0777);
if (check_add_overflow(*size, ace_sz, size)) {
+ *size -= ace_sz;
kfree(sid);
break;
}
@@ -708,6 +710,7 @@ static void set_posix_acl_entries_dacl(struct mnt_idmap *idmap,
ace_sz = fill_ace_for_sid(ntace, sid, ACCESS_ALLOWED, 0x0b,
pace->e_perm, 0777);
if (check_add_overflow(*size, ace_sz, size)) {
+ *size -= ace_sz;
kfree(sid);
break;
}
@@ -750,8 +753,10 @@ static void set_ntacl_dacl(struct mnt_idmap *idmap,
goto next_ace;
memcpy((char *)pndace + size, ntace, nt_ace_size);
- if (check_add_overflow(size, nt_ace_size, &size))
+ if (check_add_overflow(size, nt_ace_size, &size)) {
+ size -= nt_ace_size;
break;
+ }
num_aces++;
next_ace:
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 455/602] ksmbd: bound DACL dedup walk to copied ACEs
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (453 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 454/602] ksmbd: restore DACL size on check_add_overflow() to avoid malformed ACL Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 456/602] ksmbd: validate ACE size against SID sub-authorities Greg Kroah-Hartman
` (150 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Namjae Jeon, Steve French,
Wentao Guan, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namjae Jeon <linkinjeon@kernel.org>
commit 58d97fcd0bf1aee694e244cc28635b9df95b543b upstream.
set_ntacl_dacl() can stop copying ACEs before consuming the full input
DACL when size accounting overflows.
When that happens, num_aces reflects only the ACEs that were actually
copied into the output DACL, but set_posix_acl_entries_dacl() still
receives nt_num_aces and uses it to walk the existing ACE array during
dedup.
That makes the dedup walk scan past the copied ACE array and inspect
buffer tail that does not contain valid ACEs.
Split the two meanings currently carried by the NT ACE count. Pass the
number of copied NT ACEs to bound the dedup walk, and preserve the
original "input DACL had NT ACEs" state separately for the
Everyone/default ACL fallback.
This keeps the dedup walk aligned with the ACEs that are actually
present in the rebuilt DACL.
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/smb/server/smbacl.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/fs/smb/server/smbacl.c b/fs/smb/server/smbacl.c
index ca0e4aab6dd87f..b0677e095c3292 100644
--- a/fs/smb/server/smbacl.c
+++ b/fs/smb/server/smbacl.c
@@ -595,7 +595,8 @@ static void parse_dacl(struct mnt_idmap *idmap,
static void set_posix_acl_entries_dacl(struct mnt_idmap *idmap,
struct smb_ace *pndace,
struct smb_fattr *fattr, u16 *num_aces,
- u16 *size, u32 nt_aces_num)
+ u16 *size, u16 existing_nt_aces,
+ bool had_nt_aces)
{
struct posix_acl_entry *pace;
struct smb_sid *sid;
@@ -627,14 +628,14 @@ static void set_posix_acl_entries_dacl(struct mnt_idmap *idmap,
gid = posix_acl_gid_translate(idmap, pace);
id_to_sid(gid, SIDUNIX_GROUP, sid);
- } else if (pace->e_tag == ACL_OTHER && !nt_aces_num) {
+ } else if (pace->e_tag == ACL_OTHER && !had_nt_aces) {
smb_copy_sid(sid, &sid_everyone);
} else {
kfree(sid);
continue;
}
ntace = pndace;
- for (j = 0; j < nt_aces_num; j++) {
+ for (j = 0; j < existing_nt_aces; j++) {
if (ntace->sid.sub_auth[ntace->sid.num_subauth - 1] ==
sid->sub_auth[sid->num_subauth - 1])
goto pass_same_sid;
@@ -678,7 +679,7 @@ static void set_posix_acl_entries_dacl(struct mnt_idmap *idmap,
kfree(sid);
}
- if (nt_aces_num)
+ if (had_nt_aces)
return;
posix_default_acl:
@@ -732,6 +733,7 @@ static void set_ntacl_dacl(struct mnt_idmap *idmap,
{
struct smb_ace *ntace, *pndace;
u16 nt_num_aces = le16_to_cpu(nt_dacl->num_aces), num_aces = 0;
+ u16 copied_nt_aces;
unsigned short size = 0;
int i;
@@ -765,8 +767,10 @@ static void set_ntacl_dacl(struct mnt_idmap *idmap,
}
}
+ copied_nt_aces = num_aces;
set_posix_acl_entries_dacl(idmap, pndace, fattr,
- &num_aces, &size, nt_num_aces);
+ &num_aces, &size, copied_nt_aces,
+ nt_num_aces != 0);
pndacl->num_aces = cpu_to_le16(num_aces);
pndacl->size = cpu_to_le16(le16_to_cpu(pndacl->size) + size);
}
@@ -784,7 +788,7 @@ static void set_mode_dacl(struct mnt_idmap *idmap,
if (fattr->cf_acls) {
set_posix_acl_entries_dacl(idmap, pndace, fattr,
- &num_aces, &size, num_aces);
+ &num_aces, &size, num_aces, false);
goto out;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 456/602] ksmbd: validate ACE size against SID sub-authorities
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (454 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 455/602] ksmbd: bound DACL dedup walk to copied ACEs Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 457/602] fscrypt: Avoid dynamic allocation in fscrypt_get_devices() Greg Kroah-Hartman
` (149 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, LocalHost, Namjae Jeon, Steve French,
Wentao Guan, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namjae Jeon <linkinjeon@kernel.org>
commit 5152c6d49e3fd4e9f2e857c57527aead752f1f87 upstream.
set_ntacl_dacl() validates sid.num_subauth before copying an ACE, but
does not verify that the declared ACE size contains all sub-authorities
described by that field. An undersized ACE can therefore be copied
and later make the POSIX ACL deduplication walk inspect data beyond
the copied ACE boundary.
The existing initial bound check is also too small. It only ensures
that the ACE size field is accessible before set_ntacl_dacl() reads
sid.num_subauth farther into the input buffer.
Require enough input for the fixed SID header before accessing
num_subauth, reject ACEs smaller than that header, and skip ACEs
whose declared size cannot contain the complete SID. This makes the
validation consistent with the other ACE walk paths.
Reported-by: LocalHost <localhost.detect@gmail.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/smb/server/smbacl.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/fs/smb/server/smbacl.c b/fs/smb/server/smbacl.c
index b0677e095c3292..d3d0a22620f96d 100644
--- a/fs/smb/server/smbacl.c
+++ b/fs/smb/server/smbacl.c
@@ -743,15 +743,22 @@ static void set_ntacl_dacl(struct mnt_idmap *idmap,
for (i = 0; i < nt_num_aces; i++) {
unsigned short nt_ace_size;
- if (offsetof(struct smb_ace, access_req) > aces_size)
+ if (aces_size < offsetof(struct smb_ace, sid) +
+ CIFS_SID_BASE_SIZE)
break;
nt_ace_size = le16_to_cpu(ntace->size);
- if (nt_ace_size > aces_size)
+ if (nt_ace_size > aces_size ||
+ nt_ace_size < offsetof(struct smb_ace, sid) +
+ CIFS_SID_BASE_SIZE)
break;
if (ntace->sid.num_subauth == 0 ||
- ntace->sid.num_subauth > SID_MAX_SUB_AUTHORITIES)
+ ntace->sid.num_subauth > SID_MAX_SUB_AUTHORITIES ||
+ nt_ace_size < offsetof(struct smb_ace, sid) +
+ CIFS_SID_BASE_SIZE +
+ sizeof(__le32) *
+ ntace->sid.num_subauth)
goto next_ace;
memcpy((char *)pndace + size, ntace, nt_ace_size);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 457/602] fscrypt: Avoid dynamic allocation in fscrypt_get_devices()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (455 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 456/602] ksmbd: validate ACE size against SID sub-authorities Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 458/602] drm/amd/display: Fix DTB DTO updates breaking live pixel rate sources Greg Kroah-Hartman
` (148 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sashiko, Christoph Hellwig,
Eric Biggers, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Biggers <ebiggers@kernel.org>
commit 6fe4e4b8259e1330945b5f3c9476e08473b8e0e8 upstream.
When a blk_crypto_key starts being used or is evicted, fs/crypto/ calls
fscrypt_get_devices() to get the filesystem's list of block devices,
then iterates over them and calls blk_crypto_config_supported(),
blk_crypto_start_using_key(), or blk_crypto_evict_key() on each one.
Currently, the block device pointers are placed in a dynamically
allocated array. This dynamic allocation is problematic because:
- It can fail, especially at the fscrypt_destroy_inline_crypt_key() call
site when it's invoked for inode eviction under direct reclaim.
- fscrypt_destroy_inline_crypt_key() doesn't handle the failure. It
just zeroizes and frees the blk_crypto_key without calling
blk_crypto_evict_key(). That causes a use-after-free.
For now, let's fix this in the straightforward and easily-backportable
way by switching to an on-stack array. Currently the fscrypt
multi-device functionality is used only by f2fs, which has a hardcoded
limit of 8 block devices. An on-stack array works fine for that.
(Of course, this solution won't scale up to large number of block
devices. For that we'd need a different solution, like moving the block
device iteration into the filesystem. Or in the case of btrfs, which
will only support blk-crypto-fallback, we should make it just call
blk-crypto-fallback directly, so the block devices won't be needed.)
Fixes: 22e9947a4b2b ("fscrypt: stop holding extra request_queue references")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260713023708.9245-1-ebiggers%40kernel.org
Reviewed-by: Christoph Hellwig <hch@lst.de>
Link: https://patch.msgid.link/20260719055602.78828-1-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/crypto/inline_crypt.c | 57 ++++++++++++++--------------------------
fs/f2fs/super.c | 25 ++++++++++--------
include/linux/fscrypt.h | 18 +++++++------
3 files changed, 44 insertions(+), 56 deletions(-)
diff --git a/fs/crypto/inline_crypt.c b/fs/crypto/inline_crypt.c
index 4b1f10f1cbd85e..0a216d20e6950d 100644
--- a/fs/crypto/inline_crypt.c
+++ b/fs/crypto/inline_crypt.c
@@ -21,22 +21,14 @@
#include "fscrypt_private.h"
-static struct block_device **fscrypt_get_devices(struct super_block *sb,
- unsigned int *num_devs)
+static unsigned int
+fscrypt_get_devices(struct super_block *sb,
+ struct block_device *devs[FSCRYPT_MAX_DEVICES])
{
- struct block_device **devs;
-
- if (sb->s_cop->get_devices) {
- devs = sb->s_cop->get_devices(sb, num_devs);
- if (devs)
- return devs;
- }
- devs = kmalloc(sizeof(*devs), GFP_KERNEL);
- if (!devs)
- return ERR_PTR(-ENOMEM);
+ if (sb->s_cop->get_devices)
+ return sb->s_cop->get_devices(sb, devs);
devs[0] = sb->s_bdev;
- *num_devs = 1;
- return devs;
+ return 1;
}
static unsigned int fscrypt_get_dun_bytes(const struct fscrypt_inode_info *ci)
@@ -94,7 +86,7 @@ int fscrypt_select_encryption_impl(struct fscrypt_inode_info *ci)
const struct inode *inode = ci->ci_inode;
struct super_block *sb = inode->i_sb;
struct blk_crypto_config crypto_cfg;
- struct block_device **devs;
+ struct block_device *devs[FSCRYPT_MAX_DEVICES];
unsigned int num_devs;
unsigned int i;
@@ -131,20 +123,15 @@ int fscrypt_select_encryption_impl(struct fscrypt_inode_info *ci)
crypto_cfg.data_unit_size = 1U << ci->ci_data_unit_bits;
crypto_cfg.dun_bytes = fscrypt_get_dun_bytes(ci);
- devs = fscrypt_get_devices(sb, &num_devs);
- if (IS_ERR(devs))
- return PTR_ERR(devs);
-
+ num_devs = fscrypt_get_devices(sb, devs);
for (i = 0; i < num_devs; i++) {
if (!blk_crypto_config_supported(devs[i], &crypto_cfg))
- goto out_free_devs;
+ return 0;
}
fscrypt_log_blk_crypto_impl(ci->ci_mode, devs, num_devs, &crypto_cfg);
ci->ci_inlinecrypt = true;
-out_free_devs:
- kfree(devs);
return 0;
}
@@ -157,7 +144,7 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
struct super_block *sb = inode->i_sb;
enum blk_crypto_mode_num crypto_mode = ci->ci_mode->blk_crypto_mode;
struct blk_crypto_key *blk_key;
- struct block_device **devs;
+ struct block_device *devs[FSCRYPT_MAX_DEVICES];
unsigned int num_devs;
unsigned int i;
int err;
@@ -175,17 +162,12 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key,
}
/* Start using blk-crypto on all the filesystem's block devices. */
- devs = fscrypt_get_devices(sb, &num_devs);
- if (IS_ERR(devs)) {
- err = PTR_ERR(devs);
- goto fail;
- }
+ num_devs = fscrypt_get_devices(sb, devs);
for (i = 0; i < num_devs; i++) {
err = blk_crypto_start_using_key(devs[i], blk_key);
if (err)
break;
}
- kfree(devs);
if (err) {
fscrypt_err(inode, "error %d starting to use blk-crypto", err);
goto fail;
@@ -203,20 +185,21 @@ void fscrypt_destroy_inline_crypt_key(struct super_block *sb,
struct fscrypt_prepared_key *prep_key)
{
struct blk_crypto_key *blk_key = prep_key->blk_key;
- struct block_device **devs;
+ struct block_device *devs[FSCRYPT_MAX_DEVICES];
unsigned int num_devs;
unsigned int i;
if (!blk_key)
return;
- /* Evict the key from all the filesystem's block devices. */
- devs = fscrypt_get_devices(sb, &num_devs);
- if (!IS_ERR(devs)) {
- for (i = 0; i < num_devs; i++)
- blk_crypto_evict_key(devs[i], blk_key);
- kfree(devs);
- }
+ /*
+ * Evict the key from all the filesystem's block devices.
+ * This *must* be done before the key is freed.
+ */
+ num_devs = fscrypt_get_devices(sb, devs);
+ for (i = 0; i < num_devs; i++)
+ blk_crypto_evict_key(devs[i], blk_key);
+
kfree_sensitive(blk_key);
}
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 1bce35d6f4e253..8ceffecf28c80c 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -3282,24 +3282,27 @@ static bool f2fs_has_stable_inodes(struct super_block *sb)
return true;
}
-static struct block_device **f2fs_get_devices(struct super_block *sb,
- unsigned int *num_devs)
+static unsigned int
+f2fs_get_devices(struct super_block *sb,
+ struct block_device *devs[FSCRYPT_MAX_DEVICES])
{
struct f2fs_sb_info *sbi = F2FS_SB(sb);
- struct block_device **devs;
+ int ndevs;
int i;
- if (!f2fs_is_multi_device(sbi))
- return NULL;
+ static_assert(MAX_DEVICES <= FSCRYPT_MAX_DEVICES);
- devs = kmalloc_array(sbi->s_ndevs, sizeof(*devs), GFP_KERNEL);
- if (!devs)
- return ERR_PTR(-ENOMEM);
+ if (!f2fs_is_multi_device(sbi)) {
+ devs[0] = sb->s_bdev;
+ return 1;
+ }
+ ndevs = sbi->s_ndevs;
+ if (WARN_ON_ONCE(ndevs > FSCRYPT_MAX_DEVICES))
+ ndevs = FSCRYPT_MAX_DEVICES;
- for (i = 0; i < sbi->s_ndevs; i++)
+ for (i = 0; i < ndevs; i++)
devs[i] = FDEV(i).bdev;
- *num_devs = sbi->s_ndevs;
- return devs;
+ return ndevs;
}
static const struct fscrypt_operations f2fs_cryptops = {
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 772f822dc6b82e..3cb1e449d8cfc1 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -57,6 +57,9 @@ struct fscrypt_name {
/* Maximum value for the third parameter of fscrypt_operations.set_context(). */
#define FSCRYPT_SET_CONTEXT_MAX_SIZE 40
+/* Maximum supported number of block devices per filesystem */
+#define FSCRYPT_MAX_DEVICES 8
+
#ifdef CONFIG_FS_ENCRYPTION
/* Crypto operations for filesystems */
@@ -175,21 +178,20 @@ struct fscrypt_operations {
bool (*has_stable_inodes)(struct super_block *sb);
/*
- * Return an array of pointers to the block devices to which the
- * filesystem may write encrypted file contents, NULL if the filesystem
- * only has a single such block device, or an ERR_PTR() on error.
+ * Retrieve the list of block devices to which the filesystem may write
+ * encrypted file contents.
*
- * On successful non-NULL return, *num_devs is set to the number of
- * devices in the returned array. The caller must free the returned
- * array using kfree().
+ * This writes the block_device pointers to @devs and returns the count
+ * (between 1 and FSCRYPT_MAX_DEVICES inclusively).
*
* If the filesystem can use multiple block devices (other than block
* devices that aren't used for encrypted file contents, such as
* external journal devices), and wants to support inline encryption,
* then it must implement this function. Otherwise it's not needed.
*/
- struct block_device **(*get_devices)(struct super_block *sb,
- unsigned int *num_devs);
+ unsigned int (*get_devices)(
+ struct super_block *sb,
+ struct block_device *devs[FSCRYPT_MAX_DEVICES]);
};
int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags);
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 458/602] drm/amd/display: Fix DTB DTO updates breaking live pixel rate sources
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (456 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 457/602] fscrypt: Avoid dynamic allocation in fscrypt_get_devices() Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 459/602] io_uring/rw: fix missing ERESTARTSYS conversion in read paths Greg Kroah-Hartman
` (147 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Harry Wentland, Fangzhi Zuo,
Dan Wheeler, Alex Deucher, Matthew Schwartz, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Harry Wentland <harry.wentland@amd.com>
commit 76a2db58e95e328007043f54ac3c7336ccbee440 upstream.
dcn32_update_clocks_update_dtb_dto() and its dcn35 counterpart reprogram
the DTB DTO of every timing generator in the context whenever the DTBCLK
reference changes, passing a zeroed pixel rate and never setting
is_hdmi. Both dccg set_dtbclk_dto() implementations treat a zero pixel
rate as a disable request. On dcn32 that branch drives PIPE_DTO_SRC_SEL
to the DP DTO source, so a timing generator actively scanning out an
HDMI stream has its pixel rate source re-muxed out from under the live
raster and the OTG stops on the spot. On dcn35 it clears
DTBCLK_DTO_ENABLE and restores DTBCLK_Pn clock gating, which does the
same to a live 128b/132b stream.
Two displays where only one runs a 128b/132b link hit this reliably.
is_dtbclk_required() holds the DTBCLK reference high while both are
active, and the moment the 128b/132b stream is torn down (compositor
switch, display disable, hot-unplug) the next safe_to_lower pass drops
the reference to the lowest DPM level and the DTO walk freezes the
surviving screen. On Navi31 the DAL mailbox then goes deaf on the
DISPCLK hard-min that follows the walk in dcn32_update_clocks(),
stranding both SMU mailboxes until reboot.
Set is_hdmi for HDMI and DVI signals so the disable path leaves the
pixel rate source selection on the HDMI path, and pass the real pixel
rate for 128b/132b streams so a reference change rescales their DTO
instead of disabling it.
Fixes: 128c1ca0303f ("drm/amd/display: Update DTBCLK for DCN32")
Fixes: 8774029f76b9 ("drm/amd/display: Add DCN35 CLK_MGR")
Signed-off-by: Harry Wentland <harry.wentland@amd.com>
Reviewed-by: Fangzhi Zuo <Jerry.Zuo@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
[ mschwartz: dcn32 and dcn35 clk_mgr hunks only. The rest is HDMI FRL
enablement, absent before 7.2, so the FRL conditions and the
req_audio_dtbclk_khz assignment they guard are dropped and the
FRL-centric changelog is rewritten. Added the pipe_ctx->stream check
the new dereferences need. ]
Signed-off-by: Matthew Schwartz <matthew.schwartz@linux.dev>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
.../gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c | 9 ++++++++-
.../gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 9 ++++++++-
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
index 084994c650c4c9..285689d7ecc4ea 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c
@@ -276,13 +276,20 @@ static void dcn32_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr,
struct dtbclk_dto_params dto_params = {0};
/* use mask to program DTO once per tg */
- if (pipe_ctx->stream_res.tg &&
+ if (pipe_ctx->stream && pipe_ctx->stream_res.tg &&
!(tg_mask & (1 << pipe_ctx->stream_res.tg->inst))) {
tg_mask |= (1 << pipe_ctx->stream_res.tg->inst);
dto_params.otg_inst = pipe_ctx->stream_res.tg->inst;
dto_params.ref_dtbclk_khz = ref_dtbclk_khz;
+ if (dccg->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx))
+ dto_params.pixclk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10;
+
+ if (dc_is_hdmi_signal(pipe_ctx->stream->signal) ||
+ dc_is_dvi_signal(pipe_ctx->stream->signal))
+ dto_params.is_hdmi = true;
+
dccg->funcs->set_dtbclk_dto(clk_mgr->dccg, &dto_params);
//dccg->funcs->set_audio_dtbclk_dto(clk_mgr->dccg, &dto_params);
}
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
index 33ee7e81b1b939..05e4dbc7fb8398 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c
@@ -247,13 +247,20 @@ static void dcn35_update_clocks_update_dtb_dto(struct clk_mgr_internal *clk_mgr,
struct dtbclk_dto_params dto_params = {0};
/* use mask to program DTO once per tg */
- if (pipe_ctx->stream_res.tg &&
+ if (pipe_ctx->stream && pipe_ctx->stream_res.tg &&
!(tg_mask & (1 << pipe_ctx->stream_res.tg->inst))) {
tg_mask |= (1 << pipe_ctx->stream_res.tg->inst);
dto_params.otg_inst = pipe_ctx->stream_res.tg->inst;
dto_params.ref_dtbclk_khz = ref_dtbclk_khz;
+ if (dccg->ctx->dc->link_srv->dp_is_128b_132b_signal(pipe_ctx))
+ dto_params.pixclk_khz = pipe_ctx->stream->timing.pix_clk_100hz / 10;
+
+ if (dc_is_hdmi_signal(pipe_ctx->stream->signal) ||
+ dc_is_dvi_signal(pipe_ctx->stream->signal))
+ dto_params.is_hdmi = true;
+
dccg->funcs->set_dtbclk_dto(clk_mgr->dccg, &dto_params);
//dccg->funcs->set_audio_dtbclk_dto(clk_mgr->dccg, &dto_params);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 459/602] io_uring/rw: fix missing ERESTARTSYS conversion in read paths
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (457 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 458/602] drm/amd/display: Fix DTB DTO updates breaking live pixel rate sources Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 460/602] net: pcs: xpcs: fix SGMII state reading Greg Kroah-Hartman
` (146 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Yitang Yang, Jens Axboe, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yitang Yang <yi1tang.yang@gmail.com>
commit ab05caca123c6d0b41850b7c05b246e4dca4a770 upstream.
Both read and write may receive internal restart error codes from
the filesystem layer and should be converted to -EINTR. However,
when multishot read support was added, the error code normalization
was lost for both io_read() and io_read_mshot().
Extract the conversion into io_fixup_restart_res() and apply it
in all three locations: io_rw_done(), io_read(), and io_read_mshot().
Fixes: a08d195b586a ("io_uring/rw: split io_read() into a helper")
Cc: stable@vger.kernel.org
Signed-off-by: Yitang Yang <yi1tang.yang@gmail.com>
Link: https://patch.msgid.link/20260722124551.130563-1-yi1tang.yang@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
io_uring/rw.c | 42 +++++++++++++++++++++++++-----------------
1 file changed, 25 insertions(+), 17 deletions(-)
diff --git a/io_uring/rw.c b/io_uring/rw.c
index a744cb5d235a6a..a74664c4a05efe 100644
--- a/io_uring/rw.c
+++ b/io_uring/rw.c
@@ -560,6 +560,24 @@ static void io_complete_rw_iopoll(struct kiocb *kiocb, long res)
smp_store_release(&req->iopoll_completed, 1);
}
+static inline ssize_t io_fixup_restart_res(ssize_t ret)
+{
+ switch (ret) {
+ case -ERESTARTSYS:
+ case -ERESTARTNOINTR:
+ case -ERESTARTNOHAND:
+ case -ERESTART_RESTARTBLOCK:
+ /*
+ * We can't just restart the syscall, since previously
+ * submitted sqes may already be in progress. Just fail
+ * this IO with EINTR.
+ */
+ return -EINTR;
+ default:
+ return ret;
+ }
+}
+
static inline void io_rw_done(struct kiocb *kiocb, ssize_t ret)
{
/* IO was queued async, completion will happen later */
@@ -567,21 +585,8 @@ static inline void io_rw_done(struct kiocb *kiocb, ssize_t ret)
return;
/* transform internal restart error codes */
- if (unlikely(ret < 0)) {
- switch (ret) {
- case -ERESTARTSYS:
- case -ERESTARTNOINTR:
- case -ERESTARTNOHAND:
- case -ERESTART_RESTARTBLOCK:
- /*
- * We can't just restart the syscall, since previously
- * submitted sqes may already be in progress. Just fail
- * this IO with EINTR.
- */
- ret = -EINTR;
- break;
- }
- }
+ if (unlikely(ret < 0))
+ ret = io_fixup_restart_res(ret);
INDIRECT_CALL_2(kiocb->ki_complete, io_complete_rw_iopoll,
io_complete_rw, kiocb, ret);
@@ -961,7 +966,8 @@ int io_read(struct io_kiocb *req, unsigned int issue_flags)
if (req->flags & REQ_F_BUFFERS_COMMIT)
io_kbuf_recycle(req, sel.buf_list, issue_flags);
- return ret;
+
+ return io_fixup_restart_res(ret);
}
int io_read_mshot(struct io_kiocb *req, unsigned int issue_flags)
@@ -995,8 +1001,10 @@ int io_read_mshot(struct io_kiocb *req, unsigned int issue_flags)
return -EAGAIN;
} else if (ret <= 0) {
io_kbuf_recycle(req, sel.buf_list, issue_flags);
- if (ret < 0)
+ if (ret < 0) {
+ ret = io_fixup_restart_res(ret);
req_set_fail(req);
+ }
} else if (!(req->flags & REQ_F_APOLL_MULTISHOT)) {
cflags = io_put_kbuf(req, ret, sel.buf_list);
} else {
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 460/602] net: pcs: xpcs: fix SGMII state reading
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (458 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 459/602] io_uring/rw: fix missing ERESTARTSYS conversion in read paths Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 461/602] gve: fix Rx queue stall on alloc failure Greg Kroah-Hartman
` (145 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jiawen Wu, Coia Prant,
Maxime Chevallier, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Coia Prant <coiaprant@gmail.com>
commit def9a4745e105145133e442dd8a1c126caf0f553 upstream.
Commit 2a22b7ae2fa3 ("net: pcs: xpcs: adapt Wangxun NICs for SGMII mode")
added a path in xpcs_get_state_c37_sgmii() that reads speed/duplex from
BMCR after AN completes. However, BMCR does not reflect the negotiated
result on the hardware where this has been tested:
- On RK3568 (MAC side SGMII), BMCR returns a fixed hardware reset value
- Wangxun engineer Jiawen Wu confirmed that on their side, "BMCR looks
like it only wants to be return as 0" [0]
The correct information is available in CL37_ANSGM_STS, which contains
the actual link status and negotiated speed/duplex.
This bug was previously masked by phylink core, which overrides the PCS
link state with the PHY state when a PHY is present:
/* If we have a phy, the "up" state is the union of both the
* PHY and the MAC
*/
if (phy)
link_state.link &= pl->phy_state.link;
Thus, when the link is down, the PHY's link_down state is applied on top
of whatever the PCS reports, hiding the broken PCS state reading path.
Modify xpcs_get_state_c37_sgmii() to:
1. Read link state from CL37_ANSGM_STS
2. If link is up, report speed/duplex from CL37_ANSGM_STS
3. Remove the broken BMCR reading path entirely
Also properly set state->an_complete to reflect the AN completion status,
and clear CL37_ANCMPLT_INTR when link is down to avoid stale state.
[0] https://lore.kernel.org/all/000c01dd1593$2ac0b0f0$804212d0$@trustnetic.com/
Fixes: 2a22b7ae2fa3 ("net: pcs: xpcs: adapt Wangxun NICs for SGMII mode")
Cc: stable@vger.kernel.org
Tested-by: Jiawen Wu <jiawenwu@trustnetic.com>
Signed-off-by: Coia Prant <coiaprant@gmail.com>
Tested-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Link: https://patch.msgid.link/20260717074324.3250043-2-coiaprant@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/pcs/pcs-xpcs.c | 32 +++++++-------------------------
1 file changed, 7 insertions(+), 25 deletions(-)
diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c
index 82463f9d50c85c..0152f820c1bbe5 100644
--- a/drivers/net/pcs/pcs-xpcs.c
+++ b/drivers/net/pcs/pcs-xpcs.c
@@ -973,6 +973,7 @@ static int xpcs_get_state_c37_sgmii(struct dw_xpcs *xpcs,
/* Reset link_state */
state->link = false;
+ state->an_complete = false;
state->speed = SPEED_UNKNOWN;
state->duplex = DUPLEX_UNKNOWN;
state->pause = 0;
@@ -984,6 +985,8 @@ static int xpcs_get_state_c37_sgmii(struct dw_xpcs *xpcs,
if (ret < 0)
return ret;
+ state->an_complete = ret & DW_VR_MII_AN_STS_C37_ANCMPLT_INTR;
+
if (ret & DW_VR_MII_C37_ANSGM_SP_LNKSTS) {
int speed_value;
@@ -1002,34 +1005,13 @@ static int xpcs_get_state_c37_sgmii(struct dw_xpcs *xpcs,
state->duplex = DUPLEX_FULL;
else
state->duplex = DUPLEX_HALF;
- } else if (ret == DW_VR_MII_AN_STS_C37_ANCMPLT_INTR) {
- int speed, duplex;
-
- state->link = true;
-
- speed = xpcs_read(xpcs, MDIO_MMD_VEND2, MDIO_CTRL1);
- if (speed < 0)
- return speed;
-
- speed &= SGMII_SPEED_SS13 | SGMII_SPEED_SS6;
- if (speed == SGMII_SPEED_SS6)
- state->speed = SPEED_1000;
- else if (speed == SGMII_SPEED_SS13)
- state->speed = SPEED_100;
- else if (speed == 0)
- state->speed = SPEED_10;
-
- duplex = xpcs_read(xpcs, MDIO_MMD_VEND2, MII_ADVERTISE);
- if (duplex < 0)
- return duplex;
- if (duplex & DW_FULL_DUPLEX)
- state->duplex = DUPLEX_FULL;
- else if (duplex & DW_HALF_DUPLEX)
- state->duplex = DUPLEX_HALF;
+ return 0;
+ }
+ /* Clear AN complete status or interrupt */
+ if (state->an_complete)
xpcs_write(xpcs, MDIO_MMD_VEND2, DW_VR_MII_AN_INTR_STS, 0);
- }
return 0;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 461/602] gve: fix Rx queue stall on alloc failure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (459 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 460/602] net: pcs: xpcs: fix SGMII state reading Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 462/602] rust: allow `suspicious_runtime_symbol_definitions` lint for Rust >= 1.98 Greg Kroah-Hartman
` (144 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jordan Rhee, Eddie Phillips,
Harshitha Ramamurthy, Przemek Kitszel, Jakub Kicinski,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eddie Phillips <eddiephillips@google.com>
commit b65352a1bac64442ad95e64f385b40ccb9f1b0db upstream.
When the system is under extreme memory pressure, page allocations can
fail during the Rx buffer refill loop. If the number of buffers posted
to hardware falls below a critical low threshold and the refill loop
exits due to allocation failures, the queue can stall:
1. The device drops incoming packets because there are no descriptors.
2. Since no packets are processed, no Rx completions are generated.
3. Because no completions occur, NAPI is never scheduled, preventing
the refill loop from running again even after memory is freed.
This results in a permanent queue stall.
Resolve this by introducing a starvation recovery timer for each Rx queue.
If the number of buffers posted to hardware falls below a critical low
threshold, start a timer to periodically reschedule NAPI. Once NAPI runs
and successfully refills the queue above the threshold, the timer is
not rescheduled.
The threshold is set to 32 because a single maximum-sized Receive Segment
Coalescing (RSC) packet can consume up to 19 descriptors in the Rx path.
Lower thresholds (such as 8 or 16) would be insufficient to process a
complete maximum-sized RSC packet, risking packet drops or unexpected
hardware behavior under memory pressure. Setting the threshold to 32
guarantees a safe margin to handle at least one full RSC packet.
Cc: stable@vger.kernel.org
Fixes: 9b8dd5e5ea48 ("gve: DQO: Add RX path")
Reviewed-by: Jordan Rhee <jordanrhee@google.com>
Signed-off-by: Eddie Phillips <eddiephillips@google.com>
Signed-off-by: Harshitha Ramamurthy <hramamurthy@google.com>
Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Link: https://patch.msgid.link/20260709211906.3322883-1-hramamurthy@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/google/gve/gve.h | 3 ++
drivers/net/ethernet/google/gve/gve_rx_dqo.c | 36 ++++++++++++++++++++
2 files changed, 39 insertions(+)
diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h
index 8ddd366d9fde54..e19d722e8e9a18 100644
--- a/drivers/net/ethernet/google/gve/gve.h
+++ b/drivers/net/ethernet/google/gve/gve.h
@@ -12,6 +12,7 @@
#include <linux/ethtool_netlink.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
+#include <linux/timer.h>
#include <linux/u64_stats_sync.h>
#include <net/xdp.h>
@@ -38,6 +39,7 @@
/* Interval to schedule a stats report update, 20000ms. */
#define GVE_STATS_REPORT_TIMER_PERIOD 20000
+#define GVE_RX_NAPI_RESCHED_MS 20 /* msecs */
/* Numbers of NIC tx/rx stats in stats report. */
#define NIC_TX_STATS_REPORT_NUM 0
@@ -311,6 +313,7 @@ struct gve_rx_ring {
struct xdp_rxq_info xsk_rxq;
struct xsk_buff_pool *xsk_pool;
struct page_frag_cache page_cache; /* Page cache to allocate XDP frames */
+ struct timer_list starvation_timer; /* for queue starvation recovery */
};
/* A TX desc ring entry */
diff --git a/drivers/net/ethernet/google/gve/gve_rx_dqo.c b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
index 1154c1d8f66f05..2f7f31e4797cd2 100644
--- a/drivers/net/ethernet/google/gve/gve_rx_dqo.c
+++ b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
@@ -199,6 +199,16 @@ static int gve_alloc_page_dqo(struct gve_rx_ring *rx,
return 0;
}
+static void gve_rx_starvation_timer(struct timer_list *t)
+{
+ struct gve_rx_ring *rx = from_timer(rx, t, starvation_timer);
+ struct gve_priv *priv = rx->gve;
+ struct gve_notify_block *block;
+
+ block = &priv->ntfy_blocks[rx->ntfy_id];
+ napi_schedule(&block->napi);
+}
+
static void gve_rx_free_hdr_bufs(struct gve_priv *priv, struct gve_rx_ring *rx)
{
struct device *hdev = &priv->pdev->dev;
@@ -290,10 +300,13 @@ static void gve_rx_reset_ring_dqo(struct gve_priv *priv, int idx)
void gve_rx_stop_ring_dqo(struct gve_priv *priv, int idx)
{
int ntfy_idx = gve_rx_idx_to_ntfy(priv, idx);
+ struct gve_rx_ring *rx = &priv->rx[idx];
if (!gve_rx_was_added_to_block(priv, idx))
return;
+ timer_shutdown_sync(&rx->starvation_timer);
+
gve_remove_napi(priv, ntfy_idx);
gve_rx_remove_from_block(priv, idx);
gve_rx_reset_ring_dqo(priv, idx);
@@ -371,8 +384,10 @@ static int gve_rx_alloc_hdr_bufs(struct gve_priv *priv, struct gve_rx_ring *rx,
void gve_rx_start_ring_dqo(struct gve_priv *priv, int idx)
{
int ntfy_idx = gve_rx_idx_to_ntfy(priv, idx);
+ struct gve_rx_ring *rx = &priv->rx[idx];
gve_rx_add_to_block(priv, idx);
+ timer_setup(&rx->starvation_timer, gve_rx_starvation_timer, 0);
gve_add_napi(priv, ntfy_idx, gve_napi_poll_dqo);
}
@@ -511,6 +526,7 @@ void gve_rx_post_buffers_dqo(struct gve_rx_ring *rx)
struct gve_rx_compl_queue_dqo *complq = &rx->dqo.complq;
struct gve_rx_buf_queue_dqo *bufq = &rx->dqo.bufq;
struct gve_priv *priv = rx->gve;
+ u32 num_bufs_avail_to_hw;
u32 num_avail_slots;
u32 num_full_slots;
u32 num_posted = 0;
@@ -555,6 +571,26 @@ void gve_rx_post_buffers_dqo(struct gve_rx_ring *rx)
}
rx->fill_cnt += num_posted;
+
+ /* If the queue has fewer than GVE_RX_BUF_THRESH_DQO descriptors
+ * visible to the hardware, the hardware is in danger of starving
+ * and cannot trigger interrupts.
+ *
+ * We use a threshold of 32 because a single maximum-sized RSC
+ * packet can consume up to 19 descriptors in the Rx path. Lower
+ * thresholds (e.g., 8 or 16) would be unsafe as they could cause
+ * the device to drop/stall on a maximum-sized RSC packet.
+ *
+ * Start the timer to periodically reschedule NAPI and recover.
+ */
+ num_bufs_avail_to_hw =
+ ((bufq->tail & ~(GVE_RX_BUF_THRESH_DQO - 1)) -
+ bufq->head) & bufq->mask;
+
+ if (num_bufs_avail_to_hw < GVE_RX_BUF_THRESH_DQO) {
+ mod_timer(&rx->starvation_timer,
+ jiffies + msecs_to_jiffies(GVE_RX_NAPI_RESCHED_MS));
+ }
}
static void gve_try_recycle_buf(struct gve_priv *priv, struct gve_rx_ring *rx,
--
2.53.0
^ permalink raw reply related [flat|nested] 608+ messages in thread
* [PATCH 6.12 462/602] rust: allow `suspicious_runtime_symbol_definitions` lint for Rust >= 1.98
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (460 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 461/602] gve: fix Rx queue stall on alloc failure Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 463/602] mm/damon/core: validate ranges in damon_set_regions() Greg Kroah-Hartman
` (143 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Urgau, Gary Guo, Alice Ryhl,
Tamir Duberstein, Miguel Ojeda
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miguel Ojeda <ojeda@kernel.org>
commit 608045a91d9176d66b2114d0006bc8b57dff2ca9 upstream.
Starting with Rust 1.98.0 (expected 2026-08-20), Rust is introducing a
couple new lints, `invalid_runtime_symbol_definitions` (deny-by-default)
and `suspicious_runtime_symbol_definitions` (warn-by-default), which check
the signature of items whose symbol name is a runtime symbol expected by
`core`.
Our build hits the second one, i.e. the warning:
error: suspicious definition of the runtime `strlen` symbol used by the standard library
--> rust/bindings/bindings_generated.rs:20018:5
|
20018 | pub fn strlen(s: *const ffi::c_char) -> usize;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: expected `unsafe extern "C" fn(*const i8) -> usize`
found `unsafe extern "C" fn(*const u8) -> usize`
= help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "strlen")]`, or `#[link_name = "strlen"]`
= help: allow this lint if the signature is compatible
= note: `-D suspicious-runtime-symbol-definitions` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(suspicious_runtime_symbol_definitions)]`
error: suspicious definition of the runtime `strlen` symbol used by the standard library
--> rust/uapi/uapi_generated.rs:14236:5
|
14236 | pub fn strlen(s: *const ffi::c_char) -> usize;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: expected `unsafe extern "C" fn(*const i8) -> usize`
found `unsafe extern "C" fn(*const u8) -> usize`
= help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "strlen")]`, or `#[link_name = "strlen"]`
= help: allow this lint if the signature is compatible
= note: `-D suspicious-runtime-symbol-definitions` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(suspicious_runtime_symbol_definitions)]`
Thus `allow` the lint in `bindings` and `uapi`.
A more targeted alternative to avoid `allow`ing it would be to pass
`--blocklist-function strlen` to `bindgen`, but we would perhaps need
to adjust if other C headers end up adding more (or Rust checking more).
Since it is just the less critical one that we hit, and since eventually
this should be properly fixed by getting upstream Rust to provide a flag
like GCC/Clang's `-funsigned-char` [2][3], just `allow` it for now.
Cc: Urgau <urgau@numericable.fr>
Cc: stable@vger.kernel.org # Needed in 6.12.y and later (Rust is pinned in older LTSs).
Link: https://github.com/rust-lang/rust/pull/155521 [1]
Link: https://github.com/rust-lang/rust/issues/138446 [2]
Link: https://github.com/Rust-for-Linux/linux/issues/355 [3]
Reviewed-by: Gary Guo <gary@garyguo.net>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Tamir Duberstein <tamird@kernel.org>
Link: https://patch.msgid.link/20260615143225.471756-1-ojeda@kernel.org
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
init/Kconfig | 3 +++
rust/bindings/lib.rs | 4 ++++
rust/uapi/lib.rs | 4 ++++
3 files changed, 11 insertions(+)
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -140,6 +140,9 @@ config LD_CAN_USE_KEEP_IN_OVERLAY
config RUSTC_HAS_UNNECESSARY_TRANSMUTES
def_bool RUSTC_VERSION >= 108800
+config RUSTC_HAS_SUSPICIOUS_RUNTIME_SYMBOL_DEFINITIONS
+ def_bool RUSTC_VERSION >= 109800
+
config PAHOLE_VERSION
int
default $(shell,$(srctree)/scripts/pahole-version.sh $(PAHOLE))
--- a/rust/bindings/lib.rs
+++ b/rust/bindings/lib.rs
@@ -27,6 +27,10 @@
#[allow(dead_code)]
#[allow(clippy::undocumented_unsafe_blocks)]
#[cfg_attr(CONFIG_RUSTC_HAS_UNNECESSARY_TRANSMUTES, allow(unnecessary_transmutes))]
+#[cfg_attr(
+ CONFIG_RUSTC_HAS_SUSPICIOUS_RUNTIME_SYMBOL_DEFINITIONS,
+ allow(suspicious_runtime_symbol_definitions)
+)]
mod bindings_raw {
// Manual definition for blocklisted types.
type __kernel_size_t = usize;
--- a/rust/uapi/lib.rs
+++ b/rust/uapi/lib.rs
@@ -25,6 +25,10 @@
unsafe_op_in_unsafe_fn
)]
#![cfg_attr(CONFIG_RUSTC_HAS_UNNECESSARY_TRANSMUTES, allow(unnecessary_transmutes))]
+#![cfg_attr(
+ CONFIG_RUSTC_HAS_SUSPICIOUS_RUNTIME_SYMBOL_DEFINITIONS,
+ allow(suspicious_runtime_symbol_definitions)
+)]
// Manual definition of blocklisted types.
type __kernel_size_t = usize;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 463/602] mm/damon/core: validate ranges in damon_set_regions()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (461 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 462/602] rust: allow `suspicious_runtime_symbol_definitions` lint for Rust >= 1.98 Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 464/602] mm/damon/core: disallow overlapping input ranges for damon_set_regions() Greg Kroah-Hartman
` (142 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, SJ Park, Yang yingliang,
Andrew Morton
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: SJ Park <sj@kernel.org>
commit 1292c0ecb1caefb8ca064a3639d5673991e8810c upstream.
DAMON core logic assumes zero length regions don't exist. However, a few
DAMON API callers including DAMON_SYSFS, DAMON_RECLAIM and DAMON_LRU_SORT
allow users to set empty monitoring target regions. This could result in
WARN_ONCE() on CONFIG_DAMON_DEBUG_SANITY enabled kernel, and
divide-by-zero from damon_merge_two_regions().
For example, the WANR_ONCE() can be triggered like below.
# grep DAMON_DEBUG_SANITY /boot/config-$(uname -r)
# CONFIG_DAMON_DEBUG_SANITY=y
# damo start
# cd /sys/kernel/mm/damon/admin/kdamonds/0
# echo 0 > contexts/0/targets/0/regions/0/start
# echo 0 > contexts/0/targets/0/regions/0/end
# echo commit > state
# dmesg
[....]
[ 73.705780] ------------[ cut here ]------------
[ 73.707552] start 0 >= end 0
[ 73.708452] WARNING: mm/damon/core.c:359 at damon_new_region+0x6e/0x80, CPU#1: kdamond.0/758
[...]
All DAMON API callers eventually use damon_set_regions() to setup the
regions. Add the validation logic in the function.
Link: https://lore.kernel.org/20260630035221.146458-1-sj@kernel.org
Fixes: 43b0536cb471 ("mm/damon: introduce DAMON-based Reclamation (DAMON_RECLAIM)")
Signed-off-by: SJ Park <sj@kernel.org>
Cc: Yang yingliang <yangyingliang@huawei.com>
Cc: <stable@vger.kernel.org> # 5.16.x
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
mm/damon/core.c | 6 ++++++
1 file changed, 6 insertions(+)
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -214,6 +214,12 @@ int damon_set_regions(struct damon_targe
unsigned int i;
int err;
+ for (i = 0; i < nr_ranges; i++) {
+ if (ALIGN_DOWN(ranges[i].start, DAMON_MIN_REGION) >=
+ ALIGN(ranges[i].end, DAMON_MIN_REGION))
+ return -EINVAL;
+ }
+
/* Remove regions which are not in the new ranges */
damon_for_each_region_safe(r, next, t) {
for (i = 0; i < nr_ranges; i++) {
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 464/602] mm/damon/core: disallow overlapping input ranges for damon_set_regions()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (462 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 463/602] mm/damon/core: validate ranges in damon_set_regions() Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 465/602] iommufd: Reject invalid read count in iommufd_fault_fops_read() Greg Kroah-Hartman
` (141 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, SJ Park, Andrew Morton
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: SJ Park <sj@kernel.org>
commit 954157679ec34661c2e87e7eb796104a797c32db upstream.
damon_set_regions() assumes the input ranges are sorted by the address and
don't overlap each other. Hence the assumption was initially to be
explicitly validated. But commit 97d482f4592f ("mm/damon/sysfs: reuse
damon_set_regions() for regions setting") has mistakenly removed the
validation.
This can make DAMON behave in unexpected ways. At the best, the
monitoring results snapshot will just look weird since there will be
overlapping regions. DAMOS will also work weirdly, applying the same
action multiple times for overlapping regions, and make DAMOS quota weird.
More seriously, depending on the setup and regions updates sequence,
negative size regions can be made. It will trigger WARN_ONCE() if the
kernel is built with CONFIG_DAMON_DEBUG_SANITY=y. Depending on the
monitoring results, the negative size region can further trigger division
by zero in damon_merge_two_regions().
Note that some of the consequences including the WARN_ONCE() and the
divide by zero depend on commits that were introduced after the root cause
commit 97d482f4592f ("mm/damon/sysfs: reuse damon_set_regions() for
regions setting").
Fix the problems by checking the assumption and returning an error if
the input ranges don't meet the assumption.
The issue was discovered [1] by Sashiko.
Link: https://lore.kernel.org/20260703165610.92894-1-sj@kernel.org
Link: https://lore.kernel.org/20260630041806.151124-1-sj@kernel.org [1]
Fixes: 97d482f4592f ("mm/damon/sysfs: reuse damon_set_regions() for regions setting")
Signed-off-by: SJ Park <sj@kernel.org>
Cc: <stable@vger.kernel.org> # 5.19.x
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
mm/damon/core.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -212,12 +212,19 @@ int damon_set_regions(struct damon_targe
{
struct damon_region *r, *next;
unsigned int i;
+ unsigned long last_end;
int err;
for (i = 0; i < nr_ranges; i++) {
- if (ALIGN_DOWN(ranges[i].start, DAMON_MIN_REGION) >=
- ALIGN(ranges[i].end, DAMON_MIN_REGION))
+ unsigned long start, end;
+
+ start = ALIGN_DOWN(ranges[i].start, DAMON_MIN_REGION);
+ end = ALIGN(ranges[i].end, DAMON_MIN_REGION);
+ if (start >= end)
+ return -EINVAL;
+ if (i > 0 && last_end > start)
return -EINVAL;
+ last_end = end;
}
/* Remove regions which are not in the new ranges */
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 465/602] iommufd: Reject invalid read count in iommufd_fault_fops_read()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (463 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 464/602] mm/damon/core: disallow overlapping input ranges for damon_set_regions() Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 466/602] iommufd: Break the loop on failure " Greg Kroah-Hartman
` (140 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Nicolin Chen, Pranjal Shrivastava,
Kevin Tian, Jason Gunthorpe, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolin Chen <nicolinc@nvidia.com>
[ Upstream commit 47916a54eeb2a9e654512ee609f71bd5b29db702 ]
The read count must be large enough to hold one fault or a group's faults.
iommufd_fault_fops_read() does not validate the count, but returns 0 as if
the read had succeeded while leaving the pending fault in the queue.
Return -EINVAL in the undersize cases.
Fixes: 07838f7fd529 ("iommufd: Add iommufd fault object")
Link: https://patch.msgid.link/r/85c118a606fbedc5c132a1f5ec223a5ba23b92d2.1780343944.git.nicolinc@nvidia.com
Cc: stable@vger.kernel.org
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
Reviewed-by: Pranjal Shrivastava <praan@google.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/iommu/iommufd/fault.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/iommu/iommufd/fault.c
+++ b/drivers/iommu/iommufd/fault.c
@@ -273,6 +273,9 @@ static ssize_t iommufd_fault_fops_read(s
if (done >= count ||
group->fault_count * fault_size > count - done) {
iommufd_fault_deliver_restore(fault, group);
+ /* Read count doesn't fit the first fault group */
+ if (done == 0)
+ rc = -EINVAL;
break;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 466/602] iommufd: Break the loop on failure in iommufd_fault_fops_read()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (464 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 465/602] iommufd: Reject invalid read count in iommufd_fault_fops_read() Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 467/602] iommufd: Avoid partial fault group delivery " Greg Kroah-Hartman
` (139 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Nicolin Chen, Pranjal Shrivastava,
Kevin Tian, Jason Gunthorpe, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolin Chen <nicolinc@nvidia.com>
[ Upstream commit 172fc8b19825a0f5884c38f2289188284e2d45ee ]
On a copy_to_user() failure inside the inner list_for_each_entry, only the
inner loop breaks; the outer while re-fetches the just-restored fault group
and retries the failing copy_to_user() forever, spinning the reader at 100%
CPU with fault->mutex held.
Check rc after the inner loop and break the outer while as well.
Fixes: 07838f7fd529 ("iommufd: Add iommufd fault object")
Link: https://patch.msgid.link/r/336a9b6e44fe66a24199d3be777c405c85c98622.1780343944.git.nicolinc@nvidia.com
Cc: stable@vger.kernel.org
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
Reviewed-by: Pranjal Shrivastava <praan@google.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/iommu/iommufd/fault.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/iommu/iommufd/fault.c
+++ b/drivers/iommu/iommufd/fault.c
@@ -299,6 +299,8 @@ static ssize_t iommufd_fault_fops_read(s
}
done += fault_size;
}
+ if (rc)
+ break;
}
mutex_unlock(&fault->mutex);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 467/602] iommufd: Avoid partial fault group delivery in iommufd_fault_fops_read()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (465 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 466/602] iommufd: Break the loop on failure " Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 468/602] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region() Greg Kroah-Hartman
` (138 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Nicolin Chen, Pranjal Shrivastava,
Kevin Tian, Jason Gunthorpe, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolin Chen <nicolinc@nvidia.com>
[ Upstream commit 091ab6d70dc444f56ed14faedbcacfc979f4c613 ]
The cookie returned by xa_alloc() in iommufd_fault_fops_read() is per fault
group, but the inner copy_to_user() runs per fault inside the group. If a
copy fails mid-group, xa_erase clears the cookie and the group is restored
to the deliver list, yet done is not rolled back. The function returns the
partial byte count, with the successfully copied faults sitting at offsets
below done carrying the now-erased cookie. The next read() then re-fetches
the group, allocates a fresh cookie, and re-delivers every fault including
the ones already copied; userspace sees duplicates carrying the new cookie,
and a stale cookie that can never be responded to.
Use a local group_done variable that tracks the per-group progress inside
the inner loop, and only commit done = group_done after the inner loop has
finished successfully. On a copy_to_user failure the outer break skips the
commit, so done remains at its prior start-of-group baseline; the partial
bytes already written past done are undefined to userspace per the read(2)
contract, and the next read re-delivers the whole group atomically.
Fixes: 07838f7fd529 ("iommufd: Add iommufd fault object")
Link: https://patch.msgid.link/r/360cab4d4aeccb0bae275a970e2b3c340a71e0e0.1780343944.git.nicolinc@nvidia.com
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
Reviewed-by: Pranjal Shrivastava <praan@google.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/iommu/iommufd/fault.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
--- a/drivers/iommu/iommufd/fault.c
+++ b/drivers/iommu/iommufd/fault.c
@@ -270,6 +270,8 @@ static ssize_t iommufd_fault_fops_read(s
mutex_lock(&fault->mutex);
while ((group = iommufd_fault_deliver_fetch(fault))) {
+ size_t group_done = done;
+
if (done >= count ||
group->fault_count * fault_size > count - done) {
iommufd_fault_deliver_restore(fault, group);
@@ -291,16 +293,17 @@ static ssize_t iommufd_fault_fops_read(s
iommufd_compose_fault_message(&iopf->fault,
&data, idev,
group->cookie);
- if (copy_to_user(buf + done, &data, fault_size)) {
+ if (copy_to_user(buf + group_done, &data, fault_size)) {
xa_erase(&fault->response, group->cookie);
iommufd_fault_deliver_restore(fault, group);
rc = -EFAULT;
break;
}
- done += fault_size;
+ group_done += fault_size;
}
if (rc)
break;
+ done = group_done;
}
mutex_unlock(&fault->mutex);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 468/602] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (466 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 467/602] iommufd: Avoid partial fault group delivery " Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 469/602] i2c: davinci: Unregister cpufreq notifier on probe failure Greg Kroah-Hartman
` (137 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sebastian Alba Vives, Xu Yilun,
Xu Yilun, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sebastian Alba Vives <sebasjosue84@gmail.com>
[ Upstream commit fc3b071a7c8dc0f5d56defddf6e6fd5aaa3e1e27 ]
afu_ioctl_dma_map() accepts a 64-bit length from userspace via
DFL_FPGA_PORT_DMA_MAP ioctl without an upper bound check. The value
is passed to afu_dma_pin_pages() where npages is derived as
length >> PAGE_SHIFT and passed to pin_user_pages_fast() which takes
int nr_pages, causing implicit truncation if length is very large.
Validate map.length at the ioctl entry point before calling
afu_dma_map_region(), rejecting values whose page count exceeds
INT_MAX.
Fixes: fa8dda1edef9 ("fpga: dfl: afu: add DFL_FPGA_PORT_DMA_MAP/UNMAP ioctls support")
Cc: stable@vger.kernel.org
Signed-off-by: Sebastian Alba Vives <sebasjosue84@gmail.com>
Reviewed-by: Xu Yilun <yilun.xu@intel.com>
Link: https://lore.kernel.org/r/20260518190742.61426-3-sebasjosue84@gmail.com
Signed-off-by: Xu Yilun <yilun.xu@linux.intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/fpga/dfl-afu-main.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/fpga/dfl-afu-main.c
+++ b/drivers/fpga/dfl-afu-main.c
@@ -720,6 +720,9 @@ afu_ioctl_dma_map(struct dfl_feature_pla
if (map.argsz < minsz || map.flags)
return -EINVAL;
+ if (map.length >> PAGE_SHIFT > (u64)INT_MAX)
+ return -EINVAL;
+
ret = afu_dma_map_region(pdata, map.user_addr, map.length, &map.iova);
if (ret)
return ret;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 469/602] i2c: davinci: Unregister cpufreq notifier on probe failure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (467 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 468/602] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region() Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 470/602] VFS/audit: introduce kern_path_parent() for audit Greg Kroah-Hartman
` (136 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Haoxiang Li, Bartosz Golaszewski,
Andi Shyti, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haoxiang Li <haoxiang_li2024@163.com>
[ Upstream commit e43f32816a1b1fe5a86279411626fe3a9be56d45 ]
davinci_i2c_probe() registers a cpufreq transition notifier before adding
the I2C adapter. If i2c_add_numbered_adapter() fails, the probe error path
releases the device resources without unregistering the notifier.
Add a dedicated error path to unregister the cpufreq notifier after
i2c_add_numbered_adapter() fails.
Fixes: 82c0de11b734 ("i2c: davinci: Add cpufreq support")
Signed-off-by: Haoxiang Li <haoxiang_li2024@163.com>
Cc: <stable@vger.kernel.org> # v2.6.36+
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
Link: https://lore.kernel.org/r/20260610030513.2651018-1-haoxiang_li2024@163.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/i2c/busses/i2c-davinci.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/i2c/busses/i2c-davinci.c
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -864,13 +864,15 @@ static int davinci_i2c_probe(struct plat
adap->nr = pdev->id;
r = i2c_add_numbered_adapter(adap);
if (r)
- goto err_unuse_clocks;
+ goto err_cpufreq;
pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev);
return 0;
+err_cpufreq:
+ i2c_davinci_cpufreq_deregister(dev);
err_unuse_clocks:
pm_runtime_dont_use_autosuspend(dev->dev);
pm_runtime_put_sync(dev->dev);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 470/602] VFS/audit: introduce kern_path_parent() for audit
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (468 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 469/602] i2c: davinci: Unregister cpufreq notifier on probe failure Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 471/602] audit: widen ino fields to u64 Greg Kroah-Hartman
` (135 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, NeilBrown, Christian Brauner,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: NeilBrown <neil@brown.name>
[ Upstream commit 76a53de6f7ff0641570364234fb4489f4d4fc8e9 ]
audit_alloc_mark() and audit_get_nd() both need to perform a path
lookup getting the parent dentry (which must exist) and the final
target (following a LAST_NORM name) which sometimes doesn't need to
exist.
They don't need the parent to be locked, but use kern_path_locked() or
kern_path_locked_negative() anyway. This is somewhat misleading to the
casual reader.
This patch introduces a more targeted function, kern_path_parent(),
which returns not holding locks. On success the "path" will
be set to the parent, which must be found, and the return value is the
dentry of the target, which might be negative.
This will clear the way to rename kern_path_locked() which is
otherwise only used to prepare for removing something.
It also allows us to remove kern_path_locked_negative(), which is
transformed into the new kern_path_parent().
Signed-off-by: NeilBrown <neil@brown.name>
Signed-off-by: Christian Brauner <brauner@kernel.org>
Stable-dep-of: 81905b5acbe7 ("audit: fix recursive locking deadlock in audit_dupe_exe()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/namei.c | 43 +++++++++++++++++++++++++++++++++++++++++++
include/linux/namei.h | 1 +
kernel/audit.h | 4 ++--
kernel/audit_fsnotify.c | 9 +++------
kernel/audit_watch.c | 9 ++++++---
5 files changed, 55 insertions(+), 11 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2705,6 +2705,49 @@ static struct dentry *__kern_path_locked
return d;
}
+/**
+ * kern_path_parent: lookup path returning parent and target
+ * @name: path name
+ * @path: path to store parent in
+ *
+ * The path @name should end with a normal component, not "." or ".." or "/".
+ * A lookup is performed and if successful the parent information
+ * is store in @parent and the dentry is returned.
+ *
+ * The dentry maybe negative, the parent will be positive.
+ *
+ * Returns: dentry or error.
+ */
+struct dentry *kern_path_parent(const char *name, struct path *path)
+{
+ struct filename *filename = getname_kernel(name);
+ struct path parent_path;
+ struct dentry *d;
+ struct qstr last;
+ int type, error;
+
+ error = filename_parentat(AT_FDCWD, filename, 0, &parent_path, &last, &type);
+ if (error) {
+ d = ERR_PTR(error);
+ goto out;
+ }
+ if (unlikely(type != LAST_NORM)) {
+ path_put(&parent_path);
+ d = ERR_PTR(-EINVAL);
+ goto out;
+ }
+
+ d = lookup_one_len_unlocked(last.name, parent_path.dentry, last.len);
+ if (IS_ERR(d)) {
+ path_put(&parent_path);
+ goto out;
+ }
+ *path = parent_path;
+out:
+ putname(filename);
+ return d;
+}
+
struct dentry *kern_path_locked(const char *name, struct path *path)
{
struct filename *filename = getname_kernel(name);
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -51,6 +51,7 @@ struct dentry *lookup_one_qstr_excl(cons
struct dentry *base,
unsigned int flags);
extern int kern_path(const char *, unsigned, struct path *);
+struct dentry *kern_path_parent(const char *name, struct path *parent);
extern struct dentry *kern_path_create(int, const char *, struct path *, unsigned int);
extern struct dentry *user_path_create(int, const char __user *, struct path *, unsigned int);
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -279,8 +279,8 @@ extern struct audit_fsnotify_mark *audit
extern char *audit_mark_path(struct audit_fsnotify_mark *mark);
extern void audit_remove_mark(struct audit_fsnotify_mark *audit_mark);
extern void audit_remove_mark_rule(struct audit_krule *krule);
-extern int audit_mark_compare(struct audit_fsnotify_mark *mark,
- unsigned long ino, dev_t dev);
+extern int audit_mark_compare(struct audit_fsnotify_mark *mark, u64 ino,
+ dev_t dev);
extern int audit_dupe_exe(struct audit_krule *new, struct audit_krule *old);
extern int audit_exe_compare(struct task_struct *tsk,
struct audit_fsnotify_mark *mark);
--- a/kernel/audit_fsnotify.c
+++ b/kernel/audit_fsnotify.c
@@ -57,7 +57,7 @@ char *audit_mark_path(struct audit_fsnot
return mark->path;
}
-int audit_mark_compare(struct audit_fsnotify_mark *mark, unsigned long ino, dev_t dev)
+int audit_mark_compare(struct audit_fsnotify_mark *mark, u64 ino, dev_t dev)
{
if (mark->ino == AUDIT_INO_UNSET)
return 0;
@@ -76,17 +76,14 @@ struct audit_fsnotify_mark *audit_alloc_
struct audit_fsnotify_mark *audit_mark;
struct path path;
struct dentry *dentry;
- struct inode *inode;
int ret;
if (pathname[0] != '/' || pathname[len-1] == '/')
return ERR_PTR(-EINVAL);
- dentry = kern_path_locked(pathname, &path);
+ dentry = kern_path_parent(pathname, &path);
if (IS_ERR(dentry))
return ERR_CAST(dentry); /* returning an error */
- inode = path.dentry->d_inode;
- inode_unlock(inode);
audit_mark = kzalloc(sizeof(*audit_mark), GFP_KERNEL);
if (unlikely(!audit_mark)) {
@@ -100,7 +97,7 @@ struct audit_fsnotify_mark *audit_alloc_
audit_update_mark(audit_mark, dentry->d_inode);
audit_mark->rule = krule;
- ret = fsnotify_add_inode_mark(&audit_mark->mark, inode, 0);
+ ret = fsnotify_add_inode_mark(&audit_mark->mark, path.dentry->d_inode, 0);
if (ret < 0) {
audit_mark->path = NULL;
fsnotify_put_mark(&audit_mark->mark);
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -244,7 +244,7 @@ static void audit_watch_log_rule_change(
/* Update inode info in audit rules based on filesystem event. */
static void audit_update_watch(struct audit_parent *parent,
const struct qstr *dname, dev_t dev,
- unsigned long ino, unsigned invalidating)
+ u64 ino, unsigned int invalidating)
{
struct audit_watch *owatch, *nwatch, *nextw;
struct audit_krule *r, *nextr;
@@ -347,15 +347,18 @@ static void audit_remove_parent_watches(
/* Get path information necessary for adding watches. */
static int audit_get_nd(struct audit_watch *watch, struct path *parent)
{
- struct dentry *d = kern_path_locked(watch->path, parent);
+ struct dentry *d;
+
+ d = kern_path_parent(watch->path, parent);
if (IS_ERR(d))
return PTR_ERR(d);
+
if (d_is_positive(d)) {
/* update watch filter fields */
watch->dev = d->d_sb->s_dev;
watch->ino = d_backing_inode(d)->i_ino;
}
- inode_unlock(d_backing_inode(parent->dentry));
+
dput(d);
return 0;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 471/602] audit: widen ino fields to u64
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (469 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 470/602] VFS/audit: introduce kern_path_parent() for audit Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 472/602] audit: use unsigned int instead of unsigned Greg Kroah-Hartman
` (134 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jeff Layton, Paul Moore,
Christian Brauner, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Layton <jlayton@kernel.org>
[ Upstream commit 125dfa218134df7cc112667e92984de9d8cd0bf6 ]
inode->i_ino is being widened from unsigned long to u64. The audit
subsystem uses unsigned long ino in struct fields, function parameters,
and local variables that store inode numbers from arbitrary filesystems.
On 32-bit platforms this truncates inode numbers that exceed 32 bits,
which will cause incorrect audit log entries and broken watch/mark
comparisons.
Widen all audit ino fields, parameters, and locals to u64, and update
the inode format string from %lu to %llu to match.
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Link: https://patch.msgid.link/20260304-iino-u64-v3-2-2257ad83d372@kernel.org
Acked-by: Paul Moore <paul@paul-moore.com>
Signed-off-by: Christian Brauner <brauner@kernel.org>
Stable-dep-of: 81905b5acbe7 ("audit: fix recursive locking deadlock in audit_dupe_exe()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/audit.h | 2 +-
kernel/audit.h | 9 ++++-----
kernel/audit_fsnotify.c | 2 +-
kernel/audit_watch.c | 10 +++++-----
kernel/auditsc.c | 4 ++--
5 files changed, 13 insertions(+), 14 deletions(-)
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -16,7 +16,7 @@
#include <uapi/linux/netfilter/nf_tables.h>
#include <uapi/linux/fanotify.h>
-#define AUDIT_INO_UNSET ((unsigned long)-1)
+#define AUDIT_INO_UNSET ((u64)-1)
#define AUDIT_DEV_UNSET ((dev_t)-1)
struct audit_sig_info {
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -75,7 +75,7 @@ struct audit_names {
int name_len; /* number of chars to log */
bool hidden; /* don't log this record */
- unsigned long ino;
+ u64 ino;
dev_t dev;
umode_t mode;
kuid_t uid;
@@ -219,9 +219,9 @@ extern int auditd_test_task(struct task_
#define AUDIT_INODE_BUCKETS 32
extern struct list_head audit_inode_hash[AUDIT_INODE_BUCKETS];
-static inline int audit_hash_ino(u32 ino)
+static inline int audit_hash_ino(u64 ino)
{
- return (ino & (AUDIT_INODE_BUCKETS-1));
+ return ((u32)ino & (AUDIT_INODE_BUCKETS-1));
}
/* Indicates that audit should log the full pathname. */
@@ -271,8 +271,7 @@ extern int audit_to_watch(struct audit_k
extern int audit_add_watch(struct audit_krule *krule, struct list_head **list);
extern void audit_remove_watch_rule(struct audit_krule *krule);
extern char *audit_watch_path(struct audit_watch *watch);
-extern int audit_watch_compare(struct audit_watch *watch, unsigned long ino,
- dev_t dev);
+extern int audit_watch_compare(struct audit_watch *watch, u64 ino, dev_t dev);
extern struct audit_fsnotify_mark *audit_alloc_mark(struct audit_krule *krule,
char *pathname, int len);
--- a/kernel/audit_fsnotify.c
+++ b/kernel/audit_fsnotify.c
@@ -25,7 +25,7 @@
*/
struct audit_fsnotify_mark {
dev_t dev; /* associated superblock device */
- unsigned long ino; /* associated inode number */
+ u64 ino; /* associated inode number */
char *path; /* insertion path */
struct fsnotify_mark mark; /* fsnotify mark on the inode */
struct audit_krule *rule;
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -37,7 +37,7 @@ struct audit_watch {
refcount_t count; /* reference count */
dev_t dev; /* associated superblock device */
char *path; /* insertion path */
- unsigned long ino; /* associated inode number */
+ u64 ino; /* associated inode number */
struct audit_parent *parent; /* associated parent */
struct list_head wlist; /* entry in parent->watches list */
struct list_head rules; /* anchor for krule->rlist */
@@ -125,7 +125,7 @@ char *audit_watch_path(struct audit_watc
return watch->path;
}
-int audit_watch_compare(struct audit_watch *watch, unsigned long ino, dev_t dev)
+int audit_watch_compare(struct audit_watch *watch, u64 ino, dev_t dev)
{
return (watch->ino != AUDIT_INO_UNSET) &&
(watch->ino == ino) &&
@@ -285,7 +285,7 @@ static void audit_update_watch(struct au
list_del(&oentry->rule.list);
audit_panic("error updating watch, removing");
} else {
- int h = audit_hash_ino((u32)ino);
+ int h = audit_hash_ino(ino);
/*
* nentry->rule.watch == oentry->rule.watch so
@@ -439,7 +439,7 @@ int audit_add_watch(struct audit_krule *
audit_add_to_parent(krule, parent);
- h = audit_hash_ino((u32)watch->ino);
+ h = audit_hash_ino(watch->ino);
*list = &audit_inode_hash[h];
error:
path_put(&parent_path);
@@ -527,7 +527,7 @@ int audit_dupe_exe(struct audit_krule *n
int audit_exe_compare(struct task_struct *tsk, struct audit_fsnotify_mark *mark)
{
struct file *exe_file;
- unsigned long ino;
+ u64 ino;
dev_t dev;
/* only do exe filtering if we are recording @current events/records */
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -884,7 +884,7 @@ static int audit_filter_inode_name(struc
struct audit_names *n,
struct audit_context *ctx)
{
- int h = audit_hash_ino((u32)n->ino);
+ int h = audit_hash_ino(n->ino);
struct list_head *list = &audit_inode_hash[h];
return __audit_filter_op(tsk, ctx, list, n, ctx->major);
@@ -1549,7 +1549,7 @@ static void audit_log_name(struct audit_
audit_log_format(ab, " name=(null)");
if (n->ino != AUDIT_INO_UNSET)
- audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#ho ouid=%u ogid=%u rdev=%02x:%02x",
+ audit_log_format(ab, " inode=%llu dev=%02x:%02x mode=%#ho ouid=%u ogid=%u rdev=%02x:%02x",
n->ino,
MAJOR(n->dev),
MINOR(n->dev),
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 472/602] audit: use unsigned int instead of unsigned
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (470 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 471/602] audit: widen ino fields to u64 Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 473/602] audit: fix recursive locking deadlock in audit_dupe_exe() Greg Kroah-Hartman
` (133 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Ricardo Robaina, Paul Moore,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ricardo Robaina <rrobaina@redhat.com>
[ Upstream commit 8b226771014beab1292081151a99530886ce54b4 ]
Address checkpatch.pl warning below, across the audit subsystem:
WARNING: Prefer 'unsigned int' to bare use of 'unsigned'
Minor cleanup, no functional changes.
Signed-off-by: Ricardo Robaina <rrobaina@redhat.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
Stable-dep-of: 81905b5acbe7 ("audit: fix recursive locking deadlock in audit_dupe_exe()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/audit.h | 4 ++--
include/linux/audit_arch.h | 12 ++++++------
kernel/audit.c | 2 +-
kernel/audit.h | 2 +-
kernel/audit_tree.c | 2 +-
kernel/auditfilter.c | 8 ++++----
kernel/auditsc.c | 2 +-
lib/compat_audit.c | 12 ++++++------
8 files changed, 22 insertions(+), 22 deletions(-)
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -123,8 +123,8 @@ enum audit_nfcfgop {
AUDIT_NFT_OP_INVALID,
};
-extern int __init audit_register_class(int class, unsigned *list);
-extern int audit_classify_syscall(int abi, unsigned syscall);
+extern int __init audit_register_class(int class, unsigned int *list);
+extern int audit_classify_syscall(int abi, unsigned int syscall);
extern int audit_classify_arch(int arch);
/* audit_names->type values */
--- a/include/linux/audit_arch.h
+++ b/include/linux/audit_arch.h
@@ -21,13 +21,13 @@ enum auditsc_class_t {
AUDITSC_NVALS /* count */
};
-extern int audit_classify_compat_syscall(int abi, unsigned syscall);
+extern int audit_classify_compat_syscall(int abi, unsigned int syscall);
/* only for compat system calls */
-extern unsigned compat_write_class[];
-extern unsigned compat_read_class[];
-extern unsigned compat_dir_class[];
-extern unsigned compat_chattr_class[];
-extern unsigned compat_signal_class[];
+extern unsigned int compat_write_class[];
+extern unsigned int compat_read_class[];
+extern unsigned int compat_dir_class[];
+extern unsigned int compat_chattr_class[];
+extern unsigned int compat_signal_class[];
#endif
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1985,7 +1985,7 @@ static void audit_log_vformat(struct aud
* here and AUDIT_BUFSIZ is at least 1024, then we can
* log everything that printk could have logged. */
avail = audit_expand(ab,
- max_t(unsigned, AUDIT_BUFSIZ, 1+len-avail));
+ max_t(unsigned int, AUDIT_BUFSIZ, 1+len-avail));
if (!avail)
goto out_va_end;
len = vsnprintf(skb_tail_pointer(skb), avail, fmt, args2);
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -227,7 +227,7 @@ static inline int audit_hash_ino(u64 ino
/* Indicates that audit should log the full pathname. */
#define AUDIT_NAME_FULL -1
-extern int audit_match_class(int class, unsigned syscall);
+extern int audit_match_class(int class, unsigned int syscall);
extern int audit_comparator(const u32 left, const u32 op, const u32 right);
extern int audit_uid_comparator(kuid_t left, u32 op, kuid_t right);
extern int audit_gid_comparator(kgid_t left, u32 op, kgid_t right);
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -33,7 +33,7 @@ struct audit_chunk {
struct audit_node {
struct list_head list;
struct audit_tree *owner;
- unsigned index; /* index; upper bit indicates 'will prune' */
+ unsigned int index; /* index; upper bit indicates 'will prune' */
} owners[] __counted_by(count);
};
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -165,13 +165,13 @@ static inline int audit_to_inode(struct
static __u32 *classes[AUDIT_SYSCALL_CLASSES];
-int __init audit_register_class(int class, unsigned *list)
+int __init audit_register_class(int class, unsigned int *list)
{
__u32 *p = kcalloc(AUDIT_BITMASK_SIZE, sizeof(__u32), GFP_KERNEL);
if (!p)
return -ENOMEM;
while (*list != ~0U) {
- unsigned n = *list++;
+ unsigned int n = *list++;
if (n >= AUDIT_BITMASK_SIZE * 32 - AUDIT_SYSCALL_CLASSES) {
kfree(p);
return -EINVAL;
@@ -186,7 +186,7 @@ int __init audit_register_class(int clas
return 0;
}
-int audit_match_class(int class, unsigned syscall)
+int audit_match_class(int class, unsigned int syscall)
{
if (unlikely(syscall >= AUDIT_BITMASK_SIZE * 32))
return 0;
@@ -237,7 +237,7 @@ static int audit_match_signal(struct aud
/* Common user-space to kernel rule translation. */
static inline struct audit_entry *audit_to_entry_common(struct audit_rule_data *rule)
{
- unsigned listnr;
+ unsigned int listnr;
struct audit_entry *entry;
int i, err;
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -150,7 +150,7 @@ static const struct audit_nfcfgop_tab au
static int audit_match_perm(struct audit_context *ctx, int mask)
{
- unsigned n;
+ unsigned int n;
if (unlikely(!ctx))
return 0;
--- a/lib/compat_audit.c
+++ b/lib/compat_audit.c
@@ -4,32 +4,32 @@
#include <linux/audit_arch.h>
#include <asm/unistd32.h>
-unsigned compat_dir_class[] = {
+unsigned int compat_dir_class[] = {
#include <asm-generic/audit_dir_write.h>
~0U
};
-unsigned compat_read_class[] = {
+unsigned int compat_read_class[] = {
#include <asm-generic/audit_read.h>
~0U
};
-unsigned compat_write_class[] = {
+unsigned int compat_write_class[] = {
#include <asm-generic/audit_write.h>
~0U
};
-unsigned compat_chattr_class[] = {
+unsigned int compat_chattr_class[] = {
#include <asm-generic/audit_change_attr.h>
~0U
};
-unsigned compat_signal_class[] = {
+unsigned int compat_signal_class[] = {
#include <asm-generic/audit_signal.h>
~0U
};
-int audit_classify_compat_syscall(int abi, unsigned syscall)
+int audit_classify_compat_syscall(int abi, unsigned int syscall)
{
switch (syscall) {
#ifdef __NR_open
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 473/602] audit: fix recursive locking deadlock in audit_dupe_exe()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (471 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 472/602] audit: use unsigned int instead of unsigned Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 474/602] i2c: i801: fix hardware state machine corruption in error path Greg Kroah-Hartman
` (132 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, stable, Waiman Long,
Richard Guy Briggs, Nathan Chancellor, Ricardo Robaina,
Paul Moore, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ricardo Robaina <rrobaina@redhat.com>
[ Upstream commit 81905b5acbe77284734438df3fbec1158e6429a3 ]
A deadlock occurs in the audit subsystem when duplicating
executable-related rules.
When a file is moved (e.g., via do_renameat2()), the VFS layer locks
the parent directory (I_MUTEX_PARENT), which synchronously triggers an
fsnotify_move event. If an existing executable audit rule matches the
file being moved, the audit subsystem catches this event and calls
audit_dupe_exe() to duplicate the watch and update the rule. Then,
audit_alloc_mark() would call kern_path_parent() to resolve the path,
leading to a blind attempt to acquire the exact same I_MUTEX_PARENT lock
already held by the task, resulting in the following recursive locking
deadlock:
============================================
WARNING: possible recursive locking detected
6.12.0-55.27.1.el10_0.x86_64+debug #1 Not tainted
--------------------------------------------
mv/5099 is trying to acquire lock:
ffff888132845358 (&inode->i_sb->s_type->i_mutex_dir_key/1){+.+.}-{3:3},
at: __kern_path_locked+0x10a/0x2f0
but task is already holding lock:
ffff888132846b58 (&inode->i_sb->s_type->i_mutex_dir_key/1){+.+.}-{3:3},
at: lock_two_directories+0x13f/0x2b0
other info that might help us debug this:
Possible unsafe locking scenario:
CPU0
----
lock(&inode->i_sb->s_type->i_mutex_dir_key/1);
lock(&inode->i_sb->s_type->i_mutex_dir_key/1);
*** DEADLOCK ***
May be due to missing lock nesting notation
6 locks held by mv/5099:
#0: ffff888112a9c440 (sb_writers#13)
at: do_renameat2+0x34c/0xbc0
#1: ffff888112a9c790 (&type->s_vfs_rename_key#3)
at: do_renameat2+0x415/0xbc0
#2: ffff888132846b58 (&inode->i_sb->s_type->i_mutex_dir_key/1)
at: lock_two_directories+0x13f/0x2b0
#3: ffff888132845358 (&inode->i_sb->s_type->i_mutex_dir_key/5)
at: lock_two_directories+0x175/0x2b0
#4: ffffffffb3a1fb10 (&fsnotify_mark_srcu)
at: fsnotify+0x454/0x28a0
#5: ffffffffaf886230 (audit_filter_mutex)
at: audit_update_watch+0x36/0x11e0
stack backtrace:
Call Trace:
<TASK>
dump_stack_lvl+0x6f/0xb0
print_deadlock_bug.cold+0xbd/0xca
validate_chain+0x83a/0xf00
__lock_acquire+0xcac/0x1d20
lock_acquire.part.0+0x11b/0x360
down_write_nested+0x9f/0x230
__kern_path_locked+0x10a/0x2f0
kern_path_locked+0x26/0x40
audit_alloc_mark+0xfb/0x4f0
audit_dupe_exe+0x6c/0xe0
audit_dupe_rule+0x6c2/0xc00
audit_update_watch+0x4cc/0x11e0
audit_watch_handle_event+0x12c/0x1b0
send_to_group+0x5d0/0x8b0
fsnotify+0x615/0x28a0
fsnotify_move+0x1d8/0x630
vfs_rename+0xdcd/0x1df0
do_renameat2+0x9d4/0xbc0
__x64_sys_renameat+0x192/0x260
do_syscall_64+0x92/0x180
entry_SYSCALL_64_after_hwframe+0x76/0x7e
RIP: 0033:0x7f0491fe8c4e
Code: 0f 1f 40 00 48 8b 15 c1 e1 16 00 f7 d8 64 89 02 b8 ff ff ff ff
c3 66 0f 1f 44 00 00 f3 0f 1e fa 49 89 ca b8 08 01 00 00 0f 05 <48>
3d 00 f0 ff ff 77 0a c3 66 0f 1f 84 00 00 00 00 00 48 8b 15 89
RSP: 002b:00007ffc7210bf38 EFLAGS: 00000246 ORIG_RAX: 0000000000000108
RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f0491fe8c4e
RDX: 0000000000000003 RSI: 00007ffc7210e6c8 RDI: 00000000ffffff9c
RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000001
R10: 00005575eb2dae2a R11: 0000000000000246 R12: 00005575eb2dae2a
R13: 00007ffc7210e6c8 R14: 0000000000000003 R15: 00000000ffffff9c
</TASK>
The aforementioned deadlock can be consistently reproduced by running
the script below:
audit-dupe-exe-deadlock.sh
--------------------------
#!/bin/bash
auditctl -D
mkdir -p /tmp/foo
touch /tmp/file
auditctl -a always,exit -F exe=/tmp/file -F path=/tmp/file -S all -k dr
mv /tmp/file /tmp/foo/file
rm -Rf /tmp/foo
This patch fixes the issue by introducing struct audit_watch_ctx to pass
the fsnotify event context down to audit_alloc_mark(). By utilizing the
already-resolved directory inode provided by the event, we bypass the
kern_path_parent() path resolution entirely, safely avoiding the
recursive lock. Furthermore, it explicitly allows duplicate fsnotify
marks (allow_dups = 1) during the rename update, allowing the new rule's
mark to safely coexist with the old rule's mark until the old rule is
freed.
P.S.: This issue was identified and reproduced during a comprehensive
code coverage analysis of the audit subsystem. The full report is
available at the link below:
https://people.redhat.com/rrobaina/audit-code-coverage-analysis.pdf
P.P.S: With the permission of both Ricardo and Nathan, I've squashed a
fixup patch from Nathan that addresses a compile time error when
CONFIG_AUDITSYSCALL=n.
Cc: stable@kernel.org
Fixes: 34d99af52ad4 ("audit: implement audit by executable")
Acked-by: Waiman Long <longman@redhat.com>
Acked-by: Richard Guy Briggs <rgb@redhat.com>
Signed-off-by: Nathan Chancellor <nathan@kernel.org>
Signed-off-by: Ricardo Robaina <rrobaina@redhat.com>
[PM: move link metadata into the msg, apply fix from NC]
Signed-off-by: Paul Moore <paul@paul-moore.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
kernel/audit.h | 17 ++++++++++++-----
kernel/audit_fsnotify.c | 32 +++++++++++++++++++++++---------
kernel/audit_watch.c | 25 +++++++++++++++++--------
kernel/auditfilter.c | 9 +++++----
4 files changed, 57 insertions(+), 26 deletions(-)
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -250,8 +250,13 @@ extern int audit_del_rule(struct audit_e
extern void audit_free_rule_rcu(struct rcu_head *head);
extern struct list_head audit_filter_list[];
-extern struct audit_entry *audit_dupe_rule(struct audit_krule *old);
+struct audit_watch_ctx {
+ struct inode *dir;
+ struct inode *child;
+};
+extern struct audit_entry *audit_dupe_rule(struct audit_krule *old,
+ struct audit_watch_ctx *ctx);
extern void audit_log_d_path_exe(struct audit_buffer *ab,
struct mm_struct *mm);
@@ -274,13 +279,15 @@ extern char *audit_watch_path(struct aud
extern int audit_watch_compare(struct audit_watch *watch, u64 ino, dev_t dev);
extern struct audit_fsnotify_mark *audit_alloc_mark(struct audit_krule *krule,
- char *pathname, int len);
+ char *pathname, int len,
+ struct audit_watch_ctx *ctx);
extern char *audit_mark_path(struct audit_fsnotify_mark *mark);
extern void audit_remove_mark(struct audit_fsnotify_mark *audit_mark);
extern void audit_remove_mark_rule(struct audit_krule *krule);
extern int audit_mark_compare(struct audit_fsnotify_mark *mark, u64 ino,
dev_t dev);
-extern int audit_dupe_exe(struct audit_krule *new, struct audit_krule *old);
+extern int audit_dupe_exe(struct audit_krule *new, struct audit_krule *old,
+ struct audit_watch_ctx *ctx);
extern int audit_exe_compare(struct task_struct *tsk,
struct audit_fsnotify_mark *mark);
@@ -311,13 +318,13 @@ extern struct list_head *audit_killed_tr
#define audit_watch_path(w) ""
#define audit_watch_compare(w, i, d) 0
-#define audit_alloc_mark(k, p, l) (ERR_PTR(-EINVAL))
+#define audit_alloc_mark(k, p, l, c) (ERR_PTR(-EINVAL))
#define audit_mark_path(m) ""
#define audit_remove_mark(m) do { } while (0)
#define audit_remove_mark_rule(k) do { } while (0)
#define audit_mark_compare(m, i, d) 0
#define audit_exe_compare(t, m) (-EINVAL)
-#define audit_dupe_exe(n, o) (-EINVAL)
+#define audit_dupe_exe(n, o, c) (-EINVAL)
#define audit_remove_tree_rule(rule) BUG()
#define audit_add_tree_rule(rule) -EINVAL
--- a/kernel/audit_fsnotify.c
+++ b/kernel/audit_fsnotify.c
@@ -71,19 +71,30 @@ static void audit_update_mark(struct aud
audit_mark->ino = inode ? inode->i_ino : AUDIT_INO_UNSET;
}
-struct audit_fsnotify_mark *audit_alloc_mark(struct audit_krule *krule, char *pathname, int len)
+struct audit_fsnotify_mark *audit_alloc_mark(struct audit_krule *krule, char *pathname,
+ int len, struct audit_watch_ctx *ctx)
{
struct audit_fsnotify_mark *audit_mark;
struct path path;
struct dentry *dentry;
- int ret;
+ struct inode *dir, *child;
+ int ret, allow_dups;
if (pathname[0] != '/' || pathname[len-1] == '/')
return ERR_PTR(-EINVAL);
- dentry = kern_path_parent(pathname, &path);
- if (IS_ERR(dentry))
- return ERR_CAST(dentry); /* returning an error */
+ if (!ctx) {
+ dentry = kern_path_parent(pathname, &path);
+ if (IS_ERR(dentry))
+ return ERR_CAST(dentry); /* returning an error */
+ dir = d_inode(path.dentry);
+ child = d_inode(dentry);
+ allow_dups = 0;
+ } else {
+ dir = ctx->dir;
+ child = ctx->child;
+ allow_dups = 1;
+ }
audit_mark = kzalloc(sizeof(*audit_mark), GFP_KERNEL);
if (unlikely(!audit_mark)) {
@@ -94,18 +105,21 @@ struct audit_fsnotify_mark *audit_alloc_
fsnotify_init_mark(&audit_mark->mark, audit_fsnotify_group);
audit_mark->mark.mask = AUDIT_FS_EVENTS;
audit_mark->path = pathname;
- audit_update_mark(audit_mark, dentry->d_inode);
audit_mark->rule = krule;
- ret = fsnotify_add_inode_mark(&audit_mark->mark, path.dentry->d_inode, 0);
+ audit_update_mark(audit_mark, child);
+ ret = fsnotify_add_inode_mark(&audit_mark->mark, dir, allow_dups);
+
if (ret < 0) {
audit_mark->path = NULL;
fsnotify_put_mark(&audit_mark->mark);
audit_mark = ERR_PTR(ret);
}
out:
- dput(dentry);
- path_put(&path);
+ if (!ctx) {
+ dput(dentry);
+ path_put(&path);
+ }
return audit_mark;
}
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -244,7 +244,8 @@ static void audit_watch_log_rule_change(
/* Update inode info in audit rules based on filesystem event. */
static void audit_update_watch(struct audit_parent *parent,
const struct qstr *dname, dev_t dev,
- u64 ino, unsigned int invalidating)
+ u64 ino, unsigned int invalidating,
+ struct audit_watch_ctx *ctx)
{
struct audit_watch *owatch, *nwatch, *nextw;
struct audit_krule *r, *nextr;
@@ -280,7 +281,7 @@ static void audit_update_watch(struct au
list_del(&oentry->rule.rlist);
list_del_rcu(&oentry->list);
- nentry = audit_dupe_rule(&oentry->rule);
+ nentry = audit_dupe_rule(&oentry->rule, ctx);
if (IS_ERR(nentry)) {
list_del(&oentry->rule.list);
audit_panic("error updating watch, removing");
@@ -479,10 +480,17 @@ static int audit_watch_handle_event(stru
if (WARN_ON_ONCE(inode_mark->group != audit_watch_group))
return 0;
- if (mask & (FS_CREATE|FS_MOVED_TO) && inode)
- audit_update_watch(parent, dname, inode->i_sb->s_dev, inode->i_ino, 0);
- else if (mask & (FS_DELETE|FS_MOVED_FROM))
- audit_update_watch(parent, dname, AUDIT_DEV_UNSET, AUDIT_INO_UNSET, 1);
+ if (mask & (FS_CREATE|FS_MOVED_TO) && inode) {
+ struct audit_watch_ctx ctx = { .dir = dir, .child = inode };
+
+ audit_update_watch(parent, dname, inode->i_sb->s_dev, inode->i_ino, 0,
+ &ctx);
+ } else if (mask & (FS_DELETE|FS_MOVED_FROM)) {
+ struct audit_watch_ctx ctx = { .dir = dir, .child = NULL };
+
+ audit_update_watch(parent, dname, AUDIT_DEV_UNSET, AUDIT_INO_UNSET, 1,
+ &ctx);
+ }
else if (mask & (FS_DELETE_SELF|FS_UNMOUNT|FS_MOVE_SELF))
audit_remove_parent_watches(parent);
@@ -505,7 +513,8 @@ static int __init audit_watch_init(void)
}
device_initcall(audit_watch_init);
-int audit_dupe_exe(struct audit_krule *new, struct audit_krule *old)
+int audit_dupe_exe(struct audit_krule *new, struct audit_krule *old,
+ struct audit_watch_ctx *ctx)
{
struct audit_fsnotify_mark *audit_mark;
char *pathname;
@@ -514,7 +523,7 @@ int audit_dupe_exe(struct audit_krule *n
if (!pathname)
return -ENOMEM;
- audit_mark = audit_alloc_mark(new, pathname, strlen(pathname));
+ audit_mark = audit_alloc_mark(new, pathname, strlen(pathname), ctx);
if (IS_ERR(audit_mark)) {
kfree(pathname);
return PTR_ERR(audit_mark);
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -590,7 +590,7 @@ static struct audit_entry *audit_data_to
err = PTR_ERR(str);
goto exit_free;
}
- audit_mark = audit_alloc_mark(&entry->rule, str, f_val);
+ audit_mark = audit_alloc_mark(&entry->rule, str, f_val, NULL);
if (IS_ERR(audit_mark)) {
kfree(str);
err = PTR_ERR(audit_mark);
@@ -818,7 +818,8 @@ static inline int audit_dupe_lsm_field(s
* rule with the new rule in the filterlist, then free the old rule.
* The rlist element is undefined; list manipulations are handled apart from
* the initial copy. */
-struct audit_entry *audit_dupe_rule(struct audit_krule *old)
+struct audit_entry *audit_dupe_rule(struct audit_krule *old,
+ struct audit_watch_ctx *ctx)
{
u32 fcount = old->field_count;
struct audit_entry *entry;
@@ -877,7 +878,7 @@ struct audit_entry *audit_dupe_rule(stru
new->filterkey = fk;
break;
case AUDIT_EXE:
- err = audit_dupe_exe(new, old);
+ err = audit_dupe_exe(new, old, ctx);
break;
}
if (err) {
@@ -1408,7 +1409,7 @@ static int update_lsm_rule(struct audit_
if (!security_audit_rule_known(r))
return 0;
- nentry = audit_dupe_rule(r);
+ nentry = audit_dupe_rule(r, NULL);
if (entry->rule.exe)
audit_remove_mark(entry->rule.exe);
if (IS_ERR(nentry)) {
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 474/602] i2c: i801: fix hardware state machine corruption in error path
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (472 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 473/602] audit: fix recursive locking deadlock in audit_dupe_exe() Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 475/602] ALSA: hda: conexant: Remove mic bias threshold override Greg Kroah-Hartman
` (131 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Mingyu Wang, Andi Shyti, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mingyu Wang <25181214217@stu.xidian.edu.cn>
[ Upstream commit 10dd1a736d557e310a77117832874729a0175d57 ]
A severe livelock and subsequent Hung Task panic were observed in the
i2c-i801 driver during concurrent Fuzzing. The crash is caused by an
unconditional hardware register cleanup in the error handling path of
i801_access().
When i801_check_pre() fails (e.g., returning -EBUSY because the SMBus
controller is actively used by BIOS/ACPI), the kernel does not actually
acquire the hardware ownership. However, the code jumps to the 'out'
label and executes:
iowrite8(SMBHSTSTS_INUSE_STS | STATUS_FLAGS, SMBHSTSTS(priv));
This forcefully clears the INUSE_STS lock and resets the hardware status
flags without owning the controller. Doing so interrupts ongoing BIOS/ACPI
transactions and totally corrupts the SMBus hardware state machine.
Consequently, all subsequent i801_access() calls fail at the pre-check
stage, triggering an endless stream of "SMBus is busy, can't use it!"
error logs. Over a slow serial console, this printk flood monopolizes
the CPU (Console Livelock), starving other processes trying to acquire
the mmap_lock down_read semaphore, ultimately triggering the hung task
watchdog.
Fix this by moving the 'out' label below the hardware register cleanup.
If i801_check_pre() fails, we safely bypass the iowrite8() and only
release the software locks (pm_runtime and mutex), strictly adhering to
the rule of not releasing resources that were never acquired.
Fixes: 1f760b87e54c ("i2c: i801: Call i801_check_pre() from i801_access()")
Signed-off-by: Mingyu Wang <25181214217@stu.xidian.edu.cn>
Cc: <stable@vger.kernel.org> # v6.3+
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
Link: https://lore.kernel.org/r/20260512093534.348655-1-w15303746062@163.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/i2c/busses/i2c-i801.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -930,13 +930,13 @@ static s32 i801_access(struct i2c_adapte
*/
if (hwpec)
outb_p(inb_p(SMBAUXCTL(priv)) & ~SMBAUXCTL_CRC, SMBAUXCTL(priv));
-out:
/*
* Unlock the SMBus device for use by BIOS/ACPI,
* and clear status flags if not done already.
*/
outb_p(SMBHSTSTS_INUSE_STS | STATUS_FLAGS, SMBHSTSTS(priv));
+out:
pm_runtime_mark_last_busy(&priv->pci_dev->dev);
pm_runtime_put_autosuspend(&priv->pci_dev->dev);
mutex_unlock(&priv->acpi_lock);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 475/602] ALSA: hda: conexant: Remove mic bias threshold override
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (473 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 474/602] i2c: i801: fix hardware state machine corruption in error path Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 476/602] ALSA: hda: Fix cached processing coefficient verbs Greg Kroah-Hartman
` (130 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Zhang Heng, Takashi Iwai,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Heng <zhangheng@kylinos.cn>
[ Upstream commit f52524da7084c1a54683ae9fbc73e93fff19dd64 ]
Remove the mic bias current comparator threshold override (NID 0x1c,
verb 0x320, value 0x010) from Conexant codec driver.
This override was originally intended to support volume up/down controls on
headsets with inline remote controls, but it causes microphone detection
failures on some headsets with impedance less than 1k ohm.
After consulting with the vendor's engineers, it was confirmed that this
setting is board-specific and should be handled by BIOS/firmware rather
than the generic codec driver, especially since inline remote support
is not currently implemented.
Fixes: 7aeb25908648 ("ALSA: hda/conexant: Fix headset auto detect fail in cx8070 and SN6140")
Cc: stable@vger.kernel.org
Signed-off-by: Zhang Heng <zhangheng@kylinos.cn>
Link: https://patch.msgid.link/20260713100329.306892-1-zhangheng@kylinos.cn
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
sound/pci/hda/patch_conexant.c | 3 ---
1 file changed, 3 deletions(-)
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -168,9 +168,6 @@ static void cx_fixup_headset_recog(struc
{
unsigned int mic_present;
- /* fix some headset type recognize fail issue, such as EDIFIER headset */
- /* set micbias output current comparator threshold from 66% to 55%. */
- snd_hda_codec_write(codec, 0x1c, 0, 0x320, 0x010);
/* set OFF voltage for DFET from -1.2V to -0.8V, set headset micbias register
* value adjustment trim from 2.2K ohms to 2.0K ohms.
*/
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 476/602] ALSA: hda: Fix cached processing coefficient verbs
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (474 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 475/602] ALSA: hda: conexant: Remove mic bias threshold override Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 477/602] rxrpc: Pull out certain app callback funcs into an ops table Greg Kroah-Hartman
` (129 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Xu Rao, Takashi Iwai, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xu Rao <raoxu@uniontech.com>
[ Upstream commit f67be28fdf8b5d31ac1cc1152bb17250f9f8f513 ]
Intel HD Audio defines Coefficient Index and Processing Coefficient as
separate audio widget controls in the Audio Widget Verb Definitions:
Coefficient Index selects the coefficient slot, while Processing
Coefficient accesses the value at the selected slot.
hda_reg_read_coef() selects the slot with AC_VERB_SET_COEF_INDEX, but
then uses AC_VERB_GET_COEF_INDEX for the value read. That reads back the
selected index instead of the coefficient value. hda_reg_write_coef()
has the same issue and builds the value write from AC_VERB_GET_COEF_INDEX
instead of AC_VERB_SET_PROC_COEF.
This only affects the regmap coefficient cache path used by codecs that
set codec->cache_coef. Direct coefficient helpers already use the normal
SET_COEF_INDEX followed by GET_PROC_COEF or SET_PROC_COEF sequence, which
is likely why this has not been noticed widely.
Use AC_VERB_GET_PROC_COEF for cached coefficient reads and
AC_VERB_SET_PROC_COEF for cached coefficient writes.
Fixes: 40ba66a702b8 ("ALSA: hda - Add cache support for COEF read/write")
Cc: stable@vger.kernel.org
Signed-off-by: Xu Rao <raoxu@uniontech.com>
Link: https://patch.msgid.link/DB9023BF2920BA99+20260707132419.1731342-1-raoxu@uniontech.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
sound/hda/hdac_regmap.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/sound/hda/hdac_regmap.c
+++ b/sound/hda/hdac_regmap.c
@@ -214,7 +214,7 @@ static int hda_reg_read_coef(struct hdac
err = snd_hdac_exec_verb(codec, verb, 0, NULL);
if (err < 0)
return err;
- verb = (reg & ~0xfffff) | (AC_VERB_GET_COEF_INDEX << 8);
+ verb = (reg & ~0xfffff) | (AC_VERB_GET_PROC_COEF << 8);
return snd_hdac_exec_verb(codec, verb, 0, val);
}
@@ -232,7 +232,7 @@ static int hda_reg_write_coef(struct hda
err = snd_hdac_exec_verb(codec, verb, 0, NULL);
if (err < 0)
return err;
- verb = (reg & ~0xfffff) | (AC_VERB_GET_COEF_INDEX << 8) |
+ verb = (reg & ~0xfffff) | (AC_VERB_SET_PROC_COEF << 8) |
(val & 0xffff);
return snd_hdac_exec_verb(codec, verb, 0, NULL);
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 477/602] rxrpc: Pull out certain app callback funcs into an ops table
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (475 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 476/602] ALSA: hda: Fix cached processing coefficient verbs Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 478/602] rxrpc: serialize kernel accept preallocation with socket teardown Greg Kroah-Hartman
` (128 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Howells, Marc Dionne,
Simon Horman, linux-afs, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <dhowells@redhat.com>
[ Upstream commit 23738cc8048322cf324f330cd697380fb3455da5 ]
A number of functions separately furnish an AF_RXRPC socket with callback
function pointers into a kernel app (such as the AFS filesystem) that is
using it. Replace most of these with an ops table for the entire socket.
This makes it easier to add more callback functions.
Note that the call incoming data processing callback is retaind as that
gets set to different things, depending on the type of op.
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
Link: https://patch.msgid.link/20250411095303.2316168-3-dhowells@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: dc175389b18c ("rxrpc: serialize kernel accept preallocation with socket teardown")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/afs/rxrpc.c | 11 ++++++++---
include/net/af_rxrpc.h | 25 +++++++++++++++----------
net/rxrpc/af_rxrpc.c | 20 ++++++++------------
net/rxrpc/ar-internal.h | 3 +--
net/rxrpc/call_accept.c | 34 ++++++++++++++++------------------
net/rxrpc/rxperf.c | 10 +++++++---
6 files changed, 55 insertions(+), 48 deletions(-)
--- a/fs/afs/rxrpc.c
+++ b/fs/afs/rxrpc.c
@@ -24,8 +24,15 @@ static void afs_wake_up_async_call(struc
static void afs_process_async_call(struct work_struct *);
static void afs_rx_new_call(struct sock *, struct rxrpc_call *, unsigned long);
static void afs_rx_discard_new_call(struct rxrpc_call *, unsigned long);
+static void afs_rx_attach(struct rxrpc_call *rxcall, unsigned long user_call_ID);
static int afs_deliver_cm_op_id(struct afs_call *);
+static const struct rxrpc_kernel_ops afs_rxrpc_callback_ops = {
+ .notify_new_call = afs_rx_new_call,
+ .discard_new_call = afs_rx_discard_new_call,
+ .user_attach_call = afs_rx_attach,
+};
+
/* asynchronous incoming call initial processing */
static const struct afs_call_type afs_RXCMxxxx = {
.name = "CB.xxxx",
@@ -84,8 +91,7 @@ int afs_open_socket(struct afs_net *net)
* it sends back to us.
*/
- rxrpc_kernel_new_call_notification(socket, afs_rx_new_call,
- afs_rx_discard_new_call);
+ rxrpc_kernel_set_notifications(socket, &afs_rxrpc_callback_ops);
ret = kernel_listen(socket, INT_MAX);
if (ret < 0)
@@ -758,7 +764,6 @@ void afs_charge_preallocation(struct wor
if (rxrpc_kernel_charge_accept(net->socket,
afs_wake_up_async_call,
- afs_rx_attach,
(unsigned long)call,
GFP_KERNEL,
call->debug_id) < 0)
--- a/include/net/af_rxrpc.h
+++ b/include/net/af_rxrpc.h
@@ -29,18 +29,23 @@ enum rxrpc_interruptibility {
*/
extern atomic_t rxrpc_debug_id;
+/*
+ * Operations table for rxrpc to call out to a kernel application (e.g. kAFS).
+ */
+struct rxrpc_kernel_ops {
+ void (*notify_new_call)(struct sock *sk, struct rxrpc_call *call,
+ unsigned long user_call_ID);
+ void (*discard_new_call)(struct rxrpc_call *call, unsigned long user_call_ID);
+ void (*user_attach_call)(struct rxrpc_call *call, unsigned long user_call_ID);
+};
+
typedef void (*rxrpc_notify_rx_t)(struct sock *, struct rxrpc_call *,
unsigned long);
typedef void (*rxrpc_notify_end_tx_t)(struct sock *, struct rxrpc_call *,
unsigned long);
-typedef void (*rxrpc_notify_new_call_t)(struct sock *, struct rxrpc_call *,
- unsigned long);
-typedef void (*rxrpc_discard_new_call_t)(struct rxrpc_call *, unsigned long);
-typedef void (*rxrpc_user_attach_call_t)(struct rxrpc_call *, unsigned long);
-void rxrpc_kernel_new_call_notification(struct socket *,
- rxrpc_notify_new_call_t,
- rxrpc_discard_new_call_t);
+void rxrpc_kernel_set_notifications(struct socket *sock,
+ const struct rxrpc_kernel_ops *app_ops);
struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
struct rxrpc_peer *peer,
struct key *key,
@@ -70,9 +75,9 @@ struct rxrpc_peer *rxrpc_kernel_get_call
const struct sockaddr_rxrpc *rxrpc_kernel_remote_srx(const struct rxrpc_peer *peer);
const struct sockaddr *rxrpc_kernel_remote_addr(const struct rxrpc_peer *peer);
unsigned int rxrpc_kernel_get_srtt(const struct rxrpc_peer *);
-int rxrpc_kernel_charge_accept(struct socket *, rxrpc_notify_rx_t,
- rxrpc_user_attach_call_t, unsigned long, gfp_t,
- unsigned int);
+int rxrpc_kernel_charge_accept(struct socket *sock, rxrpc_notify_rx_t notify_rx,
+ unsigned long user_call_ID, gfp_t gfp,
+ unsigned int debug_id);
void rxrpc_kernel_set_tx_length(struct socket *, struct rxrpc_call *, s64);
bool rxrpc_kernel_check_life(const struct socket *, const struct rxrpc_call *);
u32 rxrpc_kernel_get_epoch(struct socket *, struct rxrpc_call *);
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -464,24 +464,20 @@ u32 rxrpc_kernel_get_epoch(struct socket
EXPORT_SYMBOL(rxrpc_kernel_get_epoch);
/**
- * rxrpc_kernel_new_call_notification - Get notifications of new calls
- * @sock: The socket to intercept received messages on
- * @notify_new_call: Function to be called when new calls appear
- * @discard_new_call: Function to discard preallocated calls
+ * rxrpc_kernel_set_notifications - Set table of callback operations
+ * @sock: The socket to install table upon
+ * @app_ops: Callback operation table to set
*
- * Allow a kernel service to be given notifications about new calls.
+ * Allow a kernel service to set a table of event notifications on a socket.
*/
-void rxrpc_kernel_new_call_notification(
- struct socket *sock,
- rxrpc_notify_new_call_t notify_new_call,
- rxrpc_discard_new_call_t discard_new_call)
+void rxrpc_kernel_set_notifications(struct socket *sock,
+ const struct rxrpc_kernel_ops *app_ops)
{
struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
- rx->notify_new_call = notify_new_call;
- rx->discard_new_call = discard_new_call;
+ rx->app_ops = app_ops;
}
-EXPORT_SYMBOL(rxrpc_kernel_new_call_notification);
+EXPORT_SYMBOL(rxrpc_kernel_set_notifications);
/**
* rxrpc_kernel_set_max_life - Set maximum lifespan on a call
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -142,8 +142,7 @@ struct rxrpc_backlog {
struct rxrpc_sock {
/* WARNING: sk has to be the first member */
struct sock sk;
- rxrpc_notify_new_call_t notify_new_call; /* Func to notify of new call */
- rxrpc_discard_new_call_t discard_new_call; /* Func to discard a new call */
+ const struct rxrpc_kernel_ops *app_ops; /* Table of kernel app notification funcs */
struct rxrpc_local *local; /* local endpoint */
struct rxrpc_backlog *backlog; /* Preallocation for services */
spinlock_t incoming_lock; /* Incoming call vs service shutdown lock */
--- a/net/rxrpc/call_accept.c
+++ b/net/rxrpc/call_accept.c
@@ -34,7 +34,6 @@ static void rxrpc_dummy_notify(struct so
static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,
struct rxrpc_backlog *b,
rxrpc_notify_rx_t notify_rx,
- rxrpc_user_attach_call_t user_attach_call,
unsigned long user_call_ID, gfp_t gfp,
unsigned int debug_id)
{
@@ -123,9 +122,10 @@ static int rxrpc_service_prealloc_one(st
call->user_call_ID = user_call_ID;
call->notify_rx = notify_rx;
- if (user_attach_call) {
+ if (rx->app_ops &&
+ rx->app_ops->user_attach_call) {
rxrpc_get_call(call, rxrpc_call_get_kernel_service);
- user_attach_call(call, user_call_ID);
+ rx->app_ops->user_attach_call(call, user_call_ID);
}
rxrpc_get_call(call, rxrpc_call_get_userid);
@@ -221,9 +221,10 @@ void rxrpc_discard_prealloc(struct rxrpc
struct rxrpc_call *call = b->call_backlog[tail];
rxrpc_see_call(call, rxrpc_call_see_discard);
rcu_assign_pointer(call->socket, rx);
- if (rx->discard_new_call) {
+ if (rx->app_ops &&
+ rx->app_ops->discard_new_call) {
_debug("discard %lx", call->user_call_ID);
- rx->discard_new_call(call, call->user_call_ID);
+ rx->app_ops->discard_new_call(call, call->user_call_ID);
if (call->notify_rx)
call->notify_rx = rxrpc_dummy_notify;
rxrpc_put_call(call, rxrpc_call_put_kernel);
@@ -392,8 +393,9 @@ bool rxrpc_new_incoming_call(struct rxrp
rxrpc_incoming_call(rx, call, skb);
conn = call->conn;
- if (rx->notify_new_call)
- rx->notify_new_call(&rx->sk, call, call->user_call_ID);
+ if (rx->app_ops &&
+ rx->app_ops->notify_new_call)
+ rx->app_ops->notify_new_call(&rx->sk, call, call->user_call_ID);
spin_lock(&conn->state_lock);
if (conn->state == RXRPC_CONN_SERVICE_UNSECURED) {
@@ -445,8 +447,7 @@ int rxrpc_user_charge_accept(struct rxrp
if (rx->sk.sk_state == RXRPC_CLOSE)
return -ESHUTDOWN;
- return rxrpc_service_prealloc_one(rx, b, NULL, NULL, user_call_ID,
- GFP_KERNEL,
+ return rxrpc_service_prealloc_one(rx, b, NULL, user_call_ID, GFP_KERNEL,
atomic_inc_return(&rxrpc_debug_id));
}
@@ -454,20 +455,18 @@ int rxrpc_user_charge_accept(struct rxrp
* rxrpc_kernel_charge_accept - Charge up socket with preallocated calls
* @sock: The socket on which to preallocate
* @notify_rx: Event notification function for the call
- * @user_attach_call: Func to attach call to user_call_ID
* @user_call_ID: The tag to attach to the preallocated call
* @gfp: The allocation conditions.
* @debug_id: The tracing debug ID.
*
- * Charge up the socket with preallocated calls, each with a user ID. A
- * function should be provided to effect the attachment from the user's side.
- * The user is given a ref to hold on the call.
+ * Charge up the socket with preallocated calls, each with a user ID. The
+ * ->user_attach_call() callback function should be provided to effect the
+ * attachment from the user's side. The user is given a ref to hold on the
+ * call.
*
* Note that the call may be come connected before this function returns.
*/
-int rxrpc_kernel_charge_accept(struct socket *sock,
- rxrpc_notify_rx_t notify_rx,
- rxrpc_user_attach_call_t user_attach_call,
+int rxrpc_kernel_charge_accept(struct socket *sock, rxrpc_notify_rx_t notify_rx,
unsigned long user_call_ID, gfp_t gfp,
unsigned int debug_id)
{
@@ -477,8 +476,7 @@ int rxrpc_kernel_charge_accept(struct so
if (sock->sk->sk_state == RXRPC_CLOSE)
return -ESHUTDOWN;
- return rxrpc_service_prealloc_one(rx, b, notify_rx,
- user_attach_call, user_call_ID,
+ return rxrpc_service_prealloc_one(rx, b, notify_rx, user_call_ID,
gfp, debug_id);
}
EXPORT_SYMBOL(rxrpc_kernel_charge_accept);
--- a/net/rxrpc/rxperf.c
+++ b/net/rxrpc/rxperf.c
@@ -136,6 +136,12 @@ static void rxperf_notify_end_reply_tx(s
RXPERF_CALL_SV_AWAIT_ACK);
}
+static const struct rxrpc_kernel_ops rxperf_rxrpc_callback_ops = {
+ .notify_new_call = rxperf_rx_new_call,
+ .discard_new_call = rxperf_rx_discard_new_call,
+ .user_attach_call = rxperf_rx_attach,
+};
+
/*
* Charge the incoming call preallocation.
*/
@@ -161,7 +167,6 @@ static void rxperf_charge_preallocation(
if (rxrpc_kernel_charge_accept(rxperf_socket,
rxperf_notify_rx,
- rxperf_rx_attach,
(unsigned long)call,
GFP_KERNEL,
call->debug_id) < 0)
@@ -209,8 +214,7 @@ static int rxperf_open_socket(void)
if (ret < 0)
goto error_2;
- rxrpc_kernel_new_call_notification(socket, rxperf_rx_new_call,
- rxperf_rx_discard_new_call);
+ rxrpc_kernel_set_notifications(socket, &rxperf_rxrpc_callback_ops);
ret = kernel_listen(socket, INT_MAX);
if (ret < 0)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 478/602] rxrpc: serialize kernel accept preallocation with socket teardown
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (476 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 477/602] rxrpc: Pull out certain app callback funcs into an ops table Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 479/602] xfs: factor out xfs_attr3_leaf_init Greg Kroah-Hartman
` (127 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yuan Tan, Yifan Wu, Juefei Pu,
Xin Liu, Li Daming, Ren Wei, David Howells, Marc Dionne,
Jeffrey Altman, Simon Horman, linux-afs, stable, Jakub Kicinski,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li Daming <d4n.for.sec@gmail.com>
[ Upstream commit dc175389b18c29a5303ee83169ec653adfae3e17 ]
rxrpc_kernel_charge_accept() reads rx->backlog without any
socket/backlog synchronization and passes that raw pointer into
rxrpc_service_prealloc_one(). A concurrent rxrpc_discard_prealloc()
sets rx->backlog = NULL and frees the backlog rings, so a kernel
preallocation worker can keep using a freed struct rxrpc_backlog
while updating *_backlog_head/tail and array slots.
Serialize the state check and backlog lookup with the socket lock,
and reject kernel preallocation once teardown has disabled
listening or discarded the service backlog.
Fixes: 00e907127e6f ("rxrpc: Preallocate peers, conns and calls for incoming service requests")
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Signed-off-by: Li Daming <d4n.for.sec@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Jeffrey Altman <jaltman@auristor.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: stable@kernel.org
Link: https://patch.msgid.link/20260609140911.838677-6-dhowells@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/rxrpc/call_accept.c | 25 +++++++++++++++++++------
1 file changed, 19 insertions(+), 6 deletions(-)
--- a/net/rxrpc/call_accept.c
+++ b/net/rxrpc/call_accept.c
@@ -470,13 +470,26 @@ int rxrpc_kernel_charge_accept(struct so
unsigned long user_call_ID, gfp_t gfp,
unsigned int debug_id)
{
- struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
- struct rxrpc_backlog *b = rx->backlog;
+ struct rxrpc_backlog *b;
+ struct rxrpc_sock *rx;
+ struct sock *sk;
+ int ret;
- if (sock->sk->sk_state == RXRPC_CLOSE)
- return -ESHUTDOWN;
+ sk = sock->sk;
+ rx = rxrpc_sk(sk);
- return rxrpc_service_prealloc_one(rx, b, notify_rx, user_call_ID,
- gfp, debug_id);
+ lock_sock(sk);
+ if (sk->sk_state != RXRPC_SERVER_LISTENING || !rx->backlog) {
+ ret = -ESHUTDOWN;
+ goto out;
+ }
+
+ b = rx->backlog;
+ ret = rxrpc_service_prealloc_one(rx, b, notify_rx, user_call_ID,
+ gfp, debug_id);
+
+out:
+ release_sock(sk);
+ return ret;
}
EXPORT_SYMBOL(rxrpc_kernel_charge_accept);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 479/602] xfs: factor out xfs_attr3_leaf_init
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (477 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 478/602] rxrpc: serialize kernel accept preallocation with socket teardown Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 480/602] xfs: dont replace the wrong part of the cow fork Greg Kroah-Hartman
` (126 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Darrick J. Wong, Long Li,
Carlos Maiolino, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Long Li <leo.lilong@huawei.com>
[ Upstream commit e65bb55d7f8c2041c8fdb73cd29b0b4cad4ed847 ]
Factor out wrapper xfs_attr3_leaf_init function, which exported for
external use.
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Long Li <leo.lilong@huawei.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
Stable-dep-of: a1caeeadbf57 ("xfs: don't replace the wrong part of the cow fork")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/xfs/libxfs/xfs_attr_leaf.c | 22 ++++++++++++++++++++++
fs/xfs/libxfs/xfs_attr_leaf.h | 3 +++
2 files changed, 25 insertions(+)
--- a/fs/xfs/libxfs/xfs_attr_leaf.c
+++ b/fs/xfs/libxfs/xfs_attr_leaf.c
@@ -1330,6 +1330,28 @@ xfs_attr3_leaf_create(
}
/*
+ * Reinitialize an existing attr fork block as an empty leaf, and attach
+ * the buffer to tp.
+ */
+int
+xfs_attr3_leaf_init(
+ struct xfs_trans *tp,
+ struct xfs_inode *dp,
+ xfs_dablk_t blkno)
+{
+ struct xfs_buf *bp = NULL;
+ struct xfs_da_args args = {
+ .trans = tp,
+ .dp = dp,
+ .owner = dp->i_ino,
+ .geo = dp->i_mount->m_attr_geo,
+ };
+
+ ASSERT(tp != NULL);
+
+ return xfs_attr3_leaf_create(&args, blkno, &bp);
+}
+/*
* Split the leaf node, rebalance, then add the new entry.
*
* Returns 0 if the entry was added, 1 if a further split is needed or a
--- a/fs/xfs/libxfs/xfs_attr_leaf.h
+++ b/fs/xfs/libxfs/xfs_attr_leaf.h
@@ -86,6 +86,9 @@ int xfs_attr3_leaf_list_int(struct xfs_b
/*
* Routines used for shrinking the Btree.
*/
+
+int xfs_attr3_leaf_init(struct xfs_trans *tp, struct xfs_inode *dp,
+ xfs_dablk_t blkno);
int xfs_attr3_leaf_toosmall(struct xfs_da_state *state, int *retval);
void xfs_attr3_leaf_unbalance(struct xfs_da_state *state,
struct xfs_da_state_blk *drop_blk,
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 480/602] xfs: dont replace the wrong part of the cow fork
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (478 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 479/602] xfs: factor out xfs_attr3_leaf_init Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 481/602] fbcon: Rename struct fbcon_ops to struct fbcon_par Greg Kroah-Hartman
` (125 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Darrick J. Wong, Christoph Hellwig,
Carlos Maiolino, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Darrick J. Wong" <djwong@kernel.org>
[ Upstream commit a1caeeadbf57ff86dfc3454398c46de86056a74e ]
LOLLM points out that xfs_iext_lookup_extent can return a @got where
got->br_startoff < startoff. In this case, xrep_cow_replace_range
replaces the entire mapping instead of just the part that had been
marked bad in the bitmap, but advances the bitmap cursor in
xrep_cow_replace by the amount replaced. As a result, we fail to
replace the end of the bad range, and replace part of the good range.
Fix this by rewriting the replace method to handle replacing the middle
of a cow fork mapping. This we do by returning both the current mapping
as @got, and the subset of the mapping that we want to replace as @rep,
using @rep to store the results of the new allocation, and comparing
@rep to @got to figure out the exact transformations needed.
Cc: stable@vger.kernel.org # v6.8
Fixes: dbbdbd0086320a ("xfs: repair problems in CoW forks")
Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Assisted-by: LOLLM # finding obvious bugs
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/xfs/scrub/cow_repair.c | 182 +++++++++++++++++++++++++++++-----------------
fs/xfs/scrub/trace.h | 28 ++++---
2 files changed, 135 insertions(+), 75 deletions(-)
--- a/fs/xfs/scrub/cow_repair.c
+++ b/fs/xfs/scrub/cow_repair.c
@@ -73,12 +73,6 @@ struct xrep_cow {
unsigned int next_bno;
};
-/* CoW staging extent. */
-struct xrep_cow_extent {
- xfs_fsblock_t fsbno;
- xfs_extlen_t len;
-};
-
/*
* Mark the part of the file range that corresponds to the given physical
* space. Caller must ensure that the physical range is within xc->irec.
@@ -315,22 +309,21 @@ out_pag:
STATIC int
xrep_cow_alloc(
struct xfs_scrub *sc,
- xfs_extlen_t maxlen,
- struct xrep_cow_extent *repl)
+ struct xfs_bmbt_irec *del)
{
struct xfs_alloc_arg args = {
.tp = sc->tp,
.mp = sc->mp,
.oinfo = XFS_RMAP_OINFO_SKIP_UPDATE,
.minlen = 1,
- .maxlen = maxlen,
+ .maxlen = del->br_blockcount,
.prod = 1,
.resv = XFS_AG_RESV_NONE,
.datatype = XFS_ALLOC_USERDATA,
};
int error;
- error = xfs_trans_reserve_more(sc->tp, maxlen, 0);
+ error = xfs_trans_reserve_more(sc->tp, del->br_blockcount, 0);
if (error)
return error;
@@ -343,8 +336,8 @@ xrep_cow_alloc(
xfs_refcount_alloc_cow_extent(sc->tp, args.fsbno, args.len);
- repl->fsbno = args.fsbno;
- repl->len = args.len;
+ del->br_startblock = args.fsbno;
+ del->br_blockcount = args.len;
return 0;
}
@@ -358,19 +351,19 @@ static inline int
xrep_cow_find_mapping(
struct xrep_cow *xc,
struct xfs_iext_cursor *icur,
- xfs_fileoff_t startoff,
- struct xfs_bmbt_irec *got)
+ xfs_fileoff_t badoff,
+ xfs_extlen_t badlen,
+ struct xfs_bmbt_irec *got,
+ struct xfs_bmbt_irec *rep)
{
struct xfs_inode *ip = xc->sc->ip;
struct xfs_ifork *ifp = xfs_ifork_ptr(ip, XFS_COW_FORK);
- if (!xfs_iext_lookup_extent(ip, ifp, startoff, icur, got))
- goto bad;
-
- if (got->br_startoff > startoff)
+ if (!xfs_iext_lookup_extent(ip, ifp, badoff, icur, got))
goto bad;
+ memcpy(rep, got, sizeof(*rep));
- if (got->br_blockcount == 0)
+ if (got->br_startoff > badoff)
goto bad;
if (isnullstartblock(got->br_startblock))
@@ -379,6 +372,24 @@ xrep_cow_find_mapping(
if (xfs_bmap_is_written_extent(got))
goto bad;
+ if (got->br_startoff < badoff) {
+ const int64_t delta = badoff - got->br_startoff;
+
+ rep->br_blockcount -= delta;
+ rep->br_startoff += delta;
+ rep->br_startblock += delta;
+ }
+
+ if (got->br_startoff + got->br_blockcount > badoff + badlen) {
+ const int64_t delta = (got->br_startoff + got->br_blockcount) -
+ (badoff + badlen);
+
+ rep->br_blockcount -= delta;
+ }
+
+ if (got->br_blockcount == 0)
+ goto bad;
+
return 0;
bad:
ASSERT(0);
@@ -389,46 +400,92 @@ bad:
#define REPLACE_RIGHT_SIDE (1U << 1)
/*
- * Given a CoW fork mapping @got and a replacement mapping @repl, remap the
- * beginning of @got with the space described by @rep.
+ * Given a CoW fork mapping @got and a replacement mapping @rep, map the space
+ * described by @rep into the cow fork, pushing aside @got as necessary. @icur
+ * must point to iext tree leaf containing @got.
*/
static inline void
xrep_cow_replace_mapping(
- struct xfs_inode *ip,
- struct xfs_iext_cursor *icur,
- const struct xfs_bmbt_irec *got,
- const struct xrep_cow_extent *repl)
+ struct xfs_inode *ip,
+ struct xfs_iext_cursor *icur,
+ struct xfs_bmbt_irec *got,
+ struct xfs_bmbt_irec *rep)
{
- struct xfs_bmbt_irec new = *got; /* struct copy */
+ struct xfs_ifork *ifp = xfs_ifork_ptr(ip, XFS_COW_FORK);
+ xfs_fileoff_t rep_endoff =
+ rep->br_startoff + rep->br_blockcount;
+ xfs_fileoff_t got_endoff =
+ got->br_startoff + got->br_blockcount;
+ uint32_t state = BMAP_COWFORK;
- ASSERT(repl->len > 0);
+ ASSERT(rep->br_blockcount > 0);
ASSERT(!isnullstartblock(got->br_startblock));
+ ASSERT(got->br_startoff <= rep->br_startoff);
+ ASSERT(got_endoff >= rep_endoff);
- trace_xrep_cow_replace_mapping(ip, got, repl->fsbno, repl->len);
+ trace_xrep_cow_replace_mapping(ip, got, rep);
- if (got->br_blockcount == repl->len) {
+ if (got->br_startoff == rep->br_startoff)
+ state |= BMAP_LEFT_FILLING;
+ if (got_endoff == rep_endoff)
+ state |= BMAP_RIGHT_FILLING;
+
+ switch (state & (BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING)) {
+ case BMAP_LEFT_FILLING | BMAP_RIGHT_FILLING:
/*
- * The new extent is a complete replacement for the existing
- * extent. Update the COW fork record.
+ * Replacement matches the whole mapping, update the record.
*/
- new.br_startblock = repl->fsbno;
- xfs_iext_update_extent(ip, BMAP_COWFORK, icur, &new);
- return;
- }
+ xfs_iext_update_extent(ip, state, icur, rep);
+ break;
+ case BMAP_LEFT_FILLING:
+ /*
+ * Replace the first part of the mapping: Update the cursor
+ * position with the new mapping, then add a record with the
+ * tail of the old mapping.
+ */
+ got->br_startoff = rep_endoff;
+ got->br_blockcount -= rep->br_blockcount;
+ got->br_startblock += rep->br_blockcount;
+
+ xfs_iext_update_extent(ip, state, icur, rep);
+ xfs_iext_next(ifp, icur);
+ xfs_iext_insert(ip, icur, got, state);
+ break;
+ case BMAP_RIGHT_FILLING:
+ /*
+ * Replacing the last part of the mapping. Shorten the current
+ * mapping then add a record with the new mapping.
+ */
+ got->br_blockcount -= rep->br_blockcount;
- /*
- * The new extent can replace the beginning of the COW fork record.
- * Move the left side of @got upwards, then insert the new record.
- */
- new.br_startoff += repl->len;
- new.br_startblock += repl->len;
- new.br_blockcount -= repl->len;
- xfs_iext_update_extent(ip, BMAP_COWFORK, icur, &new);
-
- new.br_startoff = got->br_startoff;
- new.br_startblock = repl->fsbno;
- new.br_blockcount = repl->len;
- xfs_iext_insert(ip, icur, &new, BMAP_COWFORK);
+ xfs_iext_update_extent(ip, state, icur, got);
+ xfs_iext_next(ifp, icur);
+ xfs_iext_insert(ip, icur, rep, state);
+ break;
+ case 0:
+ /*
+ * Replacing the middle of the extent. Shorten the current
+ * mapping, add a new record with the new mapping, and add a
+ * second new record with the tail of the old mapping.
+ */
+ got->br_blockcount = rep->br_startoff - got->br_startoff;
+
+ struct xfs_bmbt_irec new = {
+ .br_startoff = rep_endoff,
+ .br_blockcount = got_endoff - rep_endoff,
+ .br_state = got->br_state,
+ .br_startblock = got->br_startblock +
+ rep->br_blockcount +
+ got->br_blockcount,
+ };
+
+ xfs_iext_update_extent(ip, state, icur, got);
+ xfs_iext_next(ifp, icur);
+ xfs_iext_insert(ip, icur, rep, state);
+ xfs_iext_next(ifp, icur);
+ xfs_iext_insert(ip, icur, &new, state);
+ break;
+ }
}
/*
@@ -442,30 +499,27 @@ xrep_cow_replace_range(
xfs_extlen_t *blockcount)
{
struct xfs_iext_cursor icur;
- struct xrep_cow_extent repl;
- struct xfs_bmbt_irec got;
+ struct xfs_bmbt_irec got, rep;
struct xfs_scrub *sc = xc->sc;
- xfs_fileoff_t nextoff;
- xfs_extlen_t alloc_len;
+ xfs_fsblock_t old_fsbno;
int error;
/*
- * Put the existing CoW fork mapping in @got. If @got ends before
- * @rep, truncate @rep so we only replace one extent mapping at a time.
+ * Put the existing CoW fork mapping in @got, and put in @rep the
+ * contents of @got trimmed to @startoff/@blockcount. We only want
+ * to replace the bad region, and only one mapping at a time.
*/
- error = xrep_cow_find_mapping(xc, &icur, startoff, &got);
+ error = xrep_cow_find_mapping(xc, &icur, startoff, *blockcount, &got,
+ &rep);
if (error)
return error;
- nextoff = min(startoff + *blockcount,
- got.br_startoff + got.br_blockcount);
+ old_fsbno = rep.br_startblock;
/*
* Allocate a replacement extent. If we don't fill all the blocks,
* shorten the quantity that will be deleted in this step.
*/
- alloc_len = min_t(xfs_fileoff_t, XFS_MAX_BMBT_EXTLEN,
- nextoff - startoff);
- error = xrep_cow_alloc(sc, alloc_len, &repl);
+ error = xrep_cow_alloc(sc, &rep);
if (error)
return error;
@@ -473,7 +527,7 @@ xrep_cow_replace_range(
* Replace the old mapping with the new one, and commit the metadata
* changes made so far.
*/
- xrep_cow_replace_mapping(sc->ip, &icur, &got, &repl);
+ xrep_cow_replace_mapping(sc->ip, &icur, &got, &rep);
xfs_inode_set_cowblocks_tag(sc->ip);
error = xfs_defer_finish(&sc->tp);
@@ -481,12 +535,12 @@ xrep_cow_replace_range(
return error;
/* Note the old CoW staging extents; we'll reap them all later. */
- error = xfsb_bitmap_set(&xc->old_cowfork_fsblocks, got.br_startblock,
- repl.len);
+ error = xfsb_bitmap_set(&xc->old_cowfork_fsblocks, old_fsbno,
+ rep.br_blockcount);
if (error)
return error;
- *blockcount = repl.len;
+ *blockcount = rep.br_blockcount;
return 0;
}
--- a/fs/xfs/scrub/trace.h
+++ b/fs/xfs/scrub/trace.h
@@ -2553,9 +2553,9 @@ TRACE_EVENT(xrep_cow_mark_file_range,
);
TRACE_EVENT(xrep_cow_replace_mapping,
- TP_PROTO(struct xfs_inode *ip, const struct xfs_bmbt_irec *irec,
- xfs_fsblock_t new_startblock, xfs_extlen_t new_blockcount),
- TP_ARGS(ip, irec, new_startblock, new_blockcount),
+ TP_PROTO(struct xfs_inode *ip, const struct xfs_bmbt_irec *got,
+ const struct xfs_bmbt_irec *rep),
+ TP_ARGS(ip, got, rep),
TP_STRUCT__entry(
__field(dev_t, dev)
__field(xfs_ino_t, ino)
@@ -2563,28 +2563,34 @@ TRACE_EVENT(xrep_cow_replace_mapping,
__field(xfs_fileoff_t, startoff)
__field(xfs_filblks_t, blockcount)
__field(xfs_exntst_t, state)
+ __field(xfs_fileoff_t, new_startoff)
__field(xfs_fsblock_t, new_startblock)
__field(xfs_extlen_t, new_blockcount)
+ __field(xfs_exntst_t, new_state)
),
TP_fast_assign(
__entry->dev = ip->i_mount->m_super->s_dev;
__entry->ino = ip->i_ino;
- __entry->startoff = irec->br_startoff;
- __entry->startblock = irec->br_startblock;
- __entry->blockcount = irec->br_blockcount;
- __entry->state = irec->br_state;
- __entry->new_startblock = new_startblock;
- __entry->new_blockcount = new_blockcount;
+ __entry->startoff = got->br_startoff;
+ __entry->startblock = got->br_startblock;
+ __entry->blockcount = got->br_blockcount;
+ __entry->state = got->br_state;
+ __entry->new_startoff = rep->br_startoff;
+ __entry->new_startblock = rep->br_startblock;
+ __entry->new_blockcount = rep->br_blockcount;
+ __entry->new_state = rep->br_state;
),
- TP_printk("dev %d:%d ino 0x%llx startoff 0x%llx startblock 0x%llx fsbcount 0x%llx state 0x%x new_startblock 0x%llx new_fsbcount 0x%x",
+ TP_printk("dev %d:%d ino 0x%llx startoff 0x%llx startblock 0x%llx fsbcount 0x%llx state 0x%x new_startoff 0x%llx new_startblock 0x%llx new_fsbcount 0x%x new_state 0x%x",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino,
__entry->startoff,
__entry->startblock,
__entry->blockcount,
__entry->state,
+ __entry->new_startoff,
__entry->new_startblock,
- __entry->new_blockcount)
+ __entry->new_blockcount,
+ __entry->new_state)
);
TRACE_EVENT(xrep_cow_free_staging,
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 481/602] fbcon: Rename struct fbcon_ops to struct fbcon_par
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (479 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 480/602] xfs: dont replace the wrong part of the cow fork Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 482/602] fbcon: Use correct type for vc_resize() return value Greg Kroah-Hartman
` (124 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Thomas Zimmermann, Sam Ravnborg,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Zimmermann <tzimmermann@suse.de>
[ Upstream commit a6adbbc4c32a016146e117b1e9e5242724a75e10 ]
The type struct fbcon_ops contains fbcon state and callbacks. As the
callbacks will be removed from struct fbcon_ops, rename the data type
to struct fbcon_par. Also rename the variables from ops to par.
The _par postfix ("private access registers") is used throughout the
fbdev subsystem for per-driver state. The fbcon pointer within struct
fb_info is also named fbcon_par. Hence, the new naming fits existing
practice.
v2:
- rename struct fbcon_ops to struct fbcon_par
- fix build for CONFIG_FB_TILEBITTING=n (kernel test robot)
- fix indention
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
Link: https://lore.kernel.org/r/20250909124616.143365-3-tzimmermann@suse.de
Stable-dep-of: 84202754fb17 ("fbcon: Use correct type for vc_resize() return value")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/video/fbdev/core/bitblit.c | 120 ++++-----
drivers/video/fbdev/core/fbcon.c | 417 +++++++++++++++-----------------
drivers/video/fbdev/core/fbcon.h | 6
drivers/video/fbdev/core/fbcon_ccw.c | 146 +++++------
drivers/video/fbdev/core/fbcon_cw.c | 146 +++++------
drivers/video/fbdev/core/fbcon_rotate.c | 44 +--
drivers/video/fbdev/core/fbcon_rotate.h | 6
drivers/video/fbdev/core/fbcon_ud.c | 162 ++++++------
drivers/video/fbdev/core/softcursor.c | 20 -
drivers/video/fbdev/core/tileblit.c | 28 +-
10 files changed, 543 insertions(+), 552 deletions(-)
--- a/drivers/video/fbdev/core/bitblit.c
+++ b/drivers/video/fbdev/core/bitblit.c
@@ -261,10 +261,10 @@ static void bit_cursor(struct vc_data *v
int fg, int bg)
{
struct fb_cursor cursor;
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
int w = DIV_ROUND_UP(vc->vc_font.width, 8), c;
- int y = real_y(ops->p, vc->state.y);
+ int y = real_y(par->p, vc->state.y);
int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
int err = 1;
char *src;
@@ -278,10 +278,10 @@ static void bit_cursor(struct vc_data *v
attribute = get_attribute(info, c);
src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));
- if (ops->cursor_state.image.data != src ||
- ops->cursor_reset) {
- ops->cursor_state.image.data = src;
- cursor.set |= FB_CUR_SETIMAGE;
+ if (par->cursor_state.image.data != src ||
+ par->cursor_reset) {
+ par->cursor_state.image.data = src;
+ cursor.set |= FB_CUR_SETIMAGE;
}
if (attribute) {
@@ -290,46 +290,46 @@ static void bit_cursor(struct vc_data *v
dst = kmalloc_array(w, vc->vc_font.height, GFP_ATOMIC);
if (!dst)
return;
- kfree(ops->cursor_data);
- ops->cursor_data = dst;
+ kfree(par->cursor_data);
+ par->cursor_data = dst;
update_attr(dst, src, attribute, vc);
src = dst;
}
- if (ops->cursor_state.image.fg_color != fg ||
- ops->cursor_state.image.bg_color != bg ||
- ops->cursor_reset) {
- ops->cursor_state.image.fg_color = fg;
- ops->cursor_state.image.bg_color = bg;
+ if (par->cursor_state.image.fg_color != fg ||
+ par->cursor_state.image.bg_color != bg ||
+ par->cursor_reset) {
+ par->cursor_state.image.fg_color = fg;
+ par->cursor_state.image.bg_color = bg;
cursor.set |= FB_CUR_SETCMAP;
}
- if ((ops->cursor_state.image.dx != (vc->vc_font.width * vc->state.x)) ||
- (ops->cursor_state.image.dy != (vc->vc_font.height * y)) ||
- ops->cursor_reset) {
- ops->cursor_state.image.dx = vc->vc_font.width * vc->state.x;
- ops->cursor_state.image.dy = vc->vc_font.height * y;
+ if ((par->cursor_state.image.dx != (vc->vc_font.width * vc->state.x)) ||
+ (par->cursor_state.image.dy != (vc->vc_font.height * y)) ||
+ par->cursor_reset) {
+ par->cursor_state.image.dx = vc->vc_font.width * vc->state.x;
+ par->cursor_state.image.dy = vc->vc_font.height * y;
cursor.set |= FB_CUR_SETPOS;
}
- if (ops->cursor_state.image.height != vc->vc_font.height ||
- ops->cursor_state.image.width != vc->vc_font.width ||
- ops->cursor_reset) {
- ops->cursor_state.image.height = vc->vc_font.height;
- ops->cursor_state.image.width = vc->vc_font.width;
+ if (par->cursor_state.image.height != vc->vc_font.height ||
+ par->cursor_state.image.width != vc->vc_font.width ||
+ par->cursor_reset) {
+ par->cursor_state.image.height = vc->vc_font.height;
+ par->cursor_state.image.width = vc->vc_font.width;
cursor.set |= FB_CUR_SETSIZE;
}
- if (ops->cursor_state.hot.x || ops->cursor_state.hot.y ||
- ops->cursor_reset) {
- ops->cursor_state.hot.x = cursor.hot.y = 0;
+ if (par->cursor_state.hot.x || par->cursor_state.hot.y ||
+ par->cursor_reset) {
+ par->cursor_state.hot.x = cursor.hot.y = 0;
cursor.set |= FB_CUR_SETHOT;
}
if (cursor.set & FB_CUR_SETSIZE ||
- vc->vc_cursor_type != ops->p->cursor_shape ||
- ops->cursor_state.mask == NULL ||
- ops->cursor_reset) {
+ vc->vc_cursor_type != par->p->cursor_shape ||
+ par->cursor_state.mask == NULL ||
+ par->cursor_reset) {
char *mask = kmalloc_array(w, vc->vc_font.height, GFP_ATOMIC);
int cur_height, size, i = 0;
u8 msk = 0xff;
@@ -337,13 +337,13 @@ static void bit_cursor(struct vc_data *v
if (!mask)
return;
- kfree(ops->cursor_state.mask);
- ops->cursor_state.mask = mask;
+ kfree(par->cursor_state.mask);
+ par->cursor_state.mask = mask;
- ops->p->cursor_shape = vc->vc_cursor_type;
+ par->p->cursor_shape = vc->vc_cursor_type;
cursor.set |= FB_CUR_SETSHAPE;
- switch (CUR_SIZE(ops->p->cursor_shape)) {
+ switch (CUR_SIZE(par->p->cursor_shape)) {
case CUR_NONE:
cur_height = 0;
break;
@@ -372,19 +372,19 @@ static void bit_cursor(struct vc_data *v
mask[i++] = msk;
}
- ops->cursor_state.enable = enable && !use_sw;
+ par->cursor_state.enable = enable && !use_sw;
cursor.image.data = src;
- cursor.image.fg_color = ops->cursor_state.image.fg_color;
- cursor.image.bg_color = ops->cursor_state.image.bg_color;
- cursor.image.dx = ops->cursor_state.image.dx;
- cursor.image.dy = ops->cursor_state.image.dy;
- cursor.image.height = ops->cursor_state.image.height;
- cursor.image.width = ops->cursor_state.image.width;
- cursor.hot.x = ops->cursor_state.hot.x;
- cursor.hot.y = ops->cursor_state.hot.y;
- cursor.mask = ops->cursor_state.mask;
- cursor.enable = ops->cursor_state.enable;
+ cursor.image.fg_color = par->cursor_state.image.fg_color;
+ cursor.image.bg_color = par->cursor_state.image.bg_color;
+ cursor.image.dx = par->cursor_state.image.dx;
+ cursor.image.dy = par->cursor_state.image.dy;
+ cursor.image.height = par->cursor_state.image.height;
+ cursor.image.width = par->cursor_state.image.width;
+ cursor.hot.x = par->cursor_state.hot.x;
+ cursor.hot.y = par->cursor_state.hot.y;
+ cursor.mask = par->cursor_state.mask;
+ cursor.enable = par->cursor_state.enable;
cursor.image.depth = 1;
cursor.rop = ROP_XOR;
@@ -394,31 +394,31 @@ static void bit_cursor(struct vc_data *v
if (err)
soft_cursor(info, &cursor);
- ops->cursor_reset = 0;
+ par->cursor_reset = 0;
}
static int bit_update_start(struct fb_info *info)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
int err;
- err = fb_pan_display(info, &ops->var);
- ops->var.xoffset = info->var.xoffset;
- ops->var.yoffset = info->var.yoffset;
- ops->var.vmode = info->var.vmode;
+ err = fb_pan_display(info, &par->var);
+ par->var.xoffset = info->var.xoffset;
+ par->var.yoffset = info->var.yoffset;
+ par->var.vmode = info->var.vmode;
return err;
}
-void fbcon_set_bitops(struct fbcon_ops *ops)
+void fbcon_set_bitops(struct fbcon_par *par)
{
- ops->bmove = bit_bmove;
- ops->clear = bit_clear;
- ops->putcs = bit_putcs;
- ops->clear_margins = bit_clear_margins;
- ops->cursor = bit_cursor;
- ops->update_start = bit_update_start;
- ops->rotate_font = NULL;
+ par->bmove = bit_bmove;
+ par->clear = bit_clear;
+ par->putcs = bit_putcs;
+ par->clear_margins = bit_clear_margins;
+ par->cursor = bit_cursor;
+ par->update_start = bit_update_start;
+ par->rotate_font = NULL;
- if (ops->rotate)
- fbcon_set_rotate(ops);
+ if (par->rotate)
+ fbcon_set_rotate(par);
}
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -200,27 +200,27 @@ static struct device *fbcon_device;
#ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION
static inline void fbcon_set_rotation(struct fb_info *info)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
if (!(info->flags & FBINFO_MISC_TILEBLITTING) &&
- ops->p->con_rotate < 4)
- ops->rotate = ops->p->con_rotate;
+ par->p->con_rotate < 4)
+ par->rotate = par->p->con_rotate;
else
- ops->rotate = 0;
+ par->rotate = 0;
}
static void fbcon_rotate(struct fb_info *info, u32 rotate)
{
- struct fbcon_ops *ops= info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
struct fb_info *fb_info;
- if (!ops || ops->currcon == -1)
+ if (!par || par->currcon == -1)
return;
- fb_info = fbcon_info_from_console(ops->currcon);
+ fb_info = fbcon_info_from_console(par->currcon);
if (info == fb_info) {
- struct fbcon_display *p = &fb_display[ops->currcon];
+ struct fbcon_display *p = &fb_display[par->currcon];
if (rotate < 4)
p->con_rotate = rotate;
@@ -233,12 +233,12 @@ static void fbcon_rotate(struct fb_info
static void fbcon_rotate_all(struct fb_info *info, u32 rotate)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
struct vc_data *vc;
struct fbcon_display *p;
int i;
- if (!ops || ops->currcon < 0 || rotate > 3)
+ if (!par || par->currcon < 0 || rotate > 3)
return;
for (i = first_fb_vc; i <= last_fb_vc; i++) {
@@ -256,9 +256,9 @@ static void fbcon_rotate_all(struct fb_i
#else
static inline void fbcon_set_rotation(struct fb_info *info)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
- ops->rotate = FB_ROTATE_UR;
+ par->rotate = FB_ROTATE_UR;
}
static void fbcon_rotate(struct fb_info *info, u32 rotate)
@@ -274,9 +274,9 @@ static void fbcon_rotate_all(struct fb_i
static int fbcon_get_rotate(struct fb_info *info)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
- return (ops) ? ops->rotate : 0;
+ return (par) ? par->rotate : 0;
}
static bool fbcon_skip_panic(struct fb_info *info)
@@ -293,10 +293,10 @@ static bool fbcon_skip_panic(struct fb_i
static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
return (info->state != FBINFO_STATE_RUNNING ||
- vc->vc_mode != KD_TEXT || ops->graphics || fbcon_skip_panic(info));
+ vc->vc_mode != KD_TEXT || par->graphics || fbcon_skip_panic(info));
}
static int get_color(struct vc_data *vc, struct fb_info *info,
@@ -368,7 +368,7 @@ static int get_color(struct vc_data *vc,
static void fb_flashcursor(struct work_struct *work)
{
- struct fbcon_ops *ops = container_of(work, struct fbcon_ops, cursor_work.work);
+ struct fbcon_par *par = container_of(work, struct fbcon_par, cursor_work.work);
struct fb_info *info;
struct vc_data *vc = NULL;
int c;
@@ -383,10 +383,10 @@ static void fb_flashcursor(struct work_s
return;
/* protected by console_lock */
- info = ops->info;
+ info = par->info;
- if (ops->currcon != -1)
- vc = vc_cons[ops->currcon].d;
+ if (par->currcon != -1)
+ vc = vc_cons[par->currcon].d;
if (!vc || !con_is_visible(vc) ||
fbcon_info_from_console(vc->vc_num) != info ||
@@ -396,29 +396,29 @@ static void fb_flashcursor(struct work_s
}
c = scr_readw((u16 *) vc->vc_pos);
- enable = ops->cursor_flash && !ops->cursor_state.enable;
- ops->cursor(vc, info, enable, get_color(vc, info, c, 1),
+ enable = par->cursor_flash && !par->cursor_state.enable;
+ par->cursor(vc, info, enable, get_color(vc, info, c, 1),
get_color(vc, info, c, 0));
console_unlock();
- queue_delayed_work(system_power_efficient_wq, &ops->cursor_work,
- ops->cur_blink_jiffies);
+ queue_delayed_work(system_power_efficient_wq, &par->cursor_work,
+ par->cur_blink_jiffies);
}
static void fbcon_add_cursor_work(struct fb_info *info)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
if (!fbcon_cursor_noblink)
- queue_delayed_work(system_power_efficient_wq, &ops->cursor_work,
- ops->cur_blink_jiffies);
+ queue_delayed_work(system_power_efficient_wq, &par->cursor_work,
+ par->cur_blink_jiffies);
}
static void fbcon_del_cursor_work(struct fb_info *info)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
- cancel_delayed_work_sync(&ops->cursor_work);
+ cancel_delayed_work_sync(&par->cursor_work);
}
#ifndef MODULE
@@ -578,7 +578,7 @@ static void fbcon_prepare_logo(struct vc
int cols, int rows, int new_cols, int new_rows)
{
/* Need to make room for the logo */
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
int cnt, erase = vc->vc_video_erase_char, step;
unsigned short *save = NULL, *r, *q;
int logo_height;
@@ -594,7 +594,7 @@ static void fbcon_prepare_logo(struct vc
*/
if (fb_get_color_depth(&info->var, &info->fix) == 1)
erase &= ~0x400;
- logo_height = fb_prepare_logo(info, ops->rotate);
+ logo_height = fb_prepare_logo(info, par->rotate);
logo_lines = DIV_ROUND_UP(logo_height, vc->vc_font.height);
q = (unsigned short *) (vc->vc_origin +
vc->vc_size_row * rows);
@@ -666,15 +666,15 @@ static void fbcon_prepare_logo(struct vc
#ifdef CONFIG_FB_TILEBLITTING
static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
- ops->p = &fb_display[vc->vc_num];
+ par->p = &fb_display[vc->vc_num];
if ((info->flags & FBINFO_MISC_TILEBLITTING))
fbcon_set_tileops(vc, info);
else {
fbcon_set_rotation(info);
- fbcon_set_bitops(ops);
+ fbcon_set_bitops(par);
}
}
@@ -691,12 +691,12 @@ static int fbcon_invalid_charcount(struc
#else
static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
info->flags &= ~FBINFO_MISC_TILEBLITTING;
- ops->p = &fb_display[vc->vc_num];
+ par->p = &fb_display[vc->vc_num];
fbcon_set_rotation(info);
- fbcon_set_bitops(ops);
+ fbcon_set_bitops(par);
}
static int fbcon_invalid_charcount(struct fb_info *info, unsigned charcount)
@@ -716,13 +716,13 @@ static void fbcon_release(struct fb_info
module_put(info->fbops->owner);
if (info->fbcon_par) {
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
fbcon_del_cursor_work(info);
- kfree(ops->cursor_state.mask);
- kfree(ops->cursor_data);
- kfree(ops->cursor_src);
- kfree(ops->fontbuffer);
+ kfree(par->cursor_state.mask);
+ kfree(par->cursor_data);
+ kfree(par->cursor_src);
+ kfree(par->fontbuffer);
kfree(info->fbcon_par);
info->fbcon_par = NULL;
}
@@ -730,7 +730,7 @@ static void fbcon_release(struct fb_info
static int fbcon_open(struct fb_info *info)
{
- struct fbcon_ops *ops;
+ struct fbcon_par *par;
if (!try_module_get(info->fbops->owner))
return -ENODEV;
@@ -744,16 +744,16 @@ static int fbcon_open(struct fb_info *in
}
unlock_fb_info(info);
- ops = kzalloc(sizeof(struct fbcon_ops), GFP_KERNEL);
- if (!ops) {
+ par = kzalloc(sizeof(*par), GFP_KERNEL);
+ if (!par) {
fbcon_release(info);
return -ENOMEM;
}
- INIT_DELAYED_WORK(&ops->cursor_work, fb_flashcursor);
- ops->info = info;
- info->fbcon_par = ops;
- ops->cur_blink_jiffies = HZ / 5;
+ INIT_DELAYED_WORK(&par->cursor_work, fb_flashcursor);
+ par->info = info;
+ info->fbcon_par = par;
+ par->cur_blink_jiffies = HZ / 5;
return 0;
}
@@ -800,12 +800,12 @@ static void con2fb_release_oldinfo(struc
static void con2fb_init_display(struct vc_data *vc, struct fb_info *info,
int unit, int show_logo)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
int ret;
- ops->currcon = fg_console;
+ par->currcon = fg_console;
- if (info->fbops->fb_set_par && !ops->initialized) {
+ if (info->fbops->fb_set_par && !par->initialized) {
ret = info->fbops->fb_set_par(info);
if (ret)
@@ -814,8 +814,8 @@ static void con2fb_init_display(struct v
"error code %d\n", ret);
}
- ops->initialized = true;
- ops->graphics = 0;
+ par->initialized = true;
+ par->graphics = 0;
fbcon_set_disp(info, &info->var, unit);
if (show_logo) {
@@ -952,7 +952,7 @@ static const char *fbcon_startup(void)
struct vc_data *vc = vc_cons[fg_console].d;
const struct font_desc *font = NULL;
struct fb_info *info = NULL;
- struct fbcon_ops *ops;
+ struct fbcon_par *par;
int rows, cols;
/*
@@ -972,10 +972,10 @@ static const char *fbcon_startup(void)
if (fbcon_open(info))
return NULL;
- ops = info->fbcon_par;
- ops->currcon = -1;
- ops->graphics = 1;
- ops->cur_rotate = -1;
+ par = info->fbcon_par;
+ par->currcon = -1;
+ par->graphics = 1;
+ par->cur_rotate = -1;
p->con_rotate = initial_rotation;
if (p->con_rotate == -1)
@@ -998,8 +998,8 @@ static const char *fbcon_startup(void)
vc->vc_font.charcount = font->charcount;
}
- cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
- rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
+ cols = FBCON_SWAP(par->rotate, info->var.xres, info->var.yres);
+ rows = FBCON_SWAP(par->rotate, info->var.yres, info->var.xres);
cols /= vc->vc_font.width;
rows /= vc->vc_font.height;
vc_resize(vc, cols, rows);
@@ -1017,7 +1017,7 @@ static const char *fbcon_startup(void)
static void fbcon_init(struct vc_data *vc, bool init)
{
struct fb_info *info;
- struct fbcon_ops *ops;
+ struct fbcon_par *par;
struct vc_data **default_mode = vc->vc_display_fg;
struct vc_data *svc = *default_mode;
struct fbcon_display *t, *p = &fb_display[vc->vc_num];
@@ -1092,8 +1092,8 @@ static void fbcon_init(struct vc_data *v
if (!*vc->uni_pagedict_loc)
con_copy_unimap(vc, svc);
- ops = info->fbcon_par;
- ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms);
+ par = info->fbcon_par;
+ par->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms);
p->con_rotate = initial_rotation;
if (p->con_rotate == -1)
@@ -1105,8 +1105,8 @@ static void fbcon_init(struct vc_data *v
cols = vc->vc_cols;
rows = vc->vc_rows;
- new_cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
- new_rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
+ new_cols = FBCON_SWAP(par->rotate, info->var.xres, info->var.yres);
+ new_rows = FBCON_SWAP(par->rotate, info->var.yres, info->var.xres);
new_cols /= vc->vc_font.width;
new_rows /= vc->vc_font.height;
@@ -1118,7 +1118,7 @@ static void fbcon_init(struct vc_data *v
* We need to do it in fbcon_init() to prevent screen corruption.
*/
if (con_is_visible(vc) && vc->vc_mode == KD_TEXT) {
- if (info->fbops->fb_set_par && !ops->initialized) {
+ if (info->fbops->fb_set_par && !par->initialized) {
ret = info->fbops->fb_set_par(info);
if (ret)
@@ -1127,10 +1127,10 @@ static void fbcon_init(struct vc_data *v
"error code %d\n", ret);
}
- ops->initialized = true;
+ par->initialized = true;
}
- ops->graphics = 0;
+ par->graphics = 0;
#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
if ((info->flags & FBINFO_HWACCEL_COPYAREA) &&
@@ -1154,12 +1154,12 @@ static void fbcon_init(struct vc_data *v
if (logo)
fbcon_prepare_logo(vc, info, cols, rows, new_cols, new_rows);
- if (ops->rotate_font && ops->rotate_font(info, vc)) {
- ops->rotate = FB_ROTATE_UR;
+ if (par->rotate_font && par->rotate_font(info, vc)) {
+ par->rotate = FB_ROTATE_UR;
set_blitting_type(vc, info);
}
- ops->p = &fb_display[fg_console];
+ par->p = &fb_display[fg_console];
}
static void fbcon_free_font(struct fbcon_display *p)
@@ -1197,7 +1197,7 @@ static void fbcon_deinit(struct vc_data
{
struct fbcon_display *p = &fb_display[vc->vc_num];
struct fb_info *info;
- struct fbcon_ops *ops;
+ struct fbcon_par *par;
int idx;
fbcon_free_font(p);
@@ -1212,15 +1212,15 @@ static void fbcon_deinit(struct vc_data
if (!info)
goto finished;
- ops = info->fbcon_par;
+ par = info->fbcon_par;
- if (!ops)
+ if (!par)
goto finished;
if (con_is_visible(vc))
fbcon_del_cursor_work(info);
- ops->initialized = false;
+ par->initialized = false;
finished:
fbcon_free_font(p);
@@ -1267,7 +1267,7 @@ static void __fbcon_clear(struct vc_data
unsigned int height, unsigned int width)
{
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
int fg, bg;
struct fbcon_display *p = &fb_display[vc->vc_num];
u_int y_break;
@@ -1282,7 +1282,7 @@ static void __fbcon_clear(struct vc_data
vc->vc_top = 0;
/*
* If the font dimensions are not an integral of the display
- * dimensions then the ops->clear below won't end up clearing
+ * dimensions then the par->clear below won't end up clearing
* the margins. Call clear_margins here in case the logo
* bitmap stretched into the margin area.
*/
@@ -1296,11 +1296,10 @@ static void __fbcon_clear(struct vc_data
y_break = p->vrows - p->yscroll;
if (sy < y_break && sy + height - 1 >= y_break) {
u_int b = y_break - sy;
- ops->clear(vc, info, real_y(p, sy), sx, b, width, fg, bg);
- ops->clear(vc, info, real_y(p, sy + b), sx, height - b,
- width, fg, bg);
+ par->clear(vc, info, real_y(p, sy), sx, b, width, fg, bg);
+ par->clear(vc, info, real_y(p, sy + b), sx, height - b, width, fg, bg);
} else
- ops->clear(vc, info, real_y(p, sy), sx, height, width, fg, bg);
+ par->clear(vc, info, real_y(p, sy), sx, height, width, fg, bg);
}
static void fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
@@ -1314,10 +1313,10 @@ static void fbcon_putcs(struct vc_data *
{
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
struct fbcon_display *p = &fb_display[vc->vc_num];
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
if (!fbcon_is_inactive(vc, info))
- ops->putcs(vc, info, s, count, real_y(p, ypos), xpos,
+ par->putcs(vc, info, s, count, real_y(p, ypos), xpos,
get_color(vc, info, scr_readw(s), 1),
get_color(vc, info, scr_readw(s), 0));
}
@@ -1325,19 +1324,19 @@ static void fbcon_putcs(struct vc_data *
static void fbcon_clear_margins(struct vc_data *vc, int bottom_only)
{
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
if (!fbcon_is_inactive(vc, info))
- ops->clear_margins(vc, info, margin_color, bottom_only);
+ par->clear_margins(vc, info, margin_color, bottom_only);
}
static void fbcon_cursor(struct vc_data *vc, bool enable)
{
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
int c = scr_readw((u16 *) vc->vc_pos);
- ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms);
+ par->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms);
if (fbcon_is_inactive(vc, info) || vc->vc_deccm != 1)
return;
@@ -1347,12 +1346,12 @@ static void fbcon_cursor(struct vc_data
else
fbcon_add_cursor_work(info);
- ops->cursor_flash = enable;
+ par->cursor_flash = enable;
- if (!ops->cursor)
+ if (!par->cursor)
return;
- ops->cursor(vc, info, enable, get_color(vc, info, c, 1),
+ par->cursor(vc, info, enable, get_color(vc, info, c, 1),
get_color(vc, info, c, 0));
}
@@ -1366,7 +1365,7 @@ static void fbcon_set_disp(struct fb_inf
struct fbcon_display *p, *t;
struct vc_data **default_mode, *vc;
struct vc_data *svc;
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
int rows, cols;
unsigned long ret = 0;
@@ -1399,7 +1398,7 @@ static void fbcon_set_disp(struct fb_inf
var->yoffset = info->var.yoffset;
var->xoffset = info->var.xoffset;
fb_set_var(info, var);
- ops->var = info->var;
+ par->var = info->var;
vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
if (vc->vc_font.charcount == 256) {
@@ -1415,8 +1414,8 @@ static void fbcon_set_disp(struct fb_inf
if (!*vc->uni_pagedict_loc)
con_copy_unimap(vc, svc);
- cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
- rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
+ cols = FBCON_SWAP(par->rotate, info->var.xres, info->var.yres);
+ rows = FBCON_SWAP(par->rotate, info->var.yres, info->var.xres);
cols /= vc->vc_font.width;
rows /= vc->vc_font.height;
ret = vc_resize(vc, cols, rows);
@@ -1428,16 +1427,16 @@ static void fbcon_set_disp(struct fb_inf
static __inline__ void ywrap_up(struct vc_data *vc, int count)
{
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
struct fbcon_display *p = &fb_display[vc->vc_num];
p->yscroll += count;
if (p->yscroll >= p->vrows) /* Deal with wrap */
p->yscroll -= p->vrows;
- ops->var.xoffset = 0;
- ops->var.yoffset = p->yscroll * vc->vc_font.height;
- ops->var.vmode |= FB_VMODE_YWRAP;
- ops->update_start(info);
+ par->var.xoffset = 0;
+ par->var.yoffset = p->yscroll * vc->vc_font.height;
+ par->var.vmode |= FB_VMODE_YWRAP;
+ par->update_start(info);
scrollback_max += count;
if (scrollback_max > scrollback_phys_max)
scrollback_max = scrollback_phys_max;
@@ -1447,16 +1446,16 @@ static __inline__ void ywrap_up(struct v
static __inline__ void ywrap_down(struct vc_data *vc, int count)
{
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
struct fbcon_display *p = &fb_display[vc->vc_num];
p->yscroll -= count;
if (p->yscroll < 0) /* Deal with wrap */
p->yscroll += p->vrows;
- ops->var.xoffset = 0;
- ops->var.yoffset = p->yscroll * vc->vc_font.height;
- ops->var.vmode |= FB_VMODE_YWRAP;
- ops->update_start(info);
+ par->var.xoffset = 0;
+ par->var.yoffset = p->yscroll * vc->vc_font.height;
+ par->var.vmode |= FB_VMODE_YWRAP;
+ par->update_start(info);
scrollback_max -= count;
if (scrollback_max < 0)
scrollback_max = 0;
@@ -1467,19 +1466,19 @@ static __inline__ void ypan_up(struct vc
{
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
struct fbcon_display *p = &fb_display[vc->vc_num];
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
p->yscroll += count;
if (p->yscroll > p->vrows - vc->vc_rows) {
- ops->bmove(vc, info, p->vrows - vc->vc_rows,
+ par->bmove(vc, info, p->vrows - vc->vc_rows,
0, 0, 0, vc->vc_rows, vc->vc_cols);
p->yscroll -= p->vrows - vc->vc_rows;
}
- ops->var.xoffset = 0;
- ops->var.yoffset = p->yscroll * vc->vc_font.height;
- ops->var.vmode &= ~FB_VMODE_YWRAP;
- ops->update_start(info);
+ par->var.xoffset = 0;
+ par->var.yoffset = p->yscroll * vc->vc_font.height;
+ par->var.vmode &= ~FB_VMODE_YWRAP;
+ par->update_start(info);
fbcon_clear_margins(vc, 1);
scrollback_max += count;
if (scrollback_max > scrollback_phys_max)
@@ -1490,7 +1489,7 @@ static __inline__ void ypan_up(struct vc
static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count)
{
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
struct fbcon_display *p = &fb_display[vc->vc_num];
p->yscroll += count;
@@ -1500,10 +1499,10 @@ static __inline__ void ypan_up_redraw(st
fbcon_redraw_move(vc, p, t + count, vc->vc_rows - count, t);
}
- ops->var.xoffset = 0;
- ops->var.yoffset = p->yscroll * vc->vc_font.height;
- ops->var.vmode &= ~FB_VMODE_YWRAP;
- ops->update_start(info);
+ par->var.xoffset = 0;
+ par->var.yoffset = p->yscroll * vc->vc_font.height;
+ par->var.vmode &= ~FB_VMODE_YWRAP;
+ par->update_start(info);
fbcon_clear_margins(vc, 1);
scrollback_max += count;
if (scrollback_max > scrollback_phys_max)
@@ -1515,19 +1514,19 @@ static __inline__ void ypan_down(struct
{
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
struct fbcon_display *p = &fb_display[vc->vc_num];
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
p->yscroll -= count;
if (p->yscroll < 0) {
- ops->bmove(vc, info, 0, 0, p->vrows - vc->vc_rows,
+ par->bmove(vc, info, 0, 0, p->vrows - vc->vc_rows,
0, vc->vc_rows, vc->vc_cols);
p->yscroll += p->vrows - vc->vc_rows;
}
- ops->var.xoffset = 0;
- ops->var.yoffset = p->yscroll * vc->vc_font.height;
- ops->var.vmode &= ~FB_VMODE_YWRAP;
- ops->update_start(info);
+ par->var.xoffset = 0;
+ par->var.yoffset = p->yscroll * vc->vc_font.height;
+ par->var.vmode &= ~FB_VMODE_YWRAP;
+ par->update_start(info);
fbcon_clear_margins(vc, 1);
scrollback_max -= count;
if (scrollback_max < 0)
@@ -1538,7 +1537,7 @@ static __inline__ void ypan_down(struct
static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count)
{
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
struct fbcon_display *p = &fb_display[vc->vc_num];
p->yscroll -= count;
@@ -1548,10 +1547,10 @@ static __inline__ void ypan_down_redraw(
fbcon_redraw_move(vc, p, t, vc->vc_rows - count, t + count);
}
- ops->var.xoffset = 0;
- ops->var.yoffset = p->yscroll * vc->vc_font.height;
- ops->var.vmode &= ~FB_VMODE_YWRAP;
- ops->update_start(info);
+ par->var.xoffset = 0;
+ par->var.yoffset = p->yscroll * vc->vc_font.height;
+ par->var.vmode &= ~FB_VMODE_YWRAP;
+ par->update_start(info);
fbcon_clear_margins(vc, 1);
scrollback_max -= count;
if (scrollback_max < 0)
@@ -1600,7 +1599,7 @@ static void fbcon_redraw_blit(struct vc_
unsigned short *d = (unsigned short *)
(vc->vc_origin + vc->vc_size_row * line);
unsigned short *s = d + offset;
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
while (count--) {
unsigned short *start = s;
@@ -1613,8 +1612,8 @@ static void fbcon_redraw_blit(struct vc_
if (c == scr_readw(d)) {
if (s > start) {
- ops->bmove(vc, info, line + ycount, x,
- line, x, 1, s-start);
+ par->bmove(vc, info, line + ycount, x,
+ line, x, 1, s - start);
x += s - start + 1;
start = s + 1;
} else {
@@ -1629,8 +1628,7 @@ static void fbcon_redraw_blit(struct vc_
d++;
} while (s < le);
if (s > start)
- ops->bmove(vc, info, line + ycount, x, line, x, 1,
- s-start);
+ par->bmove(vc, info, line + ycount, x, line, x, 1, s - start);
console_conditional_schedule();
if (ycount > 0)
line++;
@@ -1701,7 +1699,7 @@ static void fbcon_bmove_rec(struct vc_da
int dy, int dx, int height, int width, u_int y_break)
{
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
u_int b;
if (sy < y_break && sy + height > y_break) {
@@ -1735,8 +1733,7 @@ static void fbcon_bmove_rec(struct vc_da
}
return;
}
- ops->bmove(vc, info, real_y(p, sy), sx, real_y(p, dy), dx,
- height, width);
+ par->bmove(vc, info, real_y(p, sy), sx, real_y(p, dy), dx, height, width);
}
static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx,
@@ -1963,15 +1960,13 @@ static void updatescrollmode_accel(struc
struct vc_data *vc)
{
#ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
int cap = info->flags;
u16 t = 0;
- int ypan = FBCON_SWAP(ops->rotate, info->fix.ypanstep,
- info->fix.xpanstep);
- int ywrap = FBCON_SWAP(ops->rotate, info->fix.ywrapstep, t);
- int yres = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
- int vyres = FBCON_SWAP(ops->rotate, info->var.yres_virtual,
- info->var.xres_virtual);
+ int ypan = FBCON_SWAP(par->rotate, info->fix.ypanstep, info->fix.xpanstep);
+ int ywrap = FBCON_SWAP(par->rotate, info->fix.ywrapstep, t);
+ int yres = FBCON_SWAP(par->rotate, info->var.yres, info->var.xres);
+ int vyres = FBCON_SWAP(par->rotate, info->var.yres_virtual, info->var.xres_virtual);
int good_pan = (cap & FBINFO_HWACCEL_YPAN) &&
divides(ypan, vc->vc_font.height) && vyres > yres;
int good_wrap = (cap & FBINFO_HWACCEL_YWRAP) &&
@@ -2004,11 +1999,10 @@ static void updatescrollmode(struct fbco
struct fb_info *info,
struct vc_data *vc)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
int fh = vc->vc_font.height;
- int yres = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
- int vyres = FBCON_SWAP(ops->rotate, info->var.yres_virtual,
- info->var.xres_virtual);
+ int yres = FBCON_SWAP(par->rotate, info->var.yres, info->var.xres);
+ int vyres = FBCON_SWAP(par->rotate, info->var.yres_virtual, info->var.xres_virtual);
p->vrows = vyres/fh;
if (yres > (fh * (vc->vc_rows + 1)))
@@ -2027,7 +2021,7 @@ static int fbcon_resize(struct vc_data *
unsigned int height, bool from_user)
{
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
struct fbcon_display *p = &fb_display[vc->vc_num];
struct fb_var_screeninfo var = info->var;
int x_diff, y_diff, virt_w, virt_h, virt_fw, virt_fh;
@@ -2050,12 +2044,10 @@ static int fbcon_resize(struct vc_data *
return -EINVAL;
}
- virt_w = FBCON_SWAP(ops->rotate, width, height);
- virt_h = FBCON_SWAP(ops->rotate, height, width);
- virt_fw = FBCON_SWAP(ops->rotate, vc->vc_font.width,
- vc->vc_font.height);
- virt_fh = FBCON_SWAP(ops->rotate, vc->vc_font.height,
- vc->vc_font.width);
+ virt_w = FBCON_SWAP(par->rotate, width, height);
+ virt_h = FBCON_SWAP(par->rotate, height, width);
+ virt_fw = FBCON_SWAP(par->rotate, vc->vc_font.width, vc->vc_font.height);
+ virt_fh = FBCON_SWAP(par->rotate, vc->vc_font.height, vc->vc_font.width);
var.xres = virt_w * virt_fw;
var.yres = virt_h * virt_fh;
x_diff = info->var.xres - var.xres;
@@ -2081,7 +2073,7 @@ static int fbcon_resize(struct vc_data *
fb_set_var(info, &var);
}
var_to_display(p, &info->var, info);
- ops->var = info->var;
+ par->var = info->var;
}
updatescrollmode(p, info, vc);
return 0;
@@ -2090,13 +2082,13 @@ static int fbcon_resize(struct vc_data *
static bool fbcon_switch(struct vc_data *vc)
{
struct fb_info *info, *old_info = NULL;
- struct fbcon_ops *ops;
+ struct fbcon_par *par;
struct fbcon_display *p = &fb_display[vc->vc_num];
struct fb_var_screeninfo var;
int i, ret, prev_console;
info = fbcon_info_from_console(vc->vc_num);
- ops = info->fbcon_par;
+ par = info->fbcon_par;
if (logo_shown >= 0) {
struct vc_data *conp2 = vc_cons[logo_shown].d;
@@ -2107,7 +2099,7 @@ static bool fbcon_switch(struct vc_data
logo_shown = FBCON_LOGO_CANSHOW;
}
- prev_console = ops->currcon;
+ prev_console = par->currcon;
if (prev_console != -1)
old_info = fbcon_info_from_console(prev_console);
/*
@@ -2120,9 +2112,9 @@ static bool fbcon_switch(struct vc_data
*/
fbcon_for_each_registered_fb(i) {
if (fbcon_registered_fb[i]->fbcon_par) {
- struct fbcon_ops *o = fbcon_registered_fb[i]->fbcon_par;
+ struct fbcon_par *par = fbcon_registered_fb[i]->fbcon_par;
- o->currcon = vc->vc_num;
+ par->currcon = vc->vc_num;
}
}
memset(&var, 0, sizeof(struct fb_var_screeninfo));
@@ -2136,7 +2128,7 @@ static bool fbcon_switch(struct vc_data
info->var.activate = var.activate;
var.vmode |= info->var.vmode & ~FB_VMODE_MASK;
fb_set_var(info, &var);
- ops->var = info->var;
+ par->var = info->var;
if (old_info != NULL && (old_info != info ||
info->flags & FBINFO_MISC_ALWAYS_SETPAR)) {
@@ -2154,16 +2146,16 @@ static bool fbcon_switch(struct vc_data
}
if (fbcon_is_inactive(vc, info) ||
- ops->blank_state != FB_BLANK_UNBLANK)
+ par->blank_state != FB_BLANK_UNBLANK)
fbcon_del_cursor_work(info);
else
fbcon_add_cursor_work(info);
set_blitting_type(vc, info);
- ops->cursor_reset = 1;
+ par->cursor_reset = 1;
- if (ops->rotate_font && ops->rotate_font(info, vc)) {
- ops->rotate = FB_ROTATE_UR;
+ if (par->rotate_font && par->rotate_font(info, vc)) {
+ par->rotate = FB_ROTATE_UR;
set_blitting_type(vc, info);
}
@@ -2194,8 +2186,8 @@ static bool fbcon_switch(struct vc_data
scrollback_current = 0;
if (!fbcon_is_inactive(vc, info)) {
- ops->var.xoffset = ops->var.yoffset = p->yscroll = 0;
- ops->update_start(info);
+ par->var.xoffset = par->var.yoffset = p->yscroll = 0;
+ par->update_start(info);
}
fbcon_set_palette(vc, color_table);
@@ -2204,7 +2196,7 @@ static bool fbcon_switch(struct vc_data
if (logo_shown == FBCON_LOGO_DRAW) {
logo_shown = fg_console;
- fb_show_logo(info, ops->rotate);
+ fb_show_logo(info, par->rotate);
update_region(vc,
vc->vc_origin + vc->vc_size_row * vc->vc_top,
vc->vc_size_row * (vc->vc_bottom -
@@ -2233,27 +2225,27 @@ static bool fbcon_blank(struct vc_data *
bool mode_switch)
{
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
if (mode_switch) {
struct fb_var_screeninfo var = info->var;
- ops->graphics = 1;
+ par->graphics = 1;
if (!blank) {
var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE |
FB_ACTIVATE_KD_TEXT;
fb_set_var(info, &var);
- ops->graphics = 0;
- ops->var = info->var;
+ par->graphics = 0;
+ par->var = info->var;
}
}
if (!fbcon_is_inactive(vc, info)) {
- if (ops->blank_state != blank) {
- ops->blank_state = blank;
+ if (par->blank_state != blank) {
+ par->blank_state = blank;
fbcon_cursor(vc, !blank);
- ops->cursor_flash = (!blank);
+ par->cursor_flash = (!blank);
if (fb_blank(info, blank))
fbcon_generic_blank(vc, info, blank);
@@ -2264,7 +2256,7 @@ static bool fbcon_blank(struct vc_data *
}
if (mode_switch || fbcon_is_inactive(vc, info) ||
- ops->blank_state != FB_BLANK_UNBLANK)
+ par->blank_state != FB_BLANK_UNBLANK)
fbcon_del_cursor_work(info);
else
fbcon_add_cursor_work(info);
@@ -2275,10 +2267,10 @@ static bool fbcon_blank(struct vc_data *
static void fbcon_debug_enter(struct vc_data *vc)
{
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
- ops->save_graphics = ops->graphics;
- ops->graphics = 0;
+ par->save_graphics = par->graphics;
+ par->graphics = 0;
if (info->fbops->fb_debug_enter)
info->fbops->fb_debug_enter(info);
fbcon_set_palette(vc, color_table);
@@ -2287,9 +2279,9 @@ static void fbcon_debug_enter(struct vc_
static void fbcon_debug_leave(struct vc_data *vc)
{
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
- ops->graphics = ops->save_graphics;
+ par->graphics = par->save_graphics;
if (info->fbops->fb_debug_leave)
info->fbops->fb_debug_leave(info);
}
@@ -2424,7 +2416,7 @@ static int fbcon_do_set_font(struct vc_d
const u8 * data, int userfont)
{
struct fb_info *info = fbcon_info_from_console(vc->vc_num);
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
struct fbcon_display *p = &fb_display[vc->vc_num];
int resize, ret, old_userfont, old_width, old_height, old_charcount;
u8 *old_data = vc->vc_font.data;
@@ -2451,8 +2443,8 @@ static int fbcon_do_set_font(struct vc_d
if (resize) {
int cols, rows;
- cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
- rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
+ cols = FBCON_SWAP(par->rotate, info->var.xres, info->var.yres);
+ rows = FBCON_SWAP(par->rotate, info->var.yres, info->var.xres);
cols /= w;
rows /= h;
ret = vc_resize(vc, cols, rows);
@@ -2657,11 +2649,11 @@ static void fbcon_invert_region(struct v
void fbcon_suspended(struct fb_info *info)
{
struct vc_data *vc = NULL;
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
- if (!ops || ops->currcon < 0)
+ if (!par || par->currcon < 0)
return;
- vc = vc_cons[ops->currcon].d;
+ vc = vc_cons[par->currcon].d;
/* Clear cursor, restore saved data */
fbcon_cursor(vc, false);
@@ -2670,27 +2662,27 @@ void fbcon_suspended(struct fb_info *inf
void fbcon_resumed(struct fb_info *info)
{
struct vc_data *vc;
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
- if (!ops || ops->currcon < 0)
+ if (!par || par->currcon < 0)
return;
- vc = vc_cons[ops->currcon].d;
+ vc = vc_cons[par->currcon].d;
update_screen(vc);
}
static void fbcon_modechanged(struct fb_info *info)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
struct vc_data *vc;
struct fbcon_display *p;
int rows, cols;
- if (!ops || ops->currcon < 0)
+ if (!par || par->currcon < 0)
return;
- vc = vc_cons[ops->currcon].d;
+ vc = vc_cons[par->currcon].d;
if (vc->vc_mode != KD_TEXT ||
- fbcon_info_from_console(ops->currcon) != info)
+ fbcon_info_from_console(par->currcon) != info)
return;
p = &fb_display[vc->vc_num];
@@ -2698,8 +2690,8 @@ static void fbcon_modechanged(struct fb_
if (con_is_visible(vc)) {
var_to_display(p, &info->var, info);
- cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
- rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
+ cols = FBCON_SWAP(par->rotate, info->var.xres, info->var.yres);
+ rows = FBCON_SWAP(par->rotate, info->var.yres, info->var.xres);
cols /= vc->vc_font.width;
rows /= vc->vc_font.height;
vc_resize(vc, cols, rows);
@@ -2708,8 +2700,8 @@ static void fbcon_modechanged(struct fb_
scrollback_current = 0;
if (!fbcon_is_inactive(vc, info)) {
- ops->var.xoffset = ops->var.yoffset = p->yscroll = 0;
- ops->update_start(info);
+ par->var.xoffset = par->var.yoffset = p->yscroll = 0;
+ par->update_start(info);
}
fbcon_set_palette(vc, color_table);
@@ -2719,12 +2711,12 @@ static void fbcon_modechanged(struct fb_
static void fbcon_set_all_vcs(struct fb_info *info)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
struct vc_data *vc;
struct fbcon_display *p;
int i, rows, cols, fg = -1;
- if (!ops || ops->currcon < 0)
+ if (!par || par->currcon < 0)
return;
for (i = first_fb_vc; i <= last_fb_vc; i++) {
@@ -2741,8 +2733,8 @@ static void fbcon_set_all_vcs(struct fb_
p = &fb_display[vc->vc_num];
set_blitting_type(vc, info);
var_to_display(p, &info->var, info);
- cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
- rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
+ cols = FBCON_SWAP(par->rotate, info->var.xres, info->var.yres);
+ rows = FBCON_SWAP(par->rotate, info->var.yres, info->var.xres);
cols /= vc->vc_font.width;
rows /= vc->vc_font.height;
vc_resize(vc, cols, rows);
@@ -2765,13 +2757,13 @@ EXPORT_SYMBOL(fbcon_update_vcs);
/* let fbcon check if it supports a new screen resolution */
int fbcon_modechange_possible(struct fb_info *info, struct fb_var_screeninfo *var)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
struct vc_data *vc;
unsigned int i;
WARN_CONSOLE_UNLOCKED();
- if (!ops)
+ if (!par)
return 0;
/* prevent setting a screen size which is smaller than font size */
@@ -3069,15 +3061,14 @@ int fbcon_fb_registered(struct fb_info *
void fbcon_fb_blanked(struct fb_info *info, int blank)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
struct vc_data *vc;
- if (!ops || ops->currcon < 0)
+ if (!par || par->currcon < 0)
return;
- vc = vc_cons[ops->currcon].d;
- if (vc->vc_mode != KD_TEXT ||
- fbcon_info_from_console(ops->currcon) != info)
+ vc = vc_cons[par->currcon].d;
+ if (vc->vc_mode != KD_TEXT || fbcon_info_from_console(par->currcon) != info)
return;
if (con_is_visible(vc)) {
@@ -3086,7 +3077,7 @@ void fbcon_fb_blanked(struct fb_info *in
else
do_unblank_screen(0);
}
- ops->blank_state = blank;
+ par->blank_state = blank;
}
void fbcon_new_modelist(struct fb_info *info)
@@ -3276,7 +3267,7 @@ static ssize_t show_cursor_blink(struct
struct device_attribute *attr, char *buf)
{
struct fb_info *info;
- struct fbcon_ops *ops;
+ struct fbcon_par *par;
int idx, blink = -1;
console_lock();
@@ -3286,12 +3277,12 @@ static ssize_t show_cursor_blink(struct
goto err;
info = fbcon_registered_fb[idx];
- ops = info->fbcon_par;
+ par = info->fbcon_par;
- if (!ops)
+ if (!par)
goto err;
- blink = delayed_work_pending(&ops->cursor_work);
+ blink = delayed_work_pending(&par->cursor_work);
err:
console_unlock();
return sysfs_emit(buf, "%d\n", blink);
--- a/drivers/video/fbdev/core/fbcon.h
+++ b/drivers/video/fbdev/core/fbcon.h
@@ -50,7 +50,7 @@ struct fbcon_display {
const struct fb_videomode *mode;
};
-struct fbcon_ops {
+struct fbcon_par {
void (*bmove)(struct vc_data *vc, struct fb_info *info, int sy,
int sx, int dy, int dx, int height, int width);
void (*clear)(struct vc_data *vc, struct fb_info *info, int sy,
@@ -185,7 +185,7 @@ static inline u_short fb_scrollmode(stru
#ifdef CONFIG_FB_TILEBLITTING
extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info);
#endif
-extern void fbcon_set_bitops(struct fbcon_ops *ops);
+extern void fbcon_set_bitops(struct fbcon_par *par);
extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor);
#define FBCON_ATTRIBUTE_UNDERLINE 1
@@ -224,7 +224,7 @@ static inline int get_attribute(struct f
(i == FB_ROTATE_UR || i == FB_ROTATE_UD) ? _r : _v; })
#ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION
-extern void fbcon_set_rotate(struct fbcon_ops *ops);
+extern void fbcon_set_rotate(struct fbcon_par *par);
#else
#define fbcon_set_rotate(x) do {} while(0)
#endif /* CONFIG_FRAMEBUFFER_CONSOLE_ROTATION */
--- a/drivers/video/fbdev/core/fbcon_ccw.c
+++ b/drivers/video/fbdev/core/fbcon_ccw.c
@@ -63,9 +63,9 @@ static void ccw_update_attr(u8 *dst, u8
static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy,
int sx, int dy, int dx, int height, int width)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
struct fb_copyarea area;
- u32 vyres = GETVYRES(ops->p, info);
+ u32 vyres = GETVYRES(par->p, info);
area.sx = sy * vc->vc_font.height;
area.sy = vyres - ((sx + width) * vc->vc_font.width);
@@ -80,9 +80,9 @@ static void ccw_bmove(struct vc_data *vc
static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy,
int sx, int height, int width, int fg, int bg)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
struct fb_fillrect region;
- u32 vyres = GETVYRES(ops->p, info);
+ u32 vyres = GETVYRES(par->p, info);
region.color = bg;
region.dx = sy * vc->vc_font.height;
@@ -99,13 +99,13 @@ static inline void ccw_putcs_aligned(str
u32 d_pitch, u32 s_pitch, u32 cellsize,
struct fb_image *image, u8 *buf, u8 *dst)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
u32 idx = (vc->vc_font.height + 7) >> 3;
u8 *src;
while (cnt--) {
- src = ops->fontbuffer + (scr_readw(s--) & charmask)*cellsize;
+ src = par->fontbuffer + (scr_readw(s--) & charmask) * cellsize;
if (attr) {
ccw_update_attr(buf, src, attr, vc);
@@ -130,7 +130,7 @@ static void ccw_putcs(struct vc_data *vc
int fg, int bg)
{
struct fb_image image;
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
u32 width = (vc->vc_font.height + 7)/8;
u32 cellsize = width * vc->vc_font.width;
u32 maxcnt = info->pixmap.size/cellsize;
@@ -139,9 +139,9 @@ static void ccw_putcs(struct vc_data *vc
u32 cnt, pitch, size;
u32 attribute = get_attribute(info, scr_readw(s));
u8 *dst, *buf = NULL;
- u32 vyres = GETVYRES(ops->p, info);
+ u32 vyres = GETVYRES(par->p, info);
- if (!ops->fontbuffer)
+ if (!par->fontbuffer)
return;
image.fg_color = fg;
@@ -221,28 +221,28 @@ static void ccw_cursor(struct vc_data *v
int fg, int bg)
{
struct fb_cursor cursor;
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
int w = (vc->vc_font.height + 7) >> 3, c;
- int y = real_y(ops->p, vc->state.y);
+ int y = real_y(par->p, vc->state.y);
int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
int err = 1, dx, dy;
char *src;
- u32 vyres = GETVYRES(ops->p, info);
+ u32 vyres = GETVYRES(par->p, info);
- if (!ops->fontbuffer)
+ if (!par->fontbuffer)
return;
cursor.set = 0;
c = scr_readw((u16 *) vc->vc_pos);
attribute = get_attribute(info, c);
- src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
+ src = par->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
- if (ops->cursor_state.image.data != src ||
- ops->cursor_reset) {
- ops->cursor_state.image.data = src;
- cursor.set |= FB_CUR_SETIMAGE;
+ if (par->cursor_state.image.data != src ||
+ par->cursor_reset) {
+ par->cursor_state.image.data = src;
+ cursor.set |= FB_CUR_SETIMAGE;
}
if (attribute) {
@@ -251,49 +251,49 @@ static void ccw_cursor(struct vc_data *v
dst = kmalloc_array(w, vc->vc_font.width, GFP_ATOMIC);
if (!dst)
return;
- kfree(ops->cursor_data);
- ops->cursor_data = dst;
+ kfree(par->cursor_data);
+ par->cursor_data = dst;
ccw_update_attr(dst, src, attribute, vc);
src = dst;
}
- if (ops->cursor_state.image.fg_color != fg ||
- ops->cursor_state.image.bg_color != bg ||
- ops->cursor_reset) {
- ops->cursor_state.image.fg_color = fg;
- ops->cursor_state.image.bg_color = bg;
+ if (par->cursor_state.image.fg_color != fg ||
+ par->cursor_state.image.bg_color != bg ||
+ par->cursor_reset) {
+ par->cursor_state.image.fg_color = fg;
+ par->cursor_state.image.bg_color = bg;
cursor.set |= FB_CUR_SETCMAP;
}
- if (ops->cursor_state.image.height != vc->vc_font.width ||
- ops->cursor_state.image.width != vc->vc_font.height ||
- ops->cursor_reset) {
- ops->cursor_state.image.height = vc->vc_font.width;
- ops->cursor_state.image.width = vc->vc_font.height;
+ if (par->cursor_state.image.height != vc->vc_font.width ||
+ par->cursor_state.image.width != vc->vc_font.height ||
+ par->cursor_reset) {
+ par->cursor_state.image.height = vc->vc_font.width;
+ par->cursor_state.image.width = vc->vc_font.height;
cursor.set |= FB_CUR_SETSIZE;
}
dx = y * vc->vc_font.height;
dy = vyres - ((vc->state.x + 1) * vc->vc_font.width);
- if (ops->cursor_state.image.dx != dx ||
- ops->cursor_state.image.dy != dy ||
- ops->cursor_reset) {
- ops->cursor_state.image.dx = dx;
- ops->cursor_state.image.dy = dy;
+ if (par->cursor_state.image.dx != dx ||
+ par->cursor_state.image.dy != dy ||
+ par->cursor_reset) {
+ par->cursor_state.image.dx = dx;
+ par->cursor_state.image.dy = dy;
cursor.set |= FB_CUR_SETPOS;
}
- if (ops->cursor_state.hot.x || ops->cursor_state.hot.y ||
- ops->cursor_reset) {
- ops->cursor_state.hot.x = cursor.hot.y = 0;
+ if (par->cursor_state.hot.x || par->cursor_state.hot.y ||
+ par->cursor_reset) {
+ par->cursor_state.hot.x = cursor.hot.y = 0;
cursor.set |= FB_CUR_SETHOT;
}
if (cursor.set & FB_CUR_SETSIZE ||
- vc->vc_cursor_type != ops->p->cursor_shape ||
- ops->cursor_state.mask == NULL ||
- ops->cursor_reset) {
+ vc->vc_cursor_type != par->p->cursor_shape ||
+ par->cursor_state.mask == NULL ||
+ par->cursor_reset) {
char *tmp, *mask = kmalloc_array(w, vc->vc_font.width,
GFP_ATOMIC);
int cur_height, size, i = 0;
@@ -309,13 +309,13 @@ static void ccw_cursor(struct vc_data *v
return;
}
- kfree(ops->cursor_state.mask);
- ops->cursor_state.mask = mask;
+ kfree(par->cursor_state.mask);
+ par->cursor_state.mask = mask;
- ops->p->cursor_shape = vc->vc_cursor_type;
+ par->p->cursor_shape = vc->vc_cursor_type;
cursor.set |= FB_CUR_SETSHAPE;
- switch (CUR_SIZE(ops->p->cursor_shape)) {
+ switch (CUR_SIZE(par->p->cursor_shape)) {
case CUR_NONE:
cur_height = 0;
break;
@@ -348,19 +348,19 @@ static void ccw_cursor(struct vc_data *v
kfree(tmp);
}
- ops->cursor_state.enable = enable && !use_sw;
+ par->cursor_state.enable = enable && !use_sw;
cursor.image.data = src;
- cursor.image.fg_color = ops->cursor_state.image.fg_color;
- cursor.image.bg_color = ops->cursor_state.image.bg_color;
- cursor.image.dx = ops->cursor_state.image.dx;
- cursor.image.dy = ops->cursor_state.image.dy;
- cursor.image.height = ops->cursor_state.image.height;
- cursor.image.width = ops->cursor_state.image.width;
- cursor.hot.x = ops->cursor_state.hot.x;
- cursor.hot.y = ops->cursor_state.hot.y;
- cursor.mask = ops->cursor_state.mask;
- cursor.enable = ops->cursor_state.enable;
+ cursor.image.fg_color = par->cursor_state.image.fg_color;
+ cursor.image.bg_color = par->cursor_state.image.bg_color;
+ cursor.image.dx = par->cursor_state.image.dx;
+ cursor.image.dy = par->cursor_state.image.dy;
+ cursor.image.height = par->cursor_state.image.height;
+ cursor.image.width = par->cursor_state.image.width;
+ cursor.hot.x = par->cursor_state.hot.x;
+ cursor.hot.y = par->cursor_state.hot.y;
+ cursor.mask = par->cursor_state.mask;
+ cursor.enable = par->cursor_state.enable;
cursor.image.depth = 1;
cursor.rop = ROP_XOR;
@@ -370,32 +370,32 @@ static void ccw_cursor(struct vc_data *v
if (err)
soft_cursor(info, &cursor);
- ops->cursor_reset = 0;
+ par->cursor_reset = 0;
}
static int ccw_update_start(struct fb_info *info)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
u32 yoffset;
- u32 vyres = GETVYRES(ops->p, info);
+ u32 vyres = GETVYRES(par->p, info);
int err;
- yoffset = (vyres - info->var.yres) - ops->var.xoffset;
- ops->var.xoffset = ops->var.yoffset;
- ops->var.yoffset = yoffset;
- err = fb_pan_display(info, &ops->var);
- ops->var.xoffset = info->var.xoffset;
- ops->var.yoffset = info->var.yoffset;
- ops->var.vmode = info->var.vmode;
+ yoffset = (vyres - info->var.yres) - par->var.xoffset;
+ par->var.xoffset = par->var.yoffset;
+ par->var.yoffset = yoffset;
+ err = fb_pan_display(info, &par->var);
+ par->var.xoffset = info->var.xoffset;
+ par->var.yoffset = info->var.yoffset;
+ par->var.vmode = info->var.vmode;
return err;
}
-void fbcon_rotate_ccw(struct fbcon_ops *ops)
+void fbcon_rotate_ccw(struct fbcon_par *par)
{
- ops->bmove = ccw_bmove;
- ops->clear = ccw_clear;
- ops->putcs = ccw_putcs;
- ops->clear_margins = ccw_clear_margins;
- ops->cursor = ccw_cursor;
- ops->update_start = ccw_update_start;
+ par->bmove = ccw_bmove;
+ par->clear = ccw_clear;
+ par->putcs = ccw_putcs;
+ par->clear_margins = ccw_clear_margins;
+ par->cursor = ccw_cursor;
+ par->update_start = ccw_update_start;
}
--- a/drivers/video/fbdev/core/fbcon_cw.c
+++ b/drivers/video/fbdev/core/fbcon_cw.c
@@ -48,9 +48,9 @@ static void cw_update_attr(u8 *dst, u8 *
static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy,
int sx, int dy, int dx, int height, int width)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
struct fb_copyarea area;
- u32 vxres = GETVXRES(ops->p, info);
+ u32 vxres = GETVXRES(par->p, info);
area.sx = vxres - ((sy + height) * vc->vc_font.height);
area.sy = sx * vc->vc_font.width;
@@ -65,9 +65,9 @@ static void cw_bmove(struct vc_data *vc,
static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy,
int sx, int height, int width, int fg, int bg)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
struct fb_fillrect region;
- u32 vxres = GETVXRES(ops->p, info);
+ u32 vxres = GETVXRES(par->p, info);
region.color = bg;
region.dx = vxres - ((sy + height) * vc->vc_font.height);
@@ -84,13 +84,13 @@ static inline void cw_putcs_aligned(stru
u32 d_pitch, u32 s_pitch, u32 cellsize,
struct fb_image *image, u8 *buf, u8 *dst)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
u32 idx = (vc->vc_font.height + 7) >> 3;
u8 *src;
while (cnt--) {
- src = ops->fontbuffer + (scr_readw(s++) & charmask)*cellsize;
+ src = par->fontbuffer + (scr_readw(s++) & charmask) * cellsize;
if (attr) {
cw_update_attr(buf, src, attr, vc);
@@ -115,7 +115,7 @@ static void cw_putcs(struct vc_data *vc,
int fg, int bg)
{
struct fb_image image;
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
u32 width = (vc->vc_font.height + 7)/8;
u32 cellsize = width * vc->vc_font.width;
u32 maxcnt = info->pixmap.size/cellsize;
@@ -124,9 +124,9 @@ static void cw_putcs(struct vc_data *vc,
u32 cnt, pitch, size;
u32 attribute = get_attribute(info, scr_readw(s));
u8 *dst, *buf = NULL;
- u32 vxres = GETVXRES(ops->p, info);
+ u32 vxres = GETVXRES(par->p, info);
- if (!ops->fontbuffer)
+ if (!par->fontbuffer)
return;
image.fg_color = fg;
@@ -204,28 +204,28 @@ static void cw_cursor(struct vc_data *vc
int fg, int bg)
{
struct fb_cursor cursor;
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
int w = (vc->vc_font.height + 7) >> 3, c;
- int y = real_y(ops->p, vc->state.y);
+ int y = real_y(par->p, vc->state.y);
int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
int err = 1, dx, dy;
char *src;
- u32 vxres = GETVXRES(ops->p, info);
+ u32 vxres = GETVXRES(par->p, info);
- if (!ops->fontbuffer)
+ if (!par->fontbuffer)
return;
cursor.set = 0;
c = scr_readw((u16 *) vc->vc_pos);
attribute = get_attribute(info, c);
- src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
+ src = par->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
- if (ops->cursor_state.image.data != src ||
- ops->cursor_reset) {
- ops->cursor_state.image.data = src;
- cursor.set |= FB_CUR_SETIMAGE;
+ if (par->cursor_state.image.data != src ||
+ par->cursor_reset) {
+ par->cursor_state.image.data = src;
+ cursor.set |= FB_CUR_SETIMAGE;
}
if (attribute) {
@@ -234,49 +234,49 @@ static void cw_cursor(struct vc_data *vc
dst = kmalloc_array(w, vc->vc_font.width, GFP_ATOMIC);
if (!dst)
return;
- kfree(ops->cursor_data);
- ops->cursor_data = dst;
+ kfree(par->cursor_data);
+ par->cursor_data = dst;
cw_update_attr(dst, src, attribute, vc);
src = dst;
}
- if (ops->cursor_state.image.fg_color != fg ||
- ops->cursor_state.image.bg_color != bg ||
- ops->cursor_reset) {
- ops->cursor_state.image.fg_color = fg;
- ops->cursor_state.image.bg_color = bg;
+ if (par->cursor_state.image.fg_color != fg ||
+ par->cursor_state.image.bg_color != bg ||
+ par->cursor_reset) {
+ par->cursor_state.image.fg_color = fg;
+ par->cursor_state.image.bg_color = bg;
cursor.set |= FB_CUR_SETCMAP;
}
- if (ops->cursor_state.image.height != vc->vc_font.width ||
- ops->cursor_state.image.width != vc->vc_font.height ||
- ops->cursor_reset) {
- ops->cursor_state.image.height = vc->vc_font.width;
- ops->cursor_state.image.width = vc->vc_font.height;
+ if (par->cursor_state.image.height != vc->vc_font.width ||
+ par->cursor_state.image.width != vc->vc_font.height ||
+ par->cursor_reset) {
+ par->cursor_state.image.height = vc->vc_font.width;
+ par->cursor_state.image.width = vc->vc_font.height;
cursor.set |= FB_CUR_SETSIZE;
}
dx = vxres - ((y * vc->vc_font.height) + vc->vc_font.height);
dy = vc->state.x * vc->vc_font.width;
- if (ops->cursor_state.image.dx != dx ||
- ops->cursor_state.image.dy != dy ||
- ops->cursor_reset) {
- ops->cursor_state.image.dx = dx;
- ops->cursor_state.image.dy = dy;
+ if (par->cursor_state.image.dx != dx ||
+ par->cursor_state.image.dy != dy ||
+ par->cursor_reset) {
+ par->cursor_state.image.dx = dx;
+ par->cursor_state.image.dy = dy;
cursor.set |= FB_CUR_SETPOS;
}
- if (ops->cursor_state.hot.x || ops->cursor_state.hot.y ||
- ops->cursor_reset) {
- ops->cursor_state.hot.x = cursor.hot.y = 0;
+ if (par->cursor_state.hot.x || par->cursor_state.hot.y ||
+ par->cursor_reset) {
+ par->cursor_state.hot.x = cursor.hot.y = 0;
cursor.set |= FB_CUR_SETHOT;
}
if (cursor.set & FB_CUR_SETSIZE ||
- vc->vc_cursor_type != ops->p->cursor_shape ||
- ops->cursor_state.mask == NULL ||
- ops->cursor_reset) {
+ vc->vc_cursor_type != par->p->cursor_shape ||
+ par->cursor_state.mask == NULL ||
+ par->cursor_reset) {
char *tmp, *mask = kmalloc_array(w, vc->vc_font.width,
GFP_ATOMIC);
int cur_height, size, i = 0;
@@ -292,13 +292,13 @@ static void cw_cursor(struct vc_data *vc
return;
}
- kfree(ops->cursor_state.mask);
- ops->cursor_state.mask = mask;
+ kfree(par->cursor_state.mask);
+ par->cursor_state.mask = mask;
- ops->p->cursor_shape = vc->vc_cursor_type;
+ par->p->cursor_shape = vc->vc_cursor_type;
cursor.set |= FB_CUR_SETSHAPE;
- switch (CUR_SIZE(ops->p->cursor_shape)) {
+ switch (CUR_SIZE(par->p->cursor_shape)) {
case CUR_NONE:
cur_height = 0;
break;
@@ -331,19 +331,19 @@ static void cw_cursor(struct vc_data *vc
kfree(tmp);
}
- ops->cursor_state.enable = enable && !use_sw;
+ par->cursor_state.enable = enable && !use_sw;
cursor.image.data = src;
- cursor.image.fg_color = ops->cursor_state.image.fg_color;
- cursor.image.bg_color = ops->cursor_state.image.bg_color;
- cursor.image.dx = ops->cursor_state.image.dx;
- cursor.image.dy = ops->cursor_state.image.dy;
- cursor.image.height = ops->cursor_state.image.height;
- cursor.image.width = ops->cursor_state.image.width;
- cursor.hot.x = ops->cursor_state.hot.x;
- cursor.hot.y = ops->cursor_state.hot.y;
- cursor.mask = ops->cursor_state.mask;
- cursor.enable = ops->cursor_state.enable;
+ cursor.image.fg_color = par->cursor_state.image.fg_color;
+ cursor.image.bg_color = par->cursor_state.image.bg_color;
+ cursor.image.dx = par->cursor_state.image.dx;
+ cursor.image.dy = par->cursor_state.image.dy;
+ cursor.image.height = par->cursor_state.image.height;
+ cursor.image.width = par->cursor_state.image.width;
+ cursor.hot.x = par->cursor_state.hot.x;
+ cursor.hot.y = par->cursor_state.hot.y;
+ cursor.mask = par->cursor_state.mask;
+ cursor.enable = par->cursor_state.enable;
cursor.image.depth = 1;
cursor.rop = ROP_XOR;
@@ -353,32 +353,32 @@ static void cw_cursor(struct vc_data *vc
if (err)
soft_cursor(info, &cursor);
- ops->cursor_reset = 0;
+ par->cursor_reset = 0;
}
static int cw_update_start(struct fb_info *info)
{
- struct fbcon_ops *ops = info->fbcon_par;
- u32 vxres = GETVXRES(ops->p, info);
+ struct fbcon_par *par = info->fbcon_par;
+ u32 vxres = GETVXRES(par->p, info);
u32 xoffset;
int err;
- xoffset = vxres - (info->var.xres + ops->var.yoffset);
- ops->var.yoffset = ops->var.xoffset;
- ops->var.xoffset = xoffset;
- err = fb_pan_display(info, &ops->var);
- ops->var.xoffset = info->var.xoffset;
- ops->var.yoffset = info->var.yoffset;
- ops->var.vmode = info->var.vmode;
+ xoffset = vxres - (info->var.xres + par->var.yoffset);
+ par->var.yoffset = par->var.xoffset;
+ par->var.xoffset = xoffset;
+ err = fb_pan_display(info, &par->var);
+ par->var.xoffset = info->var.xoffset;
+ par->var.yoffset = info->var.yoffset;
+ par->var.vmode = info->var.vmode;
return err;
}
-void fbcon_rotate_cw(struct fbcon_ops *ops)
+void fbcon_rotate_cw(struct fbcon_par *par)
{
- ops->bmove = cw_bmove;
- ops->clear = cw_clear;
- ops->putcs = cw_putcs;
- ops->clear_margins = cw_clear_margins;
- ops->cursor = cw_cursor;
- ops->update_start = cw_update_start;
+ par->bmove = cw_bmove;
+ par->clear = cw_clear;
+ par->putcs = cw_putcs;
+ par->clear_margins = cw_clear_margins;
+ par->cursor = cw_cursor;
+ par->update_start = cw_update_start;
}
--- a/drivers/video/fbdev/core/fbcon_rotate.c
+++ b/drivers/video/fbdev/core/fbcon_rotate.c
@@ -20,35 +20,35 @@
static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
int len, err = 0;
int s_cellsize, d_cellsize, i;
const u8 *src;
u8 *dst;
- if (vc->vc_font.data == ops->fontdata &&
- ops->p->con_rotate == ops->cur_rotate)
+ if (vc->vc_font.data == par->fontdata &&
+ par->p->con_rotate == par->cur_rotate)
goto finished;
- src = ops->fontdata = vc->vc_font.data;
- ops->cur_rotate = ops->p->con_rotate;
+ src = par->fontdata = vc->vc_font.data;
+ par->cur_rotate = par->p->con_rotate;
len = vc->vc_font.charcount;
s_cellsize = ((vc->vc_font.width + 7)/8) *
vc->vc_font.height;
d_cellsize = s_cellsize;
- if (ops->rotate == FB_ROTATE_CW ||
- ops->rotate == FB_ROTATE_CCW)
+ if (par->rotate == FB_ROTATE_CW ||
+ par->rotate == FB_ROTATE_CCW)
d_cellsize = ((vc->vc_font.height + 7)/8) *
vc->vc_font.width;
if (info->fbops->fb_sync)
info->fbops->fb_sync(info);
- if (ops->fd_size < d_cellsize * len) {
- kfree(ops->fontbuffer);
- ops->fontbuffer = NULL;
- ops->fd_size = 0;
+ if (par->fd_size < d_cellsize * len) {
+ kfree(par->fontbuffer);
+ par->fontbuffer = NULL;
+ par->fd_size = 0;
dst = kmalloc_array(len, d_cellsize, GFP_KERNEL);
@@ -57,14 +57,14 @@ static int fbcon_rotate_font(struct fb_i
goto finished;
}
- ops->fd_size = d_cellsize * len;
- ops->fontbuffer = dst;
+ par->fd_size = d_cellsize * len;
+ par->fontbuffer = dst;
}
- dst = ops->fontbuffer;
- memset(dst, 0, ops->fd_size);
+ dst = par->fontbuffer;
+ memset(dst, 0, par->fd_size);
- switch (ops->rotate) {
+ switch (par->rotate) {
case FB_ROTATE_UD:
for (i = len; i--; ) {
rotate_ud(src, dst, vc->vc_font.width,
@@ -96,19 +96,19 @@ finished:
return err;
}
-void fbcon_set_rotate(struct fbcon_ops *ops)
+void fbcon_set_rotate(struct fbcon_par *par)
{
- ops->rotate_font = fbcon_rotate_font;
+ par->rotate_font = fbcon_rotate_font;
- switch(ops->rotate) {
+ switch (par->rotate) {
case FB_ROTATE_CW:
- fbcon_rotate_cw(ops);
+ fbcon_rotate_cw(par);
break;
case FB_ROTATE_UD:
- fbcon_rotate_ud(ops);
+ fbcon_rotate_ud(par);
break;
case FB_ROTATE_CCW:
- fbcon_rotate_ccw(ops);
+ fbcon_rotate_ccw(par);
break;
}
}
--- a/drivers/video/fbdev/core/fbcon_rotate.h
+++ b/drivers/video/fbdev/core/fbcon_rotate.h
@@ -90,7 +90,7 @@ static inline void rotate_ccw(const char
}
}
-extern void fbcon_rotate_cw(struct fbcon_ops *ops);
-extern void fbcon_rotate_ud(struct fbcon_ops *ops);
-extern void fbcon_rotate_ccw(struct fbcon_ops *ops);
+extern void fbcon_rotate_cw(struct fbcon_par *par);
+extern void fbcon_rotate_ud(struct fbcon_par *par);
+extern void fbcon_rotate_ccw(struct fbcon_par *par);
#endif
--- a/drivers/video/fbdev/core/fbcon_ud.c
+++ b/drivers/video/fbdev/core/fbcon_ud.c
@@ -48,10 +48,10 @@ static void ud_update_attr(u8 *dst, u8 *
static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy,
int sx, int dy, int dx, int height, int width)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
struct fb_copyarea area;
- u32 vyres = GETVYRES(ops->p, info);
- u32 vxres = GETVXRES(ops->p, info);
+ u32 vyres = GETVYRES(par->p, info);
+ u32 vxres = GETVXRES(par->p, info);
area.sy = vyres - ((sy + height) * vc->vc_font.height);
area.sx = vxres - ((sx + width) * vc->vc_font.width);
@@ -66,10 +66,10 @@ static void ud_bmove(struct vc_data *vc,
static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy,
int sx, int height, int width, int fg, int bg)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
struct fb_fillrect region;
- u32 vyres = GETVYRES(ops->p, info);
- u32 vxres = GETVXRES(ops->p, info);
+ u32 vyres = GETVYRES(par->p, info);
+ u32 vxres = GETVXRES(par->p, info);
region.color = bg;
region.dy = vyres - ((sy + height) * vc->vc_font.height);
@@ -86,13 +86,13 @@ static inline void ud_putcs_aligned(stru
u32 d_pitch, u32 s_pitch, u32 cellsize,
struct fb_image *image, u8 *buf, u8 *dst)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
u32 idx = vc->vc_font.width >> 3;
u8 *src;
while (cnt--) {
- src = ops->fontbuffer + (scr_readw(s--) & charmask)*cellsize;
+ src = par->fontbuffer + (scr_readw(s--) & charmask) * cellsize;
if (attr) {
ud_update_attr(buf, src, attr, vc);
@@ -119,7 +119,7 @@ static inline void ud_putcs_unaligned(st
struct fb_image *image, u8 *buf,
u8 *dst)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
u32 shift_low = 0, mod = vc->vc_font.width % 8;
u32 shift_high = 8;
@@ -127,7 +127,7 @@ static inline void ud_putcs_unaligned(st
u8 *src;
while (cnt--) {
- src = ops->fontbuffer + (scr_readw(s--) & charmask)*cellsize;
+ src = par->fontbuffer + (scr_readw(s--) & charmask) * cellsize;
if (attr) {
ud_update_attr(buf, src, attr, vc);
@@ -152,7 +152,7 @@ static void ud_putcs(struct vc_data *vc,
int fg, int bg)
{
struct fb_image image;
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
u32 width = (vc->vc_font.width + 7)/8;
u32 cellsize = width * vc->vc_font.height;
u32 maxcnt = info->pixmap.size/cellsize;
@@ -161,10 +161,10 @@ static void ud_putcs(struct vc_data *vc,
u32 mod = vc->vc_font.width % 8, cnt, pitch, size;
u32 attribute = get_attribute(info, scr_readw(s));
u8 *dst, *buf = NULL;
- u32 vyres = GETVYRES(ops->p, info);
- u32 vxres = GETVXRES(ops->p, info);
+ u32 vyres = GETVYRES(par->p, info);
+ u32 vxres = GETVXRES(par->p, info);
- if (!ops->fontbuffer)
+ if (!par->fontbuffer)
return;
image.fg_color = fg;
@@ -251,29 +251,29 @@ static void ud_cursor(struct vc_data *vc
int fg, int bg)
{
struct fb_cursor cursor;
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
int w = (vc->vc_font.width + 7) >> 3, c;
- int y = real_y(ops->p, vc->state.y);
+ int y = real_y(par->p, vc->state.y);
int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
int err = 1, dx, dy;
char *src;
- u32 vyres = GETVYRES(ops->p, info);
- u32 vxres = GETVXRES(ops->p, info);
+ u32 vyres = GETVYRES(par->p, info);
+ u32 vxres = GETVXRES(par->p, info);
- if (!ops->fontbuffer)
+ if (!par->fontbuffer)
return;
cursor.set = 0;
c = scr_readw((u16 *) vc->vc_pos);
attribute = get_attribute(info, c);
- src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.height));
+ src = par->fontbuffer + ((c & charmask) * (w * vc->vc_font.height));
- if (ops->cursor_state.image.data != src ||
- ops->cursor_reset) {
- ops->cursor_state.image.data = src;
- cursor.set |= FB_CUR_SETIMAGE;
+ if (par->cursor_state.image.data != src ||
+ par->cursor_reset) {
+ par->cursor_state.image.data = src;
+ cursor.set |= FB_CUR_SETIMAGE;
}
if (attribute) {
@@ -282,49 +282,49 @@ static void ud_cursor(struct vc_data *vc
dst = kmalloc_array(w, vc->vc_font.height, GFP_ATOMIC);
if (!dst)
return;
- kfree(ops->cursor_data);
- ops->cursor_data = dst;
+ kfree(par->cursor_data);
+ par->cursor_data = dst;
ud_update_attr(dst, src, attribute, vc);
src = dst;
}
- if (ops->cursor_state.image.fg_color != fg ||
- ops->cursor_state.image.bg_color != bg ||
- ops->cursor_reset) {
- ops->cursor_state.image.fg_color = fg;
- ops->cursor_state.image.bg_color = bg;
+ if (par->cursor_state.image.fg_color != fg ||
+ par->cursor_state.image.bg_color != bg ||
+ par->cursor_reset) {
+ par->cursor_state.image.fg_color = fg;
+ par->cursor_state.image.bg_color = bg;
cursor.set |= FB_CUR_SETCMAP;
}
- if (ops->cursor_state.image.height != vc->vc_font.height ||
- ops->cursor_state.image.width != vc->vc_font.width ||
- ops->cursor_reset) {
- ops->cursor_state.image.height = vc->vc_font.height;
- ops->cursor_state.image.width = vc->vc_font.width;
+ if (par->cursor_state.image.height != vc->vc_font.height ||
+ par->cursor_state.image.width != vc->vc_font.width ||
+ par->cursor_reset) {
+ par->cursor_state.image.height = vc->vc_font.height;
+ par->cursor_state.image.width = vc->vc_font.width;
cursor.set |= FB_CUR_SETSIZE;
}
dy = vyres - ((y * vc->vc_font.height) + vc->vc_font.height);
dx = vxres - ((vc->state.x * vc->vc_font.width) + vc->vc_font.width);
- if (ops->cursor_state.image.dx != dx ||
- ops->cursor_state.image.dy != dy ||
- ops->cursor_reset) {
- ops->cursor_state.image.dx = dx;
- ops->cursor_state.image.dy = dy;
+ if (par->cursor_state.image.dx != dx ||
+ par->cursor_state.image.dy != dy ||
+ par->cursor_reset) {
+ par->cursor_state.image.dx = dx;
+ par->cursor_state.image.dy = dy;
cursor.set |= FB_CUR_SETPOS;
}
- if (ops->cursor_state.hot.x || ops->cursor_state.hot.y ||
- ops->cursor_reset) {
- ops->cursor_state.hot.x = cursor.hot.y = 0;
+ if (par->cursor_state.hot.x || par->cursor_state.hot.y ||
+ par->cursor_reset) {
+ par->cursor_state.hot.x = cursor.hot.y = 0;
cursor.set |= FB_CUR_SETHOT;
}
if (cursor.set & FB_CUR_SETSIZE ||
- vc->vc_cursor_type != ops->p->cursor_shape ||
- ops->cursor_state.mask == NULL ||
- ops->cursor_reset) {
+ vc->vc_cursor_type != par->p->cursor_shape ||
+ par->cursor_state.mask == NULL ||
+ par->cursor_reset) {
char *mask = kmalloc_array(w, vc->vc_font.height, GFP_ATOMIC);
int cur_height, size, i = 0;
u8 msk = 0xff;
@@ -332,13 +332,13 @@ static void ud_cursor(struct vc_data *vc
if (!mask)
return;
- kfree(ops->cursor_state.mask);
- ops->cursor_state.mask = mask;
+ kfree(par->cursor_state.mask);
+ par->cursor_state.mask = mask;
- ops->p->cursor_shape = vc->vc_cursor_type;
+ par->p->cursor_shape = vc->vc_cursor_type;
cursor.set |= FB_CUR_SETSHAPE;
- switch (CUR_SIZE(ops->p->cursor_shape)) {
+ switch (CUR_SIZE(par->p->cursor_shape)) {
case CUR_NONE:
cur_height = 0;
break;
@@ -371,19 +371,19 @@ static void ud_cursor(struct vc_data *vc
mask[i++] = ~msk;
}
- ops->cursor_state.enable = enable && !use_sw;
+ par->cursor_state.enable = enable && !use_sw;
cursor.image.data = src;
- cursor.image.fg_color = ops->cursor_state.image.fg_color;
- cursor.image.bg_color = ops->cursor_state.image.bg_color;
- cursor.image.dx = ops->cursor_state.image.dx;
- cursor.image.dy = ops->cursor_state.image.dy;
- cursor.image.height = ops->cursor_state.image.height;
- cursor.image.width = ops->cursor_state.image.width;
- cursor.hot.x = ops->cursor_state.hot.x;
- cursor.hot.y = ops->cursor_state.hot.y;
- cursor.mask = ops->cursor_state.mask;
- cursor.enable = ops->cursor_state.enable;
+ cursor.image.fg_color = par->cursor_state.image.fg_color;
+ cursor.image.bg_color = par->cursor_state.image.bg_color;
+ cursor.image.dx = par->cursor_state.image.dx;
+ cursor.image.dy = par->cursor_state.image.dy;
+ cursor.image.height = par->cursor_state.image.height;
+ cursor.image.width = par->cursor_state.image.width;
+ cursor.hot.x = par->cursor_state.hot.x;
+ cursor.hot.y = par->cursor_state.hot.y;
+ cursor.mask = par->cursor_state.mask;
+ cursor.enable = par->cursor_state.enable;
cursor.image.depth = 1;
cursor.rop = ROP_XOR;
@@ -393,36 +393,36 @@ static void ud_cursor(struct vc_data *vc
if (err)
soft_cursor(info, &cursor);
- ops->cursor_reset = 0;
+ par->cursor_reset = 0;
}
static int ud_update_start(struct fb_info *info)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
int xoffset, yoffset;
- u32 vyres = GETVYRES(ops->p, info);
- u32 vxres = GETVXRES(ops->p, info);
+ u32 vyres = GETVYRES(par->p, info);
+ u32 vxres = GETVXRES(par->p, info);
int err;
- xoffset = vxres - info->var.xres - ops->var.xoffset;
- yoffset = vyres - info->var.yres - ops->var.yoffset;
+ xoffset = vxres - info->var.xres - par->var.xoffset;
+ yoffset = vyres - info->var.yres - par->var.yoffset;
if (yoffset < 0)
yoffset += vyres;
- ops->var.xoffset = xoffset;
- ops->var.yoffset = yoffset;
- err = fb_pan_display(info, &ops->var);
- ops->var.xoffset = info->var.xoffset;
- ops->var.yoffset = info->var.yoffset;
- ops->var.vmode = info->var.vmode;
+ par->var.xoffset = xoffset;
+ par->var.yoffset = yoffset;
+ err = fb_pan_display(info, &par->var);
+ par->var.xoffset = info->var.xoffset;
+ par->var.yoffset = info->var.yoffset;
+ par->var.vmode = info->var.vmode;
return err;
}
-void fbcon_rotate_ud(struct fbcon_ops *ops)
+void fbcon_rotate_ud(struct fbcon_par *par)
{
- ops->bmove = ud_bmove;
- ops->clear = ud_clear;
- ops->putcs = ud_putcs;
- ops->clear_margins = ud_clear_margins;
- ops->cursor = ud_cursor;
- ops->update_start = ud_update_start;
+ par->bmove = ud_bmove;
+ par->clear = ud_clear;
+ par->putcs = ud_putcs;
+ par->clear_margins = ud_clear_margins;
+ par->cursor = ud_cursor;
+ par->update_start = ud_update_start;
}
--- a/drivers/video/fbdev/core/softcursor.c
+++ b/drivers/video/fbdev/core/softcursor.c
@@ -21,7 +21,7 @@
int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
unsigned int scan_align = info->pixmap.scan_align - 1;
unsigned int buf_align = info->pixmap.buf_align - 1;
unsigned int i, size, dsize, s_pitch, d_pitch;
@@ -34,19 +34,19 @@ int soft_cursor(struct fb_info *info, st
s_pitch = (cursor->image.width + 7) >> 3;
dsize = s_pitch * cursor->image.height;
- if (dsize + sizeof(struct fb_image) != ops->cursor_size) {
- kfree(ops->cursor_src);
- ops->cursor_size = dsize + sizeof(struct fb_image);
-
- ops->cursor_src = kmalloc(ops->cursor_size, GFP_ATOMIC);
- if (!ops->cursor_src) {
- ops->cursor_size = 0;
+ if (dsize + sizeof(struct fb_image) != par->cursor_size) {
+ kfree(par->cursor_src);
+ par->cursor_size = dsize + sizeof(struct fb_image);
+
+ par->cursor_src = kmalloc(par->cursor_size, GFP_ATOMIC);
+ if (!par->cursor_src) {
+ par->cursor_size = 0;
return -ENOMEM;
}
}
- src = ops->cursor_src + sizeof(struct fb_image);
- image = (struct fb_image *)ops->cursor_src;
+ src = par->cursor_src + sizeof(struct fb_image);
+ image = (struct fb_image *)par->cursor_src;
*image = cursor->image;
d_pitch = (s_pitch + scan_align) & ~scan_align;
--- a/drivers/video/fbdev/core/tileblit.c
+++ b/drivers/video/fbdev/core/tileblit.c
@@ -151,34 +151,34 @@ static void tile_cursor(struct vc_data *
static int tile_update_start(struct fb_info *info)
{
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
int err;
- err = fb_pan_display(info, &ops->var);
- ops->var.xoffset = info->var.xoffset;
- ops->var.yoffset = info->var.yoffset;
- ops->var.vmode = info->var.vmode;
+ err = fb_pan_display(info, &par->var);
+ par->var.xoffset = info->var.xoffset;
+ par->var.yoffset = info->var.yoffset;
+ par->var.vmode = info->var.vmode;
return err;
}
void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info)
{
struct fb_tilemap map;
- struct fbcon_ops *ops = info->fbcon_par;
+ struct fbcon_par *par = info->fbcon_par;
- ops->bmove = tile_bmove;
- ops->clear = tile_clear;
- ops->putcs = tile_putcs;
- ops->clear_margins = tile_clear_margins;
- ops->cursor = tile_cursor;
- ops->update_start = tile_update_start;
+ par->bmove = tile_bmove;
+ par->clear = tile_clear;
+ par->putcs = tile_putcs;
+ par->clear_margins = tile_clear_margins;
+ par->cursor = tile_cursor;
+ par->update_start = tile_update_start;
- if (ops->p) {
+ if (par->p) {
map.width = vc->vc_font.width;
map.height = vc->vc_font.height;
map.depth = 1;
map.length = vc->vc_font.charcount;
- map.data = ops->p->fontdata;
+ map.data = par->p->fontdata;
info->tileops->fb_settile(info, &map);
}
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 482/602] fbcon: Use correct type for vc_resize() return value
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (480 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 481/602] fbcon: Rename struct fbcon_ops to struct fbcon_par Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 483/602] rxrpc: Fix CPU time starvation in I/O thread Greg Kroah-Hartman
` (123 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jiacheng Yu, Thomas Zimmermann,
Helge Deller, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiacheng Yu <yujiacheng3@huawei.com>
[ Upstream commit 84202754fb1727dc3ee87f47104e4162ecc8ba3a ]
The return value of vc_resize() is int, but fbcon_set_disp() stores it
in an unsigned long variable. While the !ret check happens to work
correctly by coincidence (negative values become large positive values),
the types should match. Use int instead.
Eliminates the following W=3 warning:
drivers/video/fbdev/core/fbcon.c: In function 'fbcon_set_disp':
drivers/video/fbdev/core/fbcon.c:1494:14: warning: implicit conversion from 'int' to 'unsigned long' [-Wconversion]
Fixes: af0db3c1f898 ("fbdev: Fix vmalloc out-of-bounds write in fast_imageblit")
Cc: stable@vger.kernel.org # v6.17+
Signed-off-by: Jiacheng Yu <yujiacheng3@huawei.com>
Reviewed-by: Thomas Zimmermann <tzimmermann@suse.de>
Signed-off-by: Helge Deller <deller@gmx.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/video/fbdev/core/fbcon.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -1366,8 +1366,7 @@ static void fbcon_set_disp(struct fb_inf
struct vc_data **default_mode, *vc;
struct vc_data *svc;
struct fbcon_par *par = info->fbcon_par;
- int rows, cols;
- unsigned long ret = 0;
+ int rows, cols, ret;
p = &fb_display[unit];
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 483/602] rxrpc: Fix CPU time starvation in I/O thread
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (481 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 482/602] fbcon: Use correct type for vc_resize() return value Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 484/602] rxrpc: Dont need barrier for ->tx_bottom and ->acks_hard_ack Greg Kroah-Hartman
` (122 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Howells, Marc Dionne,
linux-afs, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <dhowells@redhat.com>
[ Upstream commit 9e3cccd176b5ec6ff78693287fb03097e453e69c ]
Starvation can happen in the rxrpc I/O thread because it goes back to the
top of the I/O loop after it does any one thing without trying to give any
other connection or call CPU time. Also, because it processes one call
packet at a time, it tries to do the retransmission loop after each ACK
without checking to see if there are other ACKs already in the queue that
can update the SACK state.
Fix this by:
(1) Add a received-packet queue on each call.
(2) Distribute packets from the master Rx queue to the individual call,
conn and error queues and 'poking' calls to add them to the attend
queue first thing in the I/O thread.
(3) Go through all the attention-seeking connections and calls before
going back to the top of the I/O thread. Each queue is extracted as a
whole and then gone through so that new additions to insert themselves
into the queue.
(4) Make the call event handler go through all the packets currently on
the call's rx_queue before transmitting and retransmitting DATA
packets.
(5) Drop the skb argument from the call event handler as this is now
replaced with the rx_queue. Instead, keep track of whether we
received a packet or an ACK for the tests that used to rely on that.
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
Link: https://patch.msgid.link/20241204074710.990092-14-dhowells@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: e66f8f32f501 ("rxrpc: Fix socket notification race")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/trace/events/rxrpc.h | 2
net/rxrpc/ar-internal.h | 10 +++-
net/rxrpc/call_accept.c | 2
net/rxrpc/call_event.c | 31 +++++++-----
net/rxrpc/call_object.c | 2
net/rxrpc/conn_client.c | 12 ++--
net/rxrpc/input.c | 2
net/rxrpc/io_thread.c | 104 +++++++++++++++++++++----------------------
net/rxrpc/peer_event.c | 2
9 files changed, 93 insertions(+), 74 deletions(-)
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -121,6 +121,7 @@
EM(rxrpc_call_poke_conn_abort, "Conn-abort") \
EM(rxrpc_call_poke_error, "Error") \
EM(rxrpc_call_poke_idle, "Idle") \
+ EM(rxrpc_call_poke_rx_packet, "Rx-packet") \
EM(rxrpc_call_poke_set_timeout, "Set-timo") \
EM(rxrpc_call_poke_start, "Start") \
EM(rxrpc_call_poke_timer, "Timer") \
@@ -139,6 +140,7 @@
EM(rxrpc_skb_new_error_report, "NEW error-rpt") \
EM(rxrpc_skb_new_jumbo_subpacket, "NEW jumbo-sub") \
EM(rxrpc_skb_new_unshared, "NEW unshared ") \
+ EM(rxrpc_skb_put_call_rx, "PUT call-rx ") \
EM(rxrpc_skb_put_conn_secured, "PUT conn-secd") \
EM(rxrpc_skb_put_conn_work, "PUT conn-work") \
EM(rxrpc_skb_put_error_report, "PUT error-rep") \
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -683,6 +683,7 @@ struct rxrpc_call {
/* Received data tracking */
struct sk_buff_head recvmsg_queue; /* Queue of packets ready for recvmsg() */
+ struct sk_buff_head rx_queue; /* Queue of packets for this call to receive */
struct sk_buff_head rx_oos_queue; /* Queue of out of sequence packets */
void *rx_dec_buffer; /* Decryption buffer */
unsigned short rx_dec_bsize; /* rx_dec_buffer size */
@@ -871,7 +872,7 @@ void rxrpc_propose_delay_ACK(struct rxrp
void rxrpc_shrink_call_tx_buffer(struct rxrpc_call *);
void rxrpc_resend(struct rxrpc_call *call, struct sk_buff *ack_skb);
-bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb);
+bool rxrpc_input_call_event(struct rxrpc_call *call);
/*
* call_object.c
@@ -1320,6 +1321,13 @@ static inline bool after_eq(u32 seq1, u3
return (s32)(seq1 - seq2) >= 0;
}
+static inline void rxrpc_queue_rx_call_packet(struct rxrpc_call *call, struct sk_buff *skb)
+{
+ rxrpc_get_skb(skb, rxrpc_skb_get_call_rx);
+ __skb_queue_tail(&call->rx_queue, skb);
+ rxrpc_poke_call(call, rxrpc_call_poke_rx_packet);
+}
+
/*
* debug tracing
*/
--- a/net/rxrpc/call_accept.c
+++ b/net/rxrpc/call_accept.c
@@ -415,7 +415,7 @@ bool rxrpc_new_incoming_call(struct rxrp
}
_leave(" = %p{%d}", call, call->debug_id);
- rxrpc_input_call_event(call, skb);
+ rxrpc_queue_rx_call_packet(call, skb);
rxrpc_put_call(call, rxrpc_call_put_input);
return true;
--- a/net/rxrpc/call_event.c
+++ b/net/rxrpc/call_event.c
@@ -315,10 +315,11 @@ static void rxrpc_send_initial_ping(stru
/*
* Handle retransmission and deferred ACK/abort generation.
*/
-bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
+bool rxrpc_input_call_event(struct rxrpc_call *call)
{
+ struct sk_buff *skb;
ktime_t now, t;
- bool resend = false;
+ bool resend = false, saw_ack = false;
s32 abort_code;
rxrpc_see_call(call, rxrpc_call_see_input);
@@ -328,9 +329,6 @@ bool rxrpc_input_call_event(struct rxrpc
call->debug_id, rxrpc_call_states[__rxrpc_call_state(call)],
call->events);
- if (__rxrpc_call_is_complete(call))
- goto out;
-
/* Handle abort request locklessly, vs rxrpc_propose_abort(). */
abort_code = smp_load_acquire(&call->send_abort);
if (abort_code) {
@@ -339,11 +337,20 @@ bool rxrpc_input_call_event(struct rxrpc
goto out;
}
- if (skb && skb->mark == RXRPC_SKB_MARK_ERROR)
- goto out;
+ while ((skb = __skb_dequeue(&call->rx_queue))) {
+ struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+
+ if (__rxrpc_call_is_complete(call) ||
+ skb->mark == RXRPC_SKB_MARK_ERROR) {
+ rxrpc_free_skb(skb, rxrpc_skb_put_call_rx);
+ goto out;
+ }
+
+ saw_ack |= sp->hdr.type == RXRPC_PACKET_TYPE_ACK;
- if (skb)
rxrpc_input_call_packet(call, skb);
+ rxrpc_free_skb(skb, rxrpc_skb_put_call_rx);
+ }
/* If we see our async-event poke, check for timeout trippage. */
now = ktime_get_real();
@@ -409,12 +416,8 @@ bool rxrpc_input_call_event(struct rxrpc
rxrpc_propose_ack_ping_for_keepalive);
}
- if (skb) {
- struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
-
- if (sp->hdr.type == RXRPC_PACKET_TYPE_ACK)
- rxrpc_congestion_degrade(call);
- }
+ if (saw_ack)
+ rxrpc_congestion_degrade(call);
if (test_and_clear_bit(RXRPC_CALL_EV_INITIAL_PING, &call->events))
rxrpc_send_initial_ping(call);
--- a/net/rxrpc/call_object.c
+++ b/net/rxrpc/call_object.c
@@ -147,6 +147,7 @@ struct rxrpc_call *rxrpc_alloc_call(stru
INIT_LIST_HEAD(&call->attend_link);
INIT_LIST_HEAD(&call->tx_sendmsg);
INIT_LIST_HEAD(&call->tx_buffer);
+ skb_queue_head_init(&call->rx_queue);
skb_queue_head_init(&call->recvmsg_queue);
skb_queue_head_init(&call->rx_oos_queue);
init_waitqueue_head(&call->waitq);
@@ -535,6 +536,7 @@ void rxrpc_get_call(struct rxrpc_call *c
static void rxrpc_cleanup_ring(struct rxrpc_call *call)
{
rxrpc_purge_queue(&call->recvmsg_queue);
+ rxrpc_purge_queue(&call->rx_queue);
rxrpc_purge_queue(&call->rx_oos_queue);
kfree(call->rx_dec_buffer);
}
--- a/net/rxrpc/conn_client.c
+++ b/net/rxrpc/conn_client.c
@@ -508,16 +508,18 @@ static void rxrpc_activate_channels(stru
void rxrpc_connect_client_calls(struct rxrpc_local *local)
{
struct rxrpc_call *call;
+ LIST_HEAD(new_client_calls);
- while ((call = list_first_entry_or_null(&local->new_client_calls,
- struct rxrpc_call, wait_link))
- ) {
+ spin_lock(&local->client_call_lock);
+ list_splice_tail_init(&local->new_client_calls, &new_client_calls);
+ spin_unlock(&local->client_call_lock);
+
+ while ((call = list_first_entry_or_null(&new_client_calls,
+ struct rxrpc_call, wait_link))) {
struct rxrpc_bundle *bundle = call->bundle;
- spin_lock(&local->client_call_lock);
list_move_tail(&call->wait_link, &bundle->waiting_calls);
rxrpc_see_call(call, rxrpc_call_see_waiting_call);
- spin_unlock(&local->client_call_lock);
if (rxrpc_bundle_has_space(bundle))
rxrpc_activate_channels(bundle);
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -1122,5 +1122,5 @@ void rxrpc_implicit_end_call(struct rxrp
break;
}
- rxrpc_input_call_event(call, skb);
+ rxrpc_input_call_event(call);
}
--- a/net/rxrpc/io_thread.c
+++ b/net/rxrpc/io_thread.c
@@ -318,7 +318,6 @@ static int rxrpc_input_packet_on_conn(st
struct rxrpc_channel *chan;
struct rxrpc_call *call = NULL;
unsigned int channel;
- bool ret;
if (sp->hdr.securityIndex != conn->security_ix)
return rxrpc_direct_abort(skb, rxrpc_eproto_wrong_security,
@@ -400,9 +399,9 @@ static int rxrpc_input_packet_on_conn(st
peer_srx, skb);
}
- ret = rxrpc_input_call_event(call, skb);
+ rxrpc_queue_rx_call_packet(call, skb);
rxrpc_put_call(call, rxrpc_call_put_input);
- return ret;
+ return true;
}
/*
@@ -419,6 +418,8 @@ int rxrpc_io_thread(void *data)
ktime_t now;
#endif
bool should_stop;
+ LIST_HEAD(conn_attend_q);
+ LIST_HEAD(call_attend_q);
complete(&local->io_thread_ready);
@@ -429,43 +430,25 @@ int rxrpc_io_thread(void *data)
for (;;) {
rxrpc_inc_stat(local->rxnet, stat_io_loop);
- /* Deal with connections that want immediate attention. */
- conn = list_first_entry_or_null(&local->conn_attend_q,
- struct rxrpc_connection,
- attend_link);
- if (conn) {
- spin_lock_bh(&local->lock);
- list_del_init(&conn->attend_link);
- spin_unlock_bh(&local->lock);
-
- rxrpc_input_conn_event(conn, NULL);
- rxrpc_put_connection(conn, rxrpc_conn_put_poke);
- continue;
+ /* Inject a delay into packets if requested. */
+#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
+ now = ktime_get_real();
+ while ((skb = skb_peek(&local->rx_delay_queue))) {
+ if (ktime_before(now, skb->tstamp))
+ break;
+ skb = skb_dequeue(&local->rx_delay_queue);
+ skb_queue_tail(&local->rx_queue, skb);
}
+#endif
- if (test_and_clear_bit(RXRPC_CLIENT_CONN_REAP_TIMER,
- &local->client_conn_flags))
- rxrpc_discard_expired_client_conns(local);
-
- /* Deal with calls that want immediate attention. */
- if ((call = list_first_entry_or_null(&local->call_attend_q,
- struct rxrpc_call,
- attend_link))) {
- spin_lock_bh(&local->lock);
- list_del_init(&call->attend_link);
- spin_unlock_bh(&local->lock);
-
- trace_rxrpc_call_poked(call);
- rxrpc_input_call_event(call, NULL);
- rxrpc_put_call(call, rxrpc_call_put_poke);
- continue;
+ if (!skb_queue_empty(&local->rx_queue)) {
+ spin_lock_irq(&local->rx_queue.lock);
+ skb_queue_splice_tail_init(&local->rx_queue, &rx_queue);
+ spin_unlock_irq(&local->rx_queue.lock);
}
- if (!list_empty(&local->new_client_calls))
- rxrpc_connect_client_calls(local);
-
- /* Process received packets and errors. */
- if ((skb = __skb_dequeue(&rx_queue))) {
+ /* Distribute packets and errors. */
+ while ((skb = __skb_dequeue(&rx_queue))) {
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
switch (skb->mark) {
case RXRPC_SKB_MARK_PACKET:
@@ -489,27 +472,46 @@ int rxrpc_io_thread(void *data)
rxrpc_free_skb(skb, rxrpc_skb_put_unknown);
break;
}
- continue;
}
- /* Inject a delay into packets if requested. */
-#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
- now = ktime_get_real();
- while ((skb = skb_peek(&local->rx_delay_queue))) {
- if (ktime_before(now, skb->tstamp))
- break;
- skb = skb_dequeue(&local->rx_delay_queue);
- skb_queue_tail(&local->rx_queue, skb);
+ /* Deal with connections that want immediate attention. */
+ spin_lock_bh(&local->lock);
+ list_splice_tail_init(&local->conn_attend_q, &conn_attend_q);
+ spin_unlock_bh(&local->lock);
+
+ while ((conn = list_first_entry_or_null(&conn_attend_q,
+ struct rxrpc_connection,
+ attend_link))) {
+ spin_lock_bh(&local->lock);
+ list_del_init(&conn->attend_link);
+ spin_unlock_bh(&local->lock);
+ rxrpc_input_conn_event(conn, NULL);
+ rxrpc_put_connection(conn, rxrpc_conn_put_poke);
}
-#endif
- if (!skb_queue_empty(&local->rx_queue)) {
- spin_lock_irq(&local->rx_queue.lock);
- skb_queue_splice_tail_init(&local->rx_queue, &rx_queue);
- spin_unlock_irq(&local->rx_queue.lock);
- continue;
+ if (test_and_clear_bit(RXRPC_CLIENT_CONN_REAP_TIMER,
+ &local->client_conn_flags))
+ rxrpc_discard_expired_client_conns(local);
+
+ /* Deal with calls that want immediate attention. */
+ spin_lock_bh(&local->lock);
+ list_splice_tail_init(&local->call_attend_q, &call_attend_q);
+ spin_unlock_bh(&local->lock);
+
+ while ((call = list_first_entry_or_null(&call_attend_q,
+ struct rxrpc_call,
+ attend_link))) {
+ spin_lock_bh(&local->lock);
+ list_del_init(&call->attend_link);
+ spin_unlock_bh(&local->lock);
+ trace_rxrpc_call_poked(call);
+ rxrpc_input_call_event(call);
+ rxrpc_put_call(call, rxrpc_call_put_poke);
}
+ if (!list_empty(&local->new_client_calls))
+ rxrpc_connect_client_calls(local);
+
set_current_state(TASK_INTERRUPTIBLE);
should_stop = kthread_should_stop();
if (!skb_queue_empty(&local->rx_queue) ||
--- a/net/rxrpc/peer_event.c
+++ b/net/rxrpc/peer_event.c
@@ -216,7 +216,7 @@ static void rxrpc_distribute_error(struc
rxrpc_see_call(call, rxrpc_call_see_distribute_error);
rxrpc_set_call_completion(call, compl, 0, -err);
- rxrpc_input_call_event(call, skb);
+ rxrpc_input_call_event(call);
spin_lock(&peer->lock);
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 484/602] rxrpc: Dont need barrier for ->tx_bottom and ->acks_hard_ack
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (482 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 483/602] rxrpc: Fix CPU time starvation in I/O thread Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 485/602] rxrpc: Use irq-disabling spinlocks between app and I/O thread Greg Kroah-Hartman
` (121 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Howells, Marc Dionne,
linux-afs, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <dhowells@redhat.com>
[ Upstream commit 6396b48ac0a77165f9c2c40ab03d6c8188c89739 ]
We don't need a barrier for the ->tx_bottom value (which indicates the
lowest sequence still in the transmission queue) and the ->acks_hard_ack
value (which tracks the DATA packets hard-ack'd by the latest ACK packet
received and thus indicates which DATA packets can now be discarded) as the
app thread doesn't use either value as a reference to memory to access.
Rather, the app thread merely uses these as a guide to how much space is
available in the transmission queue
Change the code to use READ/WRITE_ONCE() instead.
Also, change rxrpc_check_tx_space() to use the same value for tx_bottom
throughout.
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
Link: https://patch.msgid.link/20241204074710.990092-18-dhowells@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: e66f8f32f501 ("rxrpc: Fix socket notification race")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/rxrpc/sendmsg.c | 8 +++++---
net/rxrpc/txbuf.c | 4 ++--
2 files changed, 7 insertions(+), 5 deletions(-)
--- a/net/rxrpc/sendmsg.c
+++ b/net/rxrpc/sendmsg.c
@@ -93,9 +93,11 @@ no_wait:
*/
static bool rxrpc_check_tx_space(struct rxrpc_call *call, rxrpc_seq_t *_tx_win)
{
+ rxrpc_seq_t tx_bottom = READ_ONCE(call->tx_bottom);
+
if (_tx_win)
- *_tx_win = call->tx_bottom;
- return call->tx_prepared - call->tx_bottom < 256;
+ *_tx_win = tx_bottom;
+ return call->tx_prepared - tx_bottom < 256;
}
/*
@@ -137,7 +139,7 @@ static int rxrpc_wait_for_tx_window_wait
rtt = 2;
timeout = rtt;
- tx_start = smp_load_acquire(&call->acks_hard_ack);
+ tx_start = READ_ONCE(call->acks_hard_ack);
for (;;) {
set_current_state(TASK_UNINTERRUPTIBLE);
--- a/net/rxrpc/txbuf.c
+++ b/net/rxrpc/txbuf.c
@@ -216,14 +216,14 @@ void rxrpc_shrink_call_tx_buffer(struct
while ((txb = list_first_entry_or_null(&call->tx_buffer,
struct rxrpc_txbuf, call_link))) {
- hard_ack = smp_load_acquire(&call->acks_hard_ack);
+ hard_ack = call->acks_hard_ack;
if (before(hard_ack, txb->seq))
break;
if (txb->seq != call->tx_bottom + 1)
rxrpc_see_txbuf(txb, rxrpc_txbuf_see_out_of_step);
ASSERTCMP(txb->seq, ==, call->tx_bottom + 1);
- smp_store_release(&call->tx_bottom, call->tx_bottom + 1);
+ WRITE_ONCE(call->tx_bottom, call->tx_bottom + 1);
list_del_rcu(&txb->call_link);
trace_rxrpc_txqueue(call, rxrpc_txqueue_dequeue);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 485/602] rxrpc: Use irq-disabling spinlocks between app and I/O thread
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (483 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 484/602] rxrpc: Dont need barrier for ->tx_bottom and ->acks_hard_ack Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 486/602] rxrpc: Fix notification vs call-release vs recvmsg Greg Kroah-Hartman
` (120 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Howells, Marc Dionne,
linux-afs, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <dhowells@redhat.com>
[ Upstream commit a2ea9a9072607c2fd6442bd1ffb4dbdbf882aed7 ]
Where a spinlock is used by both the application thread and the I/O thread,
use irq-disabling locking so that an interrupt taken on the app thread
doesn't also slow down the I/O thread.
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: e66f8f32f501 ("rxrpc: Fix socket notification race")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/rxrpc/af_rxrpc.c | 4 ++--
net/rxrpc/call_accept.c | 20 ++++++++++----------
net/rxrpc/call_object.c | 14 +++++++-------
net/rxrpc/conn_client.c | 12 ++++++------
net/rxrpc/conn_event.c | 14 +++++++-------
net/rxrpc/conn_object.c | 8 ++++----
net/rxrpc/input.c | 5 +----
net/rxrpc/io_thread.c | 8 ++++----
net/rxrpc/peer_event.c | 8 ++++----
net/rxrpc/peer_object.c | 1 +
net/rxrpc/recvmsg.c | 22 +++++++++++-----------
net/rxrpc/security.c | 4 ++--
12 files changed, 59 insertions(+), 61 deletions(-)
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -408,9 +408,9 @@ void rxrpc_kernel_shutdown_call(struct s
/* Make sure we're not going to call back into a kernel service */
if (call->notify_rx) {
- spin_lock(&call->notify_lock);
+ spin_lock_irq(&call->notify_lock);
call->notify_rx = rxrpc_dummy_notify_rx;
- spin_unlock(&call->notify_lock);
+ spin_unlock_irq(&call->notify_lock);
}
}
mutex_unlock(&call->user_mutex);
--- a/net/rxrpc/call_accept.c
+++ b/net/rxrpc/call_accept.c
@@ -189,8 +189,8 @@ void rxrpc_discard_prealloc(struct rxrpc
/* Make sure that there aren't any incoming calls in progress before we
* clear the preallocation buffers.
*/
- spin_lock(&rx->incoming_lock);
- spin_unlock(&rx->incoming_lock);
+ spin_lock_irq(&rx->incoming_lock);
+ spin_unlock_irq(&rx->incoming_lock);
head = b->peer_backlog_head;
tail = b->peer_backlog_tail;
@@ -349,7 +349,7 @@ bool rxrpc_new_incoming_call(struct rxrp
if (sp->hdr.type != RXRPC_PACKET_TYPE_DATA)
return rxrpc_protocol_error(skb, rxrpc_eproto_no_service_call);
- read_lock(&local->services_lock);
+ read_lock_irq(&local->services_lock);
/* Weed out packets to services we're not offering. Packets that would
* begin a call are explicitly rejected and the rest are just
@@ -406,12 +406,12 @@ bool rxrpc_new_incoming_call(struct rxrp
spin_unlock(&conn->state_lock);
spin_unlock(&rx->incoming_lock);
- read_unlock(&local->services_lock);
+ read_unlock_irq(&local->services_lock);
if (hlist_unhashed(&call->error_link)) {
- spin_lock(&call->peer->lock);
+ spin_lock_irq(&call->peer->lock);
hlist_add_head(&call->error_link, &call->peer->error_targets);
- spin_unlock(&call->peer->lock);
+ spin_unlock_irq(&call->peer->lock);
}
_leave(" = %p{%d}", call, call->debug_id);
@@ -420,20 +420,20 @@ bool rxrpc_new_incoming_call(struct rxrp
return true;
unsupported_service:
- read_unlock(&local->services_lock);
+ read_unlock_irq(&local->services_lock);
return rxrpc_direct_abort(skb, rxrpc_abort_service_not_offered,
RX_INVALID_OPERATION, -EOPNOTSUPP);
unsupported_security:
- read_unlock(&local->services_lock);
+ read_unlock_irq(&local->services_lock);
return rxrpc_direct_abort(skb, rxrpc_abort_service_not_offered,
RX_INVALID_OPERATION, -EKEYREJECTED);
no_call:
spin_unlock(&rx->incoming_lock);
- read_unlock(&local->services_lock);
+ read_unlock_irq(&local->services_lock);
_leave(" = f [%u]", skb->mark);
return false;
discard:
- read_unlock(&local->services_lock);
+ read_unlock_irq(&local->services_lock);
return true;
}
--- a/net/rxrpc/call_object.c
+++ b/net/rxrpc/call_object.c
@@ -48,7 +48,7 @@ void rxrpc_poke_call(struct rxrpc_call *
bool busy;
if (!test_bit(RXRPC_CALL_DISCONNECTED, &call->flags)) {
- spin_lock_bh(&local->lock);
+ spin_lock_irq(&local->lock);
busy = !list_empty(&call->attend_link);
trace_rxrpc_poke_call(call, busy, what);
if (!busy && !rxrpc_try_get_call(call, rxrpc_call_get_poke))
@@ -56,7 +56,7 @@ void rxrpc_poke_call(struct rxrpc_call *
if (!busy) {
list_add_tail(&call->attend_link, &local->call_attend_q);
}
- spin_unlock_bh(&local->lock);
+ spin_unlock_irq(&local->lock);
if (!busy)
rxrpc_wake_up_io_thread(local);
}
@@ -303,9 +303,9 @@ static int rxrpc_connect_call(struct rxr
trace_rxrpc_client(NULL, -1, rxrpc_client_queue_new_call);
rxrpc_get_call(call, rxrpc_call_get_io_thread);
- spin_lock(&local->client_call_lock);
+ spin_lock_irq(&local->client_call_lock);
list_add_tail(&call->wait_link, &local->new_client_calls);
- spin_unlock(&local->client_call_lock);
+ spin_unlock_irq(&local->client_call_lock);
rxrpc_wake_up_io_thread(local);
return 0;
@@ -435,7 +435,7 @@ error_attached_to_socket:
/*
* Set up an incoming call. call->conn points to the connection.
- * This is called in BH context and isn't allowed to fail.
+ * This is called with interrupts disabled and isn't allowed to fail.
*/
void rxrpc_incoming_call(struct rxrpc_sock *rx,
struct rxrpc_call *call,
@@ -560,7 +560,7 @@ void rxrpc_release_call(struct rxrpc_soc
rxrpc_put_call_slot(call);
/* Make sure we don't get any more notifications */
- spin_lock(&rx->recvmsg_lock);
+ spin_lock_irq(&rx->recvmsg_lock);
if (!list_empty(&call->recvmsg_link)) {
_debug("unlinking once-pending call %p { e=%lx f=%lx }",
@@ -573,7 +573,7 @@ void rxrpc_release_call(struct rxrpc_soc
call->recvmsg_link.next = NULL;
call->recvmsg_link.prev = NULL;
- spin_unlock(&rx->recvmsg_lock);
+ spin_unlock_irq(&rx->recvmsg_lock);
if (put)
rxrpc_put_call(call, rxrpc_call_put_unnotify);
--- a/net/rxrpc/conn_client.c
+++ b/net/rxrpc/conn_client.c
@@ -510,9 +510,9 @@ void rxrpc_connect_client_calls(struct r
struct rxrpc_call *call;
LIST_HEAD(new_client_calls);
- spin_lock(&local->client_call_lock);
+ spin_lock_irq(&local->client_call_lock);
list_splice_tail_init(&local->new_client_calls, &new_client_calls);
- spin_unlock(&local->client_call_lock);
+ spin_unlock_irq(&local->client_call_lock);
while ((call = list_first_entry_or_null(&new_client_calls,
struct rxrpc_call, wait_link))) {
@@ -547,9 +547,9 @@ void rxrpc_expose_client_call(struct rxr
set_bit(RXRPC_CONN_DONT_REUSE, &conn->flags);
trace_rxrpc_client(conn, channel, rxrpc_client_exposed);
- spin_lock(&call->peer->lock);
+ spin_lock_irq(&call->peer->lock);
hlist_add_head(&call->error_link, &call->peer->error_targets);
- spin_unlock(&call->peer->lock);
+ spin_unlock_irq(&call->peer->lock);
}
}
@@ -590,9 +590,9 @@ void rxrpc_disconnect_client_call(struct
ASSERTCMP(call->call_id, ==, 0);
ASSERT(!test_bit(RXRPC_CALL_EXPOSED, &call->flags));
/* May still be on ->new_client_calls. */
- spin_lock(&local->client_call_lock);
+ spin_lock_irq(&local->client_call_lock);
list_del_init(&call->wait_link);
- spin_unlock(&local->client_call_lock);
+ spin_unlock_irq(&local->client_call_lock);
return;
}
--- a/net/rxrpc/conn_event.c
+++ b/net/rxrpc/conn_event.c
@@ -26,7 +26,7 @@ static bool rxrpc_set_conn_aborted(struc
bool aborted = false;
if (conn->state != RXRPC_CONN_ABORTED) {
- spin_lock(&conn->state_lock);
+ spin_lock_irq(&conn->state_lock);
if (conn->state != RXRPC_CONN_ABORTED) {
conn->abort_code = abort_code;
conn->error = err;
@@ -37,7 +37,7 @@ static bool rxrpc_set_conn_aborted(struc
set_bit(RXRPC_CONN_EV_ABORT_CALLS, &conn->events);
aborted = true;
}
- spin_unlock(&conn->state_lock);
+ spin_unlock_irq(&conn->state_lock);
}
return aborted;
@@ -268,12 +268,12 @@ static int rxrpc_process_event(struct rx
return conn->security->respond_to_challenge(conn, skb);
case RXRPC_PACKET_TYPE_RESPONSE:
- spin_lock(&conn->state_lock);
+ spin_lock_irq(&conn->state_lock);
if (conn->state != RXRPC_CONN_SERVICE_CHALLENGING) {
- spin_unlock(&conn->state_lock);
+ spin_unlock_irq(&conn->state_lock);
return 0;
}
- spin_unlock(&conn->state_lock);
+ spin_unlock_irq(&conn->state_lock);
ret = rxrpc_verify_response(conn, skb);
if (ret < 0)
@@ -284,12 +284,12 @@ static int rxrpc_process_event(struct rx
if (ret < 0)
return ret;
- spin_lock(&conn->state_lock);
+ spin_lock_irq(&conn->state_lock);
if (conn->state == RXRPC_CONN_SERVICE_CHALLENGING) {
conn->state = RXRPC_CONN_SERVICE;
secured = true;
}
- spin_unlock(&conn->state_lock);
+ spin_unlock_irq(&conn->state_lock);
if (secured) {
/* Offload call state flipping to the I/O thread. As
--- a/net/rxrpc/conn_object.c
+++ b/net/rxrpc/conn_object.c
@@ -31,13 +31,13 @@ void rxrpc_poke_conn(struct rxrpc_connec
if (WARN_ON_ONCE(!local))
return;
- spin_lock_bh(&local->lock);
+ spin_lock_irq(&local->lock);
busy = !list_empty(&conn->attend_link);
if (!busy) {
rxrpc_get_connection(conn, why);
list_add_tail(&conn->attend_link, &local->conn_attend_q);
}
- spin_unlock_bh(&local->lock);
+ spin_unlock_irq(&local->lock);
rxrpc_wake_up_io_thread(local);
}
@@ -197,9 +197,9 @@ void rxrpc_disconnect_call(struct rxrpc_
call->peer->cong_ssthresh = call->cong_ssthresh;
if (!hlist_unhashed(&call->error_link)) {
- spin_lock(&call->peer->lock);
+ spin_lock_irq(&call->peer->lock);
hlist_del_init(&call->error_link);
- spin_unlock(&call->peer->lock);
+ spin_unlock_irq(&call->peer->lock);
}
if (rxrpc_is_client_call(call)) {
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -365,7 +365,7 @@ static void rxrpc_input_queue_data(struc
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
bool last = sp->hdr.flags & RXRPC_LAST_PACKET;
- __skb_queue_tail(&call->recvmsg_queue, skb);
+ skb_queue_tail(&call->recvmsg_queue, skb);
rxrpc_input_update_ack_window(call, window, wtop);
trace_rxrpc_receive(call, last ? why + 1 : why, sp->hdr.serial, sp->hdr.seq);
if (last)
@@ -442,7 +442,6 @@ static void rxrpc_input_data_one(struct
rxrpc_get_skb(skb, rxrpc_skb_get_to_recvmsg);
- spin_lock(&call->recvmsg_queue.lock);
rxrpc_input_queue_data(call, skb, window, wtop, rxrpc_receive_queue);
*_notify = true;
@@ -464,8 +463,6 @@ static void rxrpc_input_data_one(struct
rxrpc_receive_queue_oos);
}
- spin_unlock(&call->recvmsg_queue.lock);
-
call->ackr_sack_base = sack;
} else {
unsigned int slot;
--- a/net/rxrpc/io_thread.c
+++ b/net/rxrpc/io_thread.c
@@ -475,9 +475,9 @@ int rxrpc_io_thread(void *data)
}
/* Deal with connections that want immediate attention. */
- spin_lock_bh(&local->lock);
+ spin_lock_irq(&local->lock);
list_splice_tail_init(&local->conn_attend_q, &conn_attend_q);
- spin_unlock_bh(&local->lock);
+ spin_unlock_irq(&local->lock);
while ((conn = list_first_entry_or_null(&conn_attend_q,
struct rxrpc_connection,
@@ -494,9 +494,9 @@ int rxrpc_io_thread(void *data)
rxrpc_discard_expired_client_conns(local);
/* Deal with calls that want immediate attention. */
- spin_lock_bh(&local->lock);
+ spin_lock_irq(&local->lock);
list_splice_tail_init(&local->call_attend_q, &call_attend_q);
- spin_unlock_bh(&local->lock);
+ spin_unlock_irq(&local->lock);
while ((call = list_first_entry_or_null(&call_attend_q,
struct rxrpc_call,
--- a/net/rxrpc/peer_event.c
+++ b/net/rxrpc/peer_event.c
@@ -205,23 +205,23 @@ static void rxrpc_distribute_error(struc
struct rxrpc_call *call;
HLIST_HEAD(error_targets);
- spin_lock(&peer->lock);
+ spin_lock_irq(&peer->lock);
hlist_move_list(&peer->error_targets, &error_targets);
while (!hlist_empty(&error_targets)) {
call = hlist_entry(error_targets.first,
struct rxrpc_call, error_link);
hlist_del_init(&call->error_link);
- spin_unlock(&peer->lock);
+ spin_unlock_irq(&peer->lock);
rxrpc_see_call(call, rxrpc_call_see_distribute_error);
rxrpc_set_call_completion(call, compl, 0, -err);
rxrpc_input_call_event(call);
- spin_lock(&peer->lock);
+ spin_lock_irq(&peer->lock);
}
- spin_unlock(&peer->lock);
+ spin_unlock_irq(&peer->lock);
}
/*
--- a/net/rxrpc/peer_object.c
+++ b/net/rxrpc/peer_object.c
@@ -304,6 +304,7 @@ static void rxrpc_free_peer(struct rxrpc
* Set up a new incoming peer. There shouldn't be any other matching peers
* since we've already done a search in the list from the non-reentrant context
* (the data_ready handler) that is the only place we can add new peers.
+ * Called with interrupts disabled.
*/
void rxrpc_new_incoming_peer(struct rxrpc_local *local, struct rxrpc_peer *peer)
{
--- a/net/rxrpc/recvmsg.c
+++ b/net/rxrpc/recvmsg.c
@@ -36,16 +36,16 @@ void rxrpc_notify_socket(struct rxrpc_ca
sk = &rx->sk;
if (rx && sk->sk_state < RXRPC_CLOSE) {
if (call->notify_rx) {
- spin_lock(&call->notify_lock);
+ spin_lock_irq(&call->notify_lock);
call->notify_rx(sk, call, call->user_call_ID);
- spin_unlock(&call->notify_lock);
+ spin_unlock_irq(&call->notify_lock);
} else {
- spin_lock(&rx->recvmsg_lock);
+ spin_lock_irq(&rx->recvmsg_lock);
if (list_empty(&call->recvmsg_link)) {
rxrpc_get_call(call, rxrpc_call_get_notify_socket);
list_add_tail(&call->recvmsg_link, &rx->recvmsg_q);
}
- spin_unlock(&rx->recvmsg_lock);
+ spin_unlock_irq(&rx->recvmsg_lock);
if (!sock_flag(sk, SOCK_DEAD)) {
_debug("call %ps", sk->sk_data_ready);
@@ -379,14 +379,14 @@ try_again:
* We also want to weed out calls that got requeued whilst we were
* shovelling data out.
*/
- spin_lock(&rx->recvmsg_lock);
+ spin_lock_irq(&rx->recvmsg_lock);
l = rx->recvmsg_q.next;
call = list_entry(l, struct rxrpc_call, recvmsg_link);
if (!rxrpc_call_is_complete(call) &&
skb_queue_empty(&call->recvmsg_queue)) {
list_del_init(&call->recvmsg_link);
- spin_unlock(&rx->recvmsg_lock);
+ spin_unlock_irq(&rx->recvmsg_lock);
release_sock(&rx->sk);
trace_rxrpc_recvmsg(call->debug_id, rxrpc_recvmsg_unqueue, 0);
rxrpc_put_call(call, rxrpc_call_put_recvmsg);
@@ -407,7 +407,7 @@ try_again:
list_del_init(&call->recvmsg_link);
else
rxrpc_get_call(call, rxrpc_call_get_recvmsg);
- spin_unlock(&rx->recvmsg_lock);
+ spin_unlock_irq(&rx->recvmsg_lock);
call_debug_id = call->debug_id;
trace_rxrpc_recvmsg(call_debug_id, rxrpc_recvmsg_dequeue, 0);
@@ -502,17 +502,17 @@ error_unlock_call:
error_requeue_call:
if (!(flags & MSG_PEEK)) {
- spin_lock(&rx->recvmsg_lock);
+ spin_lock_irq(&rx->recvmsg_lock);
if (list_empty(&call->recvmsg_link)) {
list_add(&call->recvmsg_link, &rx->recvmsg_q);
rxrpc_see_call(call, rxrpc_call_see_recvmsg_requeue);
- spin_unlock(&rx->recvmsg_lock);
+ spin_unlock_irq(&rx->recvmsg_lock);
} else if (list_is_first(&call->recvmsg_link, &rx->recvmsg_q)) {
- spin_unlock(&rx->recvmsg_lock);
+ spin_unlock_irq(&rx->recvmsg_lock);
rxrpc_put_call(call, rxrpc_call_see_recvmsg_requeue_first);
} else {
list_move(&call->recvmsg_link, &rx->recvmsg_q);
- spin_unlock(&rx->recvmsg_lock);
+ spin_unlock_irq(&rx->recvmsg_lock);
rxrpc_put_call(call, rxrpc_call_see_recvmsg_requeue_move);
}
trace_rxrpc_recvmsg(call_debug_id, rxrpc_recvmsg_requeue, 0);
--- a/net/rxrpc/security.c
+++ b/net/rxrpc/security.c
@@ -114,10 +114,10 @@ found:
if (conn->state == RXRPC_CONN_CLIENT_UNSECURED) {
ret = conn->security->init_connection_security(conn, token);
if (ret == 0) {
- spin_lock(&conn->state_lock);
+ spin_lock_irq(&conn->state_lock);
if (conn->state == RXRPC_CONN_CLIENT_UNSECURED)
conn->state = RXRPC_CONN_CLIENT;
- spin_unlock(&conn->state_lock);
+ spin_unlock_irq(&conn->state_lock);
}
}
mutex_unlock(&conn->security_lock);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 486/602] rxrpc: Fix notification vs call-release vs recvmsg
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (484 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 485/602] rxrpc: Use irq-disabling spinlocks between app and I/O thread Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 487/602] rxrpc: Fix socket notification race Greg Kroah-Hartman
` (119 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Howells, Jeffrey Altman,
Marc Dionne, Junvyyang, Tencent Zhuque Lab, LePremierHomme,
Simon Horman, linux-afs, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <dhowells@redhat.com>
[ Upstream commit 2fd895842d49c23137ae48252dd211e5d6d8a3ed ]
When a call is released, rxrpc takes the spinlock and removes it from
->recvmsg_q in an effort to prevent racing recvmsg() invocations from
seeing the same call. Now, rxrpc_recvmsg() only takes the spinlock when
actually removing a call from the queue; it doesn't, however, take it in
the lead up to that when it checks to see if the queue is empty. It *does*
hold the socket lock, which prevents a recvmsg/recvmsg race - but this
doesn't prevent sendmsg from ending the call because sendmsg() drops the
socket lock and relies on the call->user_mutex.
Fix this by firstly removing the bit in rxrpc_release_call() that dequeues
the released call and, instead, rely on recvmsg() to simply discard
released calls (done in a preceding fix).
Secondly, rxrpc_notify_socket() is abandoned if the call is already marked
as released rather than trying to be clever by setting both pointers in
call->recvmsg_link to NULL to trick list_empty(). This isn't perfect and
can still race, resulting in a released call on the queue, but recvmsg()
will now clean that up.
Fixes: 17926a79320a ("[AF_RXRPC]: Provide secure RxRPC sockets for use by userspace and kernel both")
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Jeffrey Altman <jaltman@auristor.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Junvyyang, Tencent Zhuque Lab <zhuque@tencent.com>
cc: LePremierHomme <kwqcheii@proton.me>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
Link: https://patch.msgid.link/20250717074350.3767366-4-dhowells@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: e66f8f32f501 ("rxrpc: Fix socket notification race")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/trace/events/rxrpc.h | 3 ++-
net/rxrpc/call_object.c | 28 ++++++++++++----------------
net/rxrpc/recvmsg.c | 4 ++++
3 files changed, 18 insertions(+), 17 deletions(-)
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -278,10 +278,10 @@
EM(rxrpc_call_put_poke, "PUT poke ") \
EM(rxrpc_call_put_recvmsg, "PUT recvmsg ") \
EM(rxrpc_call_put_recvmsg_peek_nowait, "PUT peek-nwt") \
+ EM(rxrpc_call_put_release_recvmsg_q, "PUT rls-rcmq") \
EM(rxrpc_call_put_release_sock, "PUT rls-sock") \
EM(rxrpc_call_put_release_sock_tba, "PUT rls-sk-a") \
EM(rxrpc_call_put_sendmsg, "PUT sendmsg ") \
- EM(rxrpc_call_put_unnotify, "PUT unnotify") \
EM(rxrpc_call_put_userid_exists, "PUT u-exists") \
EM(rxrpc_call_put_userid, "PUT user-id ") \
EM(rxrpc_call_see_accept, "SEE accept ") \
@@ -294,6 +294,7 @@
EM(rxrpc_call_see_disconnected, "SEE disconn ") \
EM(rxrpc_call_see_distribute_error, "SEE dist-err") \
EM(rxrpc_call_see_input, "SEE input ") \
+ EM(rxrpc_call_see_notify_released, "SEE nfy-rlsd") \
EM(rxrpc_call_see_recvmsg, "SEE recvmsg ") \
EM(rxrpc_call_see_recvmsg_requeue, "SEE recv-rqu") \
EM(rxrpc_call_see_recvmsg_requeue_first, "SEE recv-rqF") \
--- a/net/rxrpc/call_object.c
+++ b/net/rxrpc/call_object.c
@@ -547,7 +547,7 @@ static void rxrpc_cleanup_ring(struct rx
void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
{
struct rxrpc_connection *conn = call->conn;
- bool put = false, putu = false;
+ bool putu = false;
_enter("{%d,%d}", call->debug_id, refcount_read(&call->ref));
@@ -559,23 +559,13 @@ void rxrpc_release_call(struct rxrpc_soc
rxrpc_put_call_slot(call);
- /* Make sure we don't get any more notifications */
+ /* Note that at this point, the call may still be on or may have been
+ * added back on to the socket receive queue. recvmsg() must discard
+ * released calls. The CALL_RELEASED flag should prevent further
+ * notifications.
+ */
spin_lock_irq(&rx->recvmsg_lock);
-
- if (!list_empty(&call->recvmsg_link)) {
- _debug("unlinking once-pending call %p { e=%lx f=%lx }",
- call, call->events, call->flags);
- list_del(&call->recvmsg_link);
- put = true;
- }
-
- /* list_empty() must return false in rxrpc_notify_socket() */
- call->recvmsg_link.next = NULL;
- call->recvmsg_link.prev = NULL;
-
spin_unlock_irq(&rx->recvmsg_lock);
- if (put)
- rxrpc_put_call(call, rxrpc_call_put_unnotify);
write_lock(&rx->call_lock);
@@ -624,6 +614,12 @@ void rxrpc_release_calls_on_socket(struc
rxrpc_put_call(call, rxrpc_call_put_release_sock);
}
+ while ((call = list_first_entry_or_null(&rx->recvmsg_q,
+ struct rxrpc_call, recvmsg_link))) {
+ list_del_init(&call->recvmsg_link);
+ rxrpc_put_call(call, rxrpc_call_put_release_recvmsg_q);
+ }
+
_leave("");
}
--- a/net/rxrpc/recvmsg.c
+++ b/net/rxrpc/recvmsg.c
@@ -29,6 +29,10 @@ void rxrpc_notify_socket(struct rxrpc_ca
if (!list_empty(&call->recvmsg_link))
return;
+ if (test_bit(RXRPC_CALL_RELEASED, &call->flags)) {
+ rxrpc_see_call(call, rxrpc_call_see_notify_released);
+ return;
+ }
rcu_read_lock();
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 487/602] rxrpc: Fix socket notification race
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (485 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 486/602] rxrpc: Fix notification vs call-release vs recvmsg Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 488/602] tipc: restrict socket queue dumps in enqueue tracepoints Greg Kroah-Hartman
` (118 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Howells, Marc Dionne,
Jeffrey Altman, Simon Horman, linux-afs, stable, Jakub Kicinski,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <dhowells@redhat.com>
[ Upstream commit e66f8f32f50116670dbbee5bc9e692cd2cd0c8f8 ]
There's a race between rxrpc_recvmsg() and rxrpc_notify_socket(), whereby
the latter's attempt to avoid disabling interrupts and taking the socket's
recvmsg_lock if the call is already queued may happen simultaneously with
the former's discarding of a call that has nothing queued.
Fix this by removing the shortcut. Note that this only affects userspace's
use of AF_RXRPC; the AFS filesystem driver doesn't use the socket queue.
Fixes: 248f219cb8bc ("rxrpc: Rewrite the data and ack handling code")
Link: https://sashiko.dev/#/patchset/20260616155749.2125907-1-dhowells%40redhat.com
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Jeffrey Altman <jaltman@auristor.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: stable@kernel.org
Link: https://patch.msgid.link/20260624163819.3017002-10-dhowells@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/rxrpc/recvmsg.c | 2 --
1 file changed, 2 deletions(-)
--- a/net/rxrpc/recvmsg.c
+++ b/net/rxrpc/recvmsg.c
@@ -27,8 +27,6 @@ void rxrpc_notify_socket(struct rxrpc_ca
_enter("%d", call->debug_id);
- if (!list_empty(&call->recvmsg_link))
- return;
if (test_bit(RXRPC_CALL_RELEASED, &call->flags)) {
rxrpc_see_call(call, rxrpc_call_see_notify_released);
return;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 488/602] tipc: restrict socket queue dumps in enqueue tracepoints
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (486 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 487/602] rxrpc: Fix socket notification race Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 489/602] vduse: Use fixed 4KB bounce pages for non-4KB page size Greg Kroah-Hartman
` (117 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Li Xiasong, Tung Nguyen,
Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li Xiasong <lixiasong1@huawei.com>
[ Upstream commit acd7df8d955480a6f6e5bb809da67b1500cc3cf4 ]
tipc_sk_enqueue() runs with sk->sk_lock.slock held while the socket is
owned by user context. The spinlock protects the backlog queue in this
path, but it does not serialize against the socket owner consuming or
purging sk_receive_queue.
KASAN reported:
CPU: 14 UID: 0 PID: 1050 Comm: tipc3 Not tainted 7.1.0-rc6+ #126 PREEMPT(lazy)
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
Call Trace:
<TASK>
dump_stack_lvl+0x76/0xa0 lib/dump_stack.c:123
print_report+0xce/0x5b0 mm/kasan/report.c:482
kasan_report+0xc6/0x100 mm/kasan/report.c:597
__asan_report_load4_noabort+0x14/0x30 mm/kasan/report_generic.c:380
tipc_skb_dump+0x1327/0x16f0 net/tipc/trace.c:73
tipc_list_dump+0x208/0x2e0 net/tipc/trace.c:187
tipc_sk_dump+0xaf6/0xd60 net/tipc/socket.c:3996
trace_event_raw_event_tipc_sk_class+0x312/0x5a0 net/tipc/trace.h:188
tipc_sk_rcv+0xb1d/0x1d50 net/tipc/socket.c:2497
tipc_node_xmit+0x1c3/0x1440 net/tipc/node.c:1689
__tipc_sendmsg+0x97a/0x1440 net/tipc/socket.c:1512
tipc_sendmsg+0x52/0x80 net/tipc/socket.c:1400
sock_sendmsg+0x2f6/0x3e0 net/socket.c:825
splice_to_socket+0x7f9/0x1010 fs/splice.c:884
do_splice+0xe21/0x2330 fs/splice.c:936
__do_splice+0x153/0x260 fs/splice.c:1431
__x64_sys_splice+0x150/0x230 fs/splice.c:1616
x64_sys_call+0xeb5/0x2790 arch/x86/entry/syscall_64.c:41
do_syscall_64+0xf3/0x620 arch/x86/entry/syscall_64.c:63
entry_SYSCALL_64_after_hwframe+0x76/0x7e arch/x86/entry/entry_64.S:130
RIP: 0033:0x71624e8aafe2
Code: 08 0f 85 71 3a ff ff 49 89 fb 48 89 f0 48 89 d7 48 89 ce 4c 89 c2 4d 89 ca 4c 8b 44 24 08 4c 8b 4c 24 10 4c 89 5c 24 08 0f 05 <c3> 66 2e 0f 1f 84 00 00 00 00 00 66 2e 0f 1f 84 00 00 00 00 00 66
RSP: 002b:0000716157ffed68 EFLAGS: 00000246 ORIG_RAX: 0000000000000113
RAX: ffffffffffffffda RBX: 0000716157fff6c0 RCX: 000071624e8aafe2
RDX: 000000000000005f RSI: 0000000000000000 RDI: 0000000000000066
RBP: 0000716157ffed90 R08: 0000000000008000 R09: 0000000000000001
R10: 0000000000000000 R11: 0000000000000246 R12: ffffffffffffff00
R13: 0000000000000021 R14: 0000000000000000 R15: 00007fff89799c40
</TASK>
The TIPC_DUMP_ALL tracepoints in tipc_sk_enqueue() also dump
sk_receive_queue and can therefore dereference skbs that the socket
owner has already dequeued or freed. Restrict these dumps to
TIPC_DUMP_SK_BKLGQ, which matches the queue protected by the held
spinlock.
Keep the change limited to the enqueue path, where the unsafe queue dump
is reachable while the socket is owned by user context.
Fixes: 01e661ebfbad ("tipc: add trace_events for tipc socket")
Cc: stable@vger.kernel.org
Signed-off-by: Li Xiasong <lixiasong1@huawei.com>
Reviewed-by: Tung Nguyen <tung.quang.nguyen@est.tech>
Link: https://patch.msgid.link/20260611135647.3666727-1-lixiasong1@huawei.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/tipc/socket.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -2456,17 +2456,17 @@ static void tipc_sk_enqueue(struct sk_bu
atomic_set(dcnt, 0);
lim = rcvbuf_limit(sk, skb) + atomic_read(dcnt);
if (likely(!sk_add_backlog(sk, skb, lim))) {
- trace_tipc_sk_overlimit1(sk, skb, TIPC_DUMP_ALL,
+ trace_tipc_sk_overlimit1(sk, skb, TIPC_DUMP_SK_BKLGQ,
"bklg & rcvq >90% allocated!");
continue;
}
- trace_tipc_sk_dump(sk, skb, TIPC_DUMP_ALL, "err_overload!");
+ trace_tipc_sk_dump(sk, skb, TIPC_DUMP_SK_BKLGQ, "err_overload!");
/* Overload => reject message back to sender */
onode = tipc_own_addr(sock_net(sk));
atomic_inc(&sk->sk_drops);
if (tipc_msg_reverse(onode, &skb, TIPC_ERR_OVERLOAD)) {
- trace_tipc_sk_rej_msg(sk, skb, TIPC_DUMP_ALL,
+ trace_tipc_sk_rej_msg(sk, skb, TIPC_DUMP_SK_BKLGQ,
"@sk_enqueue!");
__skb_queue_tail(xmitq, skb);
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 489/602] vduse: Use fixed 4KB bounce pages for non-4KB page size
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (487 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 488/602] tipc: restrict socket queue dumps in enqueue tracepoints Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 490/602] vduse: remove unused vaddr parameter of vduse_domain_free_coherent Greg Kroah-Hartman
` (116 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sheng Zhao, Michael S. Tsirkin,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sheng Zhao <sheng.zhao@bytedance.com>
[ Upstream commit 3fc3068e7247c94dec08e93fea422a1bb649bfe5 ]
The allocation granularity of bounce pages is PAGE_SIZE. This may cause
even small IO requests to occupy an entire bounce page exclusively. The
kind of memory waste will be more significant when PAGE_SIZE is larger
than 4KB (e.g. arm64 with 64KB pages).
So, optimize it by using fixed 4KB bounce maps and iova allocation
granularity. A single IO request occupies at least a 4KB bounce page
instead of the entire memory page of PAGE_SIZE.
Signed-off-by: Sheng Zhao <sheng.zhao@bytedance.com>
Message-Id: <20250925113516.60305-1-sheng.zhao@bytedance.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Stable-dep-of: 9c1523803445 ("VDUSE: avoid leaking information to userspace")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/vdpa/vdpa_user/iova_domain.c | 130 +++++++++++++++++++++++------------
drivers/vdpa/vdpa_user/iova_domain.h | 5 +
2 files changed, 94 insertions(+), 41 deletions(-)
--- a/drivers/vdpa/vdpa_user/iova_domain.c
+++ b/drivers/vdpa/vdpa_user/iova_domain.c
@@ -103,19 +103,38 @@ void vduse_domain_clear_map(struct vduse
static int vduse_domain_map_bounce_page(struct vduse_iova_domain *domain,
u64 iova, u64 size, u64 paddr)
{
- struct vduse_bounce_map *map;
+ struct vduse_bounce_map *map, *head_map;
+ struct page *tmp_page;
u64 last = iova + size - 1;
while (iova <= last) {
- map = &domain->bounce_maps[iova >> PAGE_SHIFT];
+ /*
+ * When PAGE_SIZE is larger than 4KB, multiple adjacent bounce_maps will
+ * point to the same memory page of PAGE_SIZE. Since bounce_maps originate
+ * from IO requests, we may not be able to guarantee that the orig_phys
+ * values of all IO requests within the same 64KB memory page are contiguous.
+ * Therefore, we need to store them separately.
+ *
+ * Bounce pages are allocated on demand. As a result, it may occur that
+ * multiple bounce pages corresponding to the same 64KB memory page attempt
+ * to allocate memory simultaneously, so we use cmpxchg to handle this
+ * concurrency.
+ */
+ map = &domain->bounce_maps[iova >> BOUNCE_MAP_SHIFT];
if (!map->bounce_page) {
- map->bounce_page = alloc_page(GFP_ATOMIC);
- if (!map->bounce_page)
- return -ENOMEM;
+ head_map = &domain->bounce_maps[(iova & PAGE_MASK) >> BOUNCE_MAP_SHIFT];
+ if (!head_map->bounce_page) {
+ tmp_page = alloc_page(GFP_ATOMIC);
+ if (!tmp_page)
+ return -ENOMEM;
+ if (cmpxchg(&head_map->bounce_page, NULL, tmp_page))
+ __free_page(tmp_page);
+ }
+ map->bounce_page = head_map->bounce_page;
}
map->orig_phys = paddr;
- paddr += PAGE_SIZE;
- iova += PAGE_SIZE;
+ paddr += BOUNCE_MAP_SIZE;
+ iova += BOUNCE_MAP_SIZE;
}
return 0;
}
@@ -127,12 +146,17 @@ static void vduse_domain_unmap_bounce_pa
u64 last = iova + size - 1;
while (iova <= last) {
- map = &domain->bounce_maps[iova >> PAGE_SHIFT];
+ map = &domain->bounce_maps[iova >> BOUNCE_MAP_SHIFT];
map->orig_phys = INVALID_PHYS_ADDR;
- iova += PAGE_SIZE;
+ iova += BOUNCE_MAP_SIZE;
}
}
+static unsigned int offset_in_bounce_page(dma_addr_t addr)
+{
+ return (addr & ~BOUNCE_MAP_MASK);
+}
+
static void do_bounce(phys_addr_t orig, void *addr, size_t size,
enum dma_data_direction dir)
{
@@ -163,7 +187,7 @@ static void vduse_domain_bounce(struct v
{
struct vduse_bounce_map *map;
struct page *page;
- unsigned int offset;
+ unsigned int offset, head_offset;
void *addr;
size_t sz;
@@ -171,9 +195,10 @@ static void vduse_domain_bounce(struct v
return;
while (size) {
- map = &domain->bounce_maps[iova >> PAGE_SHIFT];
- offset = offset_in_page(iova);
- sz = min_t(size_t, PAGE_SIZE - offset, size);
+ map = &domain->bounce_maps[iova >> BOUNCE_MAP_SHIFT];
+ head_offset = offset_in_page(iova);
+ offset = offset_in_bounce_page(iova);
+ sz = min_t(size_t, BOUNCE_MAP_SIZE - offset, size);
if (WARN_ON(!map->bounce_page ||
map->orig_phys == INVALID_PHYS_ADDR))
@@ -183,7 +208,7 @@ static void vduse_domain_bounce(struct v
map->user_bounce_page : map->bounce_page;
addr = kmap_local_page(page);
- do_bounce(map->orig_phys + offset, addr + offset, sz, dir);
+ do_bounce(map->orig_phys + offset, addr + head_offset, sz, dir);
kunmap_local(addr);
size -= sz;
iova += sz;
@@ -218,7 +243,7 @@ vduse_domain_get_bounce_page(struct vdus
struct page *page = NULL;
read_lock(&domain->bounce_lock);
- map = &domain->bounce_maps[iova >> PAGE_SHIFT];
+ map = &domain->bounce_maps[iova >> BOUNCE_MAP_SHIFT];
if (domain->user_bounce_pages || !map->bounce_page)
goto out;
@@ -236,7 +261,7 @@ vduse_domain_free_kernel_bounce_pages(st
struct vduse_bounce_map *map;
unsigned long pfn, bounce_pfns;
- bounce_pfns = domain->bounce_size >> PAGE_SHIFT;
+ bounce_pfns = domain->bounce_size >> BOUNCE_MAP_SHIFT;
for (pfn = 0; pfn < bounce_pfns; pfn++) {
map = &domain->bounce_maps[pfn];
@@ -246,7 +271,8 @@ vduse_domain_free_kernel_bounce_pages(st
if (!map->bounce_page)
continue;
- __free_page(map->bounce_page);
+ if (!((pfn << BOUNCE_MAP_SHIFT) & ~PAGE_MASK))
+ __free_page(map->bounce_page);
map->bounce_page = NULL;
}
}
@@ -254,8 +280,12 @@ vduse_domain_free_kernel_bounce_pages(st
int vduse_domain_add_user_bounce_pages(struct vduse_iova_domain *domain,
struct page **pages, int count)
{
- struct vduse_bounce_map *map;
- int i, ret;
+ struct vduse_bounce_map *map, *head_map;
+ int i, j, ret;
+ int inner_pages = PAGE_SIZE / BOUNCE_MAP_SIZE;
+ int bounce_pfns = domain->bounce_size >> BOUNCE_MAP_SHIFT;
+ struct page *head_page = NULL;
+ bool need_copy;
/* Now we don't support partial mapping */
if (count != (domain->bounce_size >> PAGE_SHIFT))
@@ -267,16 +297,23 @@ int vduse_domain_add_user_bounce_pages(s
goto out;
for (i = 0; i < count; i++) {
- map = &domain->bounce_maps[i];
- if (map->bounce_page) {
+ need_copy = false;
+ head_map = &domain->bounce_maps[(i * inner_pages)];
+ head_page = head_map->bounce_page;
+ for (j = 0; j < inner_pages; j++) {
+ if ((i * inner_pages + j) >= bounce_pfns)
+ break;
+ map = &domain->bounce_maps[(i * inner_pages + j)];
/* Copy kernel page to user page if it's in use */
- if (map->orig_phys != INVALID_PHYS_ADDR)
- memcpy_to_page(pages[i], 0,
- page_address(map->bounce_page),
- PAGE_SIZE);
+ if ((head_page) && (map->orig_phys != INVALID_PHYS_ADDR))
+ need_copy = true;
+ map->user_bounce_page = pages[i];
}
- map->user_bounce_page = pages[i];
get_page(pages[i]);
+ if ((head_page) && (need_copy))
+ memcpy_to_page(pages[i], 0,
+ page_address(head_page),
+ PAGE_SIZE);
}
domain->user_bounce_pages = true;
ret = 0;
@@ -288,8 +325,12 @@ out:
void vduse_domain_remove_user_bounce_pages(struct vduse_iova_domain *domain)
{
- struct vduse_bounce_map *map;
- unsigned long i, count;
+ struct vduse_bounce_map *map, *head_map;
+ unsigned long i, j, count;
+ int inner_pages = PAGE_SIZE / BOUNCE_MAP_SIZE;
+ int bounce_pfns = domain->bounce_size >> BOUNCE_MAP_SHIFT;
+ struct page *head_page = NULL;
+ bool need_copy;
write_lock(&domain->bounce_lock);
if (!domain->user_bounce_pages)
@@ -297,20 +338,27 @@ void vduse_domain_remove_user_bounce_pag
count = domain->bounce_size >> PAGE_SHIFT;
for (i = 0; i < count; i++) {
- struct page *page = NULL;
-
- map = &domain->bounce_maps[i];
- if (WARN_ON(!map->user_bounce_page))
+ need_copy = false;
+ head_map = &domain->bounce_maps[(i * inner_pages)];
+ if (WARN_ON(!head_map->user_bounce_page))
continue;
+ head_page = head_map->user_bounce_page;
- /* Copy user page to kernel page if it's in use */
- if (map->orig_phys != INVALID_PHYS_ADDR) {
- page = map->bounce_page;
- memcpy_from_page(page_address(page),
- map->user_bounce_page, 0, PAGE_SIZE);
+ for (j = 0; j < inner_pages; j++) {
+ if ((i * inner_pages + j) >= bounce_pfns)
+ break;
+ map = &domain->bounce_maps[(i * inner_pages + j)];
+ if (WARN_ON(!map->user_bounce_page))
+ continue;
+ /* Copy user page to kernel page if it's in use */
+ if ((map->orig_phys != INVALID_PHYS_ADDR) && (head_map->bounce_page))
+ need_copy = true;
+ map->user_bounce_page = NULL;
}
- put_page(map->user_bounce_page);
- map->user_bounce_page = NULL;
+ if (need_copy)
+ memcpy_from_page(page_address(head_map->bounce_page),
+ head_page, 0, PAGE_SIZE);
+ put_page(head_page);
}
domain->user_bounce_pages = false;
out:
@@ -581,7 +629,7 @@ vduse_domain_create(unsigned long iova_l
unsigned long pfn, bounce_pfns;
int ret;
- bounce_pfns = PAGE_ALIGN(bounce_size) >> PAGE_SHIFT;
+ bounce_pfns = PAGE_ALIGN(bounce_size) >> BOUNCE_MAP_SHIFT;
if (iova_limit <= bounce_size)
return NULL;
@@ -613,7 +661,7 @@ vduse_domain_create(unsigned long iova_l
rwlock_init(&domain->bounce_lock);
spin_lock_init(&domain->iotlb_lock);
init_iova_domain(&domain->stream_iovad,
- PAGE_SIZE, IOVA_START_PFN);
+ BOUNCE_MAP_SIZE, IOVA_START_PFN);
ret = iova_domain_init_rcaches(&domain->stream_iovad);
if (ret)
goto err_iovad_stream;
--- a/drivers/vdpa/vdpa_user/iova_domain.h
+++ b/drivers/vdpa/vdpa_user/iova_domain.h
@@ -19,6 +19,11 @@
#define INVALID_PHYS_ADDR (~(phys_addr_t)0)
+#define BOUNCE_MAP_SHIFT 12
+#define BOUNCE_MAP_SIZE (1 << BOUNCE_MAP_SHIFT)
+#define BOUNCE_MAP_MASK (~(BOUNCE_MAP_SIZE - 1))
+#define BOUNCE_MAP_ALIGN(addr) (((addr) + BOUNCE_MAP_SIZE - 1) & ~(BOUNCE_MAP_SIZE - 1))
+
struct vduse_bounce_map {
struct page *bounce_page;
struct page *user_bounce_page;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 490/602] vduse: remove unused vaddr parameter of vduse_domain_free_coherent
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (488 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 489/602] vduse: Use fixed 4KB bounce pages for non-4KB page size Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 491/602] vduse: take out allocations from vduse_dev_alloc_coherent Greg Kroah-Hartman
` (115 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Eugenio Pérez,
Michael S. Tsirkin, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eugenio Pérez <eperezma@redhat.com>
[ Upstream commit 766e1749c0ef6a09651be9b8a8283d508c322b58 ]
We will modify the function in next patches so let's clean it first.
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260119143306.1818855-9-eperezma@redhat.com>
Stable-dep-of: 9c1523803445 ("VDUSE: avoid leaking information to userspace")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/vdpa/vdpa_user/iova_domain.c | 3 +--
drivers/vdpa/vdpa_user/iova_domain.h | 3 +--
drivers/vdpa/vdpa_user/vduse_dev.c | 2 +-
3 files changed, 3 insertions(+), 5 deletions(-)
--- a/drivers/vdpa/vdpa_user/iova_domain.c
+++ b/drivers/vdpa/vdpa_user/iova_domain.c
@@ -528,8 +528,7 @@ err:
}
void vduse_domain_free_coherent(struct vduse_iova_domain *domain, size_t size,
- void *vaddr, dma_addr_t dma_addr,
- unsigned long attrs)
+ dma_addr_t dma_addr, unsigned long attrs)
{
struct iova_domain *iovad = &domain->consistent_iovad;
struct vhost_iotlb_map *map;
--- a/drivers/vdpa/vdpa_user/iova_domain.h
+++ b/drivers/vdpa/vdpa_user/iova_domain.h
@@ -72,8 +72,7 @@ void *vduse_domain_alloc_coherent(struct
gfp_t flag, unsigned long attrs);
void vduse_domain_free_coherent(struct vduse_iova_domain *domain, size_t size,
- void *vaddr, dma_addr_t dma_addr,
- unsigned long attrs);
+ dma_addr_t dma_addr, unsigned long attrs);
void vduse_domain_reset_bounce_map(struct vduse_iova_domain *domain);
--- a/drivers/vdpa/vdpa_user/vduse_dev.c
+++ b/drivers/vdpa/vdpa_user/vduse_dev.c
@@ -904,7 +904,7 @@ static void vduse_dev_free_coherent(stru
struct vduse_dev *vdev = dev_to_vduse(dev);
struct vduse_iova_domain *domain = vdev->domain;
- vduse_domain_free_coherent(domain, size, vaddr, dma_addr, attrs);
+ vduse_domain_free_coherent(domain, size, dma_addr, attrs);
}
static size_t vduse_dev_max_mapping_size(struct device *dev)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 491/602] vduse: take out allocations from vduse_dev_alloc_coherent
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (489 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 490/602] vduse: remove unused vaddr parameter of vduse_domain_free_coherent Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 492/602] VDUSE: avoid leaking information to userspace Greg Kroah-Hartman
` (114 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jason Wang, Eugenio Pérez,
Michael S. Tsirkin, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eugenio Pérez <eperezma@redhat.com>
[ Upstream commit 489d76520612abf9a4ede4344349105406c91a73 ]
The function vduse_dev_alloc_coherent will be called under rwlock in
next patches. Make it out of the lock to avoid increasing its fail
rate.
Acked-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-Id: <20260119143306.1818855-10-eperezma@redhat.com>
Stable-dep-of: 9c1523803445 ("VDUSE: avoid leaking information to userspace")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/vdpa/vdpa_user/iova_domain.c | 24 +++++++-----------------
drivers/vdpa/vdpa_user/iova_domain.h | 5 ++---
drivers/vdpa/vdpa_user/vduse_dev.c | 14 ++++++++++----
3 files changed, 19 insertions(+), 24 deletions(-)
--- a/drivers/vdpa/vdpa_user/iova_domain.c
+++ b/drivers/vdpa/vdpa_user/iova_domain.c
@@ -493,17 +493,15 @@ void vduse_domain_unmap_page(struct vdus
vduse_domain_free_iova(iovad, dma_addr, size);
}
-void *vduse_domain_alloc_coherent(struct vduse_iova_domain *domain,
- size_t size, dma_addr_t *dma_addr,
- gfp_t flag, unsigned long attrs)
+dma_addr_t vduse_domain_alloc_coherent(struct vduse_iova_domain *domain,
+ size_t size, void *orig)
{
struct iova_domain *iovad = &domain->consistent_iovad;
unsigned long limit = domain->iova_limit;
dma_addr_t iova = vduse_domain_alloc_iova(iovad, size, limit);
- void *orig = alloc_pages_exact(size, flag);
- if (!iova || !orig)
- goto err;
+ if (!iova)
+ return DMA_MAPPING_ERROR;
spin_lock(&domain->iotlb_lock);
if (vduse_iotlb_add_range(domain, (u64)iova, (u64)iova + size - 1,
@@ -514,17 +512,12 @@ void *vduse_domain_alloc_coherent(struct
}
spin_unlock(&domain->iotlb_lock);
- *dma_addr = iova;
+ return iova;
- return orig;
err:
- *dma_addr = DMA_MAPPING_ERROR;
- if (orig)
- free_pages_exact(orig, size);
- if (iova)
- vduse_domain_free_iova(iovad, iova, size);
+ vduse_domain_free_iova(iovad, iova, size);
- return NULL;
+ return DMA_MAPPING_ERROR;
}
void vduse_domain_free_coherent(struct vduse_iova_domain *domain, size_t size,
@@ -533,7 +526,6 @@ void vduse_domain_free_coherent(struct v
struct iova_domain *iovad = &domain->consistent_iovad;
struct vhost_iotlb_map *map;
struct vdpa_map_file *map_file;
- phys_addr_t pa;
spin_lock(&domain->iotlb_lock);
map = vhost_iotlb_itree_first(domain->iotlb, (u64)dma_addr,
@@ -545,12 +537,10 @@ void vduse_domain_free_coherent(struct v
map_file = (struct vdpa_map_file *)map->opaque;
fput(map_file->file);
kfree(map_file);
- pa = map->addr;
vhost_iotlb_map_free(domain->iotlb, map);
spin_unlock(&domain->iotlb_lock);
vduse_domain_free_iova(iovad, dma_addr, size);
- free_pages_exact(phys_to_virt(pa), size);
}
static vm_fault_t vduse_domain_mmap_fault(struct vm_fault *vmf)
--- a/drivers/vdpa/vdpa_user/iova_domain.h
+++ b/drivers/vdpa/vdpa_user/iova_domain.h
@@ -67,9 +67,8 @@ void vduse_domain_unmap_page(struct vdus
dma_addr_t dma_addr, size_t size,
enum dma_data_direction dir, unsigned long attrs);
-void *vduse_domain_alloc_coherent(struct vduse_iova_domain *domain,
- size_t size, dma_addr_t *dma_addr,
- gfp_t flag, unsigned long attrs);
+dma_addr_t vduse_domain_alloc_coherent(struct vduse_iova_domain *domain,
+ size_t size, void *orig);
void vduse_domain_free_coherent(struct vduse_iova_domain *domain, size_t size,
dma_addr_t dma_addr, unsigned long attrs);
--- a/drivers/vdpa/vdpa_user/vduse_dev.c
+++ b/drivers/vdpa/vdpa_user/vduse_dev.c
@@ -883,18 +883,23 @@ static void *vduse_dev_alloc_coherent(st
{
struct vduse_dev *vdev = dev_to_vduse(dev);
struct vduse_iova_domain *domain = vdev->domain;
- unsigned long iova;
void *addr;
*dma_addr = DMA_MAPPING_ERROR;
- addr = vduse_domain_alloc_coherent(domain, size,
- (dma_addr_t *)&iova, flag, attrs);
+
+ addr = alloc_pages_exact(size, flag);
if (!addr)
return NULL;
- *dma_addr = (dma_addr_t)iova;
+ *dma_addr = vduse_domain_alloc_coherent(domain, size, addr);
+ if (*dma_addr == DMA_MAPPING_ERROR)
+ goto err;
return addr;
+
+err:
+ free_pages_exact(addr, size);
+ return NULL;
}
static void vduse_dev_free_coherent(struct device *dev, size_t size,
@@ -905,6 +910,7 @@ static void vduse_dev_free_coherent(stru
struct vduse_iova_domain *domain = vdev->domain;
vduse_domain_free_coherent(domain, size, dma_addr, attrs);
+ free_pages_exact(vaddr, size);
}
static size_t vduse_dev_max_mapping_size(struct device *dev)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 492/602] VDUSE: avoid leaking information to userspace
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (490 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 491/602] vduse: take out allocations from vduse_dev_alloc_coherent Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 493/602] octeontx2: Annotate mmio regions as __iomem Greg Kroah-Hartman
` (113 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jason Wang, Xie Yongji,
Eugenio Pérez, Michael S. Tsirkin, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Wang <jasowang@redhat.com>
[ Upstream commit 9c1523803445ee0348f62b77793266dd981596e0 ]
The bounceing is not necessarily page aligned, so current VDUSE can
leak kernel information through mapping bounce pages to
userspace. Allocate bounce pages with __GFP_ZERO to avoid leaking
information to userspace.
Fixes: 8c773d53fb7b ("vduse: Implement an MMU-based software IOTLB")
Cc: stable@vger.kernel.org
Signed-off-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Xie Yongji <xieyongji@bytedance.com>
Reviewed-by: Eugenio Pérez <eperezma@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Message-ID: <20260130050750.4050-1-jasowang@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/vdpa/vdpa_user/iova_domain.c | 2 +-
drivers/vdpa/vdpa_user/vduse_dev.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/vdpa/vdpa_user/iova_domain.c
+++ b/drivers/vdpa/vdpa_user/iova_domain.c
@@ -124,7 +124,7 @@ static int vduse_domain_map_bounce_page(
if (!map->bounce_page) {
head_map = &domain->bounce_maps[(iova & PAGE_MASK) >> BOUNCE_MAP_SHIFT];
if (!head_map->bounce_page) {
- tmp_page = alloc_page(GFP_ATOMIC);
+ tmp_page = alloc_page(GFP_ATOMIC | __GFP_ZERO);
if (!tmp_page)
return -ENOMEM;
if (cmpxchg(&head_map->bounce_page, NULL, tmp_page))
--- a/drivers/vdpa/vdpa_user/vduse_dev.c
+++ b/drivers/vdpa/vdpa_user/vduse_dev.c
@@ -887,7 +887,7 @@ static void *vduse_dev_alloc_coherent(st
*dma_addr = DMA_MAPPING_ERROR;
- addr = alloc_pages_exact(size, flag);
+ addr = alloc_pages_exact(size, flag | __GFP_ZERO);
if (!addr)
return NULL;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 493/602] octeontx2: Annotate mmio regions as __iomem
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (491 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 492/602] VDUSE: avoid leaking information to userspace Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 494/602] octeontx2-vf: clear stale mailbox IRQ state before request_irq() Greg Kroah-Hartman
` (112 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Subbaraya Sundeep, Jakub Kicinski,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Subbaraya Sundeep <sbhatta@marvell.com>
[ Upstream commit d0976b43956ee8c8bd093223df9115bfcf63dfe5 ]
This patch removes unnecessary typecasts by marking the
mbox_regions array as __iomem since it is used to store
pointers to memory-mapped I/O (MMIO) regions. Also simplified
the call to readq() in PF driver by removing redundant type casts.
Signed-off-by: Subbaraya Sundeep <sbhatta@marvell.com>
Link: https://patch.msgid.link/1749484309-3434-1-git-send-email-sbhatta@marvell.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: 0b352f04b9be ("octeontx2-vf: clear stale mailbox IRQ state before request_irq()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/marvell/octeontx2/af/rvu.c | 12 ++++++------
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 3 +--
2 files changed, 7 insertions(+), 8 deletions(-)
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
@@ -2401,7 +2401,7 @@ static inline void rvu_afvf_mbox_up_hand
__rvu_mbox_up_handler(mwork, TYPE_AFVF);
}
-static int rvu_get_mbox_regions(struct rvu *rvu, void **mbox_addr,
+static int rvu_get_mbox_regions(struct rvu *rvu, void __iomem **mbox_addr,
int num, int type, unsigned long *pf_bmap)
{
struct rvu_hwinfo *hw = rvu->hw;
@@ -2426,7 +2426,7 @@ static int rvu_get_mbox_regions(struct r
bar4 = rvupf_read64(rvu, RVU_PF_VF_BAR4_ADDR);
bar4 += region * MBOX_SIZE;
}
- mbox_addr[region] = (void *)ioremap_wc(bar4, MBOX_SIZE);
+ mbox_addr[region] = ioremap_wc(bar4, MBOX_SIZE);
if (!mbox_addr[region])
goto error;
}
@@ -2449,7 +2449,7 @@ static int rvu_get_mbox_regions(struct r
RVU_AF_PF_BAR4_ADDR);
bar4 += region * MBOX_SIZE;
}
- mbox_addr[region] = (void *)ioremap_wc(bar4, MBOX_SIZE);
+ mbox_addr[region] = ioremap_wc(bar4, MBOX_SIZE);
if (!mbox_addr[region])
goto error;
}
@@ -2457,7 +2457,7 @@ static int rvu_get_mbox_regions(struct r
error:
while (region--)
- iounmap((void __iomem *)mbox_addr[region]);
+ iounmap(mbox_addr[region]);
return -ENOMEM;
}
@@ -2467,10 +2467,10 @@ static int rvu_mbox_init(struct rvu *rvu
void (mbox_up_handler)(struct work_struct *))
{
int err = -EINVAL, i, dir, dir_up;
+ void __iomem **mbox_regions;
void __iomem *reg_base;
struct rvu_work *mwork;
unsigned long *pf_bmap;
- void **mbox_regions;
const char *name;
u64 cfg;
@@ -2493,7 +2493,7 @@ static int rvu_mbox_init(struct rvu *rvu
mutex_init(&rvu->mbox_lock);
- mbox_regions = kcalloc(num, sizeof(void *), GFP_KERNEL);
+ mbox_regions = kcalloc(num, sizeof(void __iomem *), GFP_KERNEL);
if (!mbox_regions) {
err = -ENOMEM;
goto free_bitmap;
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -593,8 +593,7 @@ static int otx2_pfvf_mbox_init(struct ot
base = pci_resource_start(pf->pdev, PCI_MBOX_BAR_NUM) +
MBOX_SIZE;
else
- base = readq((void __iomem *)((u64)pf->reg_base +
- RVU_PF_VF_BAR4_ADDR));
+ base = readq(pf->reg_base + RVU_PF_VF_BAR4_ADDR);
hwbase = ioremap_wc(base, MBOX_SIZE * pf->total_vfs);
if (!hwbase) {
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 494/602] octeontx2-vf: clear stale mailbox IRQ state before request_irq()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (492 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 493/602] octeontx2: Annotate mmio regions as __iomem Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 495/602] octeontx2-pf: " Greg Kroah-Hartman
` (111 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Runyu Xiao, Simon Horman,
Ratheesh Kannoth, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Runyu Xiao <runyu.xiao@seu.edu.cn>
[ Upstream commit 0b352f04b9be2c83c0240aa6dae7257fefa90464 ]
otx2vf_register_mbox_intr() currently installs the VF mailbox IRQ
handler before clearing stale mailbox interrupt state. The code then says
that local interrupt bits should be cleared first to avoid spurious
interrupts, but that clear still happens only after request_irq() has
already made the handler reachable.
A running system can reach this during VF mailbox interrupt registration
while stale or latched RVU_VF_INT state is still present. If delivery
happens in the request_irq()-to-clear window,
otx2vf_vfaf_mbox_intr_handler() can run before local quiesce and touch
the same vf->mbox and vf->mbox_wq carrier that probe and teardown later
reuse or destroy.
Move the stale mailbox interrupt clear ahead of request_irq(), but keep
interrupt enabling after the handler is installed. This closes the
pre-clear early-IRQ window without creating a new enable-before-handler
window.
Fixes: 3184fb5ba96e ("octeontx2-vf: Virtual function driver support")
Cc: stable@vger.kernel.org
Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn>
Reviewed-by: Simon Horman <horms@kernel.org>
Reviewed-by: Ratheesh Kannoth <rkannoth@marvell.com>
Link: https://patch.msgid.link/20260611160014.3202224-3-runyu.xiao@seu.edu.cn
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
@@ -245,9 +245,15 @@ static int otx2vf_register_mbox_intr(str
{
struct otx2_hw *hw = &vf->hw;
struct msg_req *req;
+ u64 mbox_int_mask;
char *irq_name;
int err;
+ mbox_int_mask = BIT_ULL(0);
+
+ /* Clear stale mailbox interrupt state before installing the handler. */
+ otx2_write64(vf, RVU_VF_INT, mbox_int_mask);
+
/* Register mailbox interrupt handler */
irq_name = &hw->irq_name[RVU_VF_INT_VEC_MBOX * NAME_SIZE];
snprintf(irq_name, NAME_SIZE, "RVUVFAF Mbox");
@@ -259,11 +265,8 @@ static int otx2vf_register_mbox_intr(str
return err;
}
- /* Enable mailbox interrupt for msgs coming from PF.
- * First clear to avoid spurious interrupts, if any.
- */
- otx2_write64(vf, RVU_VF_INT, BIT_ULL(0));
- otx2_write64(vf, RVU_VF_INT_ENA_W1S, BIT_ULL(0));
+ /* Enable mailbox interrupt for msgs coming from PF. */
+ otx2_write64(vf, RVU_VF_INT_ENA_W1S, mbox_int_mask);
if (!probe_pf)
return 0;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 495/602] octeontx2-pf: clear stale mailbox IRQ state before request_irq()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (493 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 494/602] octeontx2-vf: clear stale mailbox IRQ state before request_irq() Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 496/602] arm64: dts: qcom: correct RBR opp entry Greg Kroah-Hartman
` (110 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Runyu Xiao, Simon Horman,
Ratheesh Kannoth, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Runyu Xiao <runyu.xiao@seu.edu.cn>
[ Upstream commit f918554fb7246e89b98ef90abe80801f038258b3 ]
otx2_register_mbox_intr() currently installs the PF mailbox IRQ handler
before clearing stale mailbox interrupt state. The function itself then
comments that the local interrupt bits must be cleared first to avoid
spurious interrupts, but that clear happens only after request_irq() has
already exposed the handler to irq delivery.
A running system can reach this during PF mailbox interrupt registration
while stale or latched RVU_PF_INT state is still present. If delivery
happens in the request_irq()-to-clear window,
otx2_pfaf_mbox_intr_handler() can run before local quiesce and touch
the same pf->mbox and pf->mbox_wq carrier that probe and teardown later
reuse or destroy.
Move the stale mailbox interrupt clear ahead of request_irq(), but keep
interrupt enabling after the handler is installed. This closes the
pre-clear early-IRQ window without creating a new enable-before-handler
window.
Fixes: 5a6d7c9daef3 ("octeontx2-pf: Mailbox communication with AF")
Cc: stable@vger.kernel.org
Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn>
Reviewed-by: Simon Horman <horms@kernel.org>
Reviewed-by: Ratheesh Kannoth <rkannoth@marvell.com>
Link: https://patch.msgid.link/20260611160014.3202224-2-runyu.xiao@seu.edu.cn
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -1023,6 +1023,9 @@ static int otx2_register_mbox_intr(struc
char *irq_name;
int err;
+ /* Clear stale mailbox interrupt state before installing the handler. */
+ otx2_write64(pf, RVU_PF_INT, BIT_ULL(0));
+
/* Register mailbox interrupt handler */
irq_name = &hw->irq_name[RVU_PF_INT_VEC_AFPF_MBOX * NAME_SIZE];
snprintf(irq_name, NAME_SIZE, "RVUPFAF Mbox");
@@ -1034,10 +1037,7 @@ static int otx2_register_mbox_intr(struc
return err;
}
- /* Enable mailbox interrupt for msgs coming from AF.
- * First clear to avoid spurious interrupts, if any.
- */
- otx2_write64(pf, RVU_PF_INT, BIT_ULL(0));
+ /* Enable mailbox interrupt for msgs coming from AF. */
otx2_write64(pf, RVU_PF_INT_ENA_W1S, BIT_ULL(0));
if (!probe_af)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 496/602] arm64: dts: qcom: correct RBR opp entry
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (494 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 495/602] octeontx2-pf: " Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 497/602] arm64: dts: qcom: hamoa: Fix OPP tables for all DisplayPort controllers Greg Kroah-Hartman
` (109 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Dmitry Baryshkov, Bjorn Andersson,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
[ Upstream commit a5c21b9bd5f531e50141b0484faabb707b92f1e2 ]
DisplayPort Reduced Bit Rate uses link rate of 1.62 Gbps, the main link
clock should be 162 MHz. Having the incorrect frequency (160 MHz) in the
OPP table will result in selecting wrong link frequency. Correct the
entry in the OPP table.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20260304-msm-fix-rbr-v1-1-b9eba986eaef@oss.qualcomm.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
Stable-dep-of: c17e22094667 ("arm64: dts: qcom: hamoa: Fix OPP tables for all DisplayPort controllers")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/arm64/boot/dts/qcom/sc7180.dtsi | 4 ++--
arch/arm64/boot/dts/qcom/sc7280.dtsi | 8 ++++----
arch/arm64/boot/dts/qcom/sc8180x.dtsi | 12 ++++++------
arch/arm64/boot/dts/qcom/sc8280xp.dtsi | 32 ++++++++++++++++----------------
arch/arm64/boot/dts/qcom/sm6350.dtsi | 4 ++--
arch/arm64/boot/dts/qcom/sm8150.dtsi | 4 ++--
arch/arm64/boot/dts/qcom/sm8250.dtsi | 4 ++--
arch/arm64/boot/dts/qcom/sm8350.dtsi | 4 ++--
arch/arm64/boot/dts/qcom/sm8450.dtsi | 4 ++--
arch/arm64/boot/dts/qcom/x1e80100.dtsi | 16 ++++++++--------
10 files changed, 46 insertions(+), 46 deletions(-)
--- a/arch/arm64/boot/dts/qcom/sc7180.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi
@@ -3410,8 +3410,8 @@
dp_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-160000000 {
- opp-hz = /bits/ 64 <160000000>;
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
--- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
@@ -4723,8 +4723,8 @@
edp_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-160000000 {
- opp-hz = /bits/ 64 <160000000>;
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
@@ -4820,8 +4820,8 @@
dp_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-160000000 {
- opp-hz = /bits/ 64 <160000000>;
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
--- a/arch/arm64/boot/dts/qcom/sc8180x.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc8180x.dtsi
@@ -3269,8 +3269,8 @@
dp0_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-160000000 {
- opp-hz = /bits/ 64 <160000000>;
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
@@ -3347,8 +3347,8 @@
dp1_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-160000000 {
- opp-hz = /bits/ 64 <160000000>;
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
@@ -3415,8 +3415,8 @@
edp_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-160000000 {
- opp-hz = /bits/ 64 <160000000>;
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
--- a/arch/arm64/boot/dts/qcom/sc8280xp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc8280xp.dtsi
@@ -4259,8 +4259,8 @@
mdss0_dp0_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-160000000 {
- opp-hz = /bits/ 64 <160000000>;
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
@@ -4337,8 +4337,8 @@
mdss0_dp1_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-160000000 {
- opp-hz = /bits/ 64 <160000000>;
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
@@ -4409,8 +4409,8 @@
mdss0_dp2_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-160000000 {
- opp-hz = /bits/ 64 <160000000>;
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
@@ -4481,8 +4481,8 @@
mdss0_dp3_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-160000000 {
- opp-hz = /bits/ 64 <160000000>;
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
@@ -5547,8 +5547,8 @@
mdss1_dp0_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-160000000 {
- opp-hz = /bits/ 64 <160000000>;
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
@@ -5619,8 +5619,8 @@
mdss1_dp1_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-160000000 {
- opp-hz = /bits/ 64 <160000000>;
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
@@ -5691,8 +5691,8 @@
mdss1_dp2_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-160000000 {
- opp-hz = /bits/ 64 <160000000>;
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
@@ -5763,8 +5763,8 @@
mdss1_dp3_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-160000000 {
- opp-hz = /bits/ 64 <160000000>;
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
--- a/arch/arm64/boot/dts/qcom/sm6350.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6350.dtsi
@@ -2222,8 +2222,8 @@
dp_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-160000000 {
- opp-hz = /bits/ 64 <160000000>;
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
--- a/arch/arm64/boot/dts/qcom/sm8150.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi
@@ -3932,8 +3932,8 @@
dp_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-160000000 {
- opp-hz = /bits/ 64 <160000000>;
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
--- a/arch/arm64/boot/dts/qcom/sm8250.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi
@@ -4818,8 +4818,8 @@
dp_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-160000000 {
- opp-hz = /bits/ 64 <160000000>;
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
--- a/arch/arm64/boot/dts/qcom/sm8350.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8350.dtsi
@@ -2909,8 +2909,8 @@
dp_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-160000000 {
- opp-hz = /bits/ 64 <160000000>;
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
--- a/arch/arm64/boot/dts/qcom/sm8450.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8450.dtsi
@@ -3223,8 +3223,8 @@
dp_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-160000000 {
- opp-hz = /bits/ 64 <160000000>;
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
--- a/arch/arm64/boot/dts/qcom/x1e80100.dtsi
+++ b/arch/arm64/boot/dts/qcom/x1e80100.dtsi
@@ -4758,8 +4758,8 @@
mdss_dp0_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-160000000 {
- opp-hz = /bits/ 64 <160000000>;
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
@@ -4841,8 +4841,8 @@
mdss_dp1_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-160000000 {
- opp-hz = /bits/ 64 <160000000>;
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
@@ -4923,8 +4923,8 @@
mdss_dp2_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-160000000 {
- opp-hz = /bits/ 64 <160000000>;
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
@@ -5002,8 +5002,8 @@
mdss_dp3_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-160000000 {
- opp-hz = /bits/ 64 <160000000>;
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
required-opps = <&rpmhpd_opp_low_svs>;
};
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 497/602] arm64: dts: qcom: hamoa: Fix OPP tables for all DisplayPort controllers
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (495 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 496/602] arm64: dts: qcom: correct RBR opp entry Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 498/602] ASoC: mediatek: mt8192-afe-pcm: Simplify probe() with local dev variable Greg Kroah-Hartman
` (108 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Dmitry Baryshkov, Konrad Dybcio,
Abel Vesa, Bjorn Andersson, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abel Vesa <abel.vesa@oss.qualcomm.com>
[ Upstream commit c17e220946675232d383620ed9cff6685735ec48 ]
According to internal documentation, the corners specific for each rate
from the DP link clock are:
- LOWSVS_D1 -> 19.2 MHz
- LOWSVS -> 270 MHz
- SVS -> 540 MHz (594 MHz in case of DP3)
- SVS_L1 -> 594 MHz
- NOM -> 810 MHz
- NOM_L1 -> 810 MHz
- TURBO -> 810 MHz
So fix all tables for each of the four controllers according to the
documentation, but since DP0 through DP2 have the same entries in their
tables, lets drop the DP1 and DP2 and have all of them share the DP0
table instead. However keep a separate table for the DP3 as it is
different for the SVS, compared to the rest of the controllers.
The 19.2 MHz @ LOWSVS_D1 isn't needed as it's not an actual working
frequency and the controller will never select it. So remove it.
Cc: stable@vger.kernel.org # v6.9+
Fixes: 1940c25eaa63 ("arm64: dts: qcom: x1e80100: Add display nodes")
Suggested-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: Abel Vesa <abel.vesa@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20260323-hamoa-fix-dp3-opp-table-v3-1-a823776bd1b0@oss.qualcomm.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/arm64/boot/dts/qcom/x1e80100.dtsi | 77 +++++----------------------------
1 file changed, 12 insertions(+), 65 deletions(-)
--- a/arch/arm64/boot/dts/qcom/x1e80100.dtsi
+++ b/arch/arm64/boot/dts/qcom/x1e80100.dtsi
@@ -4758,18 +4758,18 @@
mdss_dp0_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-162000000 {
- opp-hz = /bits/ 64 <162000000>;
- required-opps = <&rpmhpd_opp_low_svs>;
- };
-
opp-270000000 {
opp-hz = /bits/ 64 <270000000>;
- required-opps = <&rpmhpd_opp_svs>;
+ required-opps = <&rpmhpd_opp_low_svs>;
};
opp-540000000 {
opp-hz = /bits/ 64 <540000000>;
+ required-opps = <&rpmhpd_opp_svs>;
+ };
+
+ opp-594000000 {
+ opp-hz = /bits/ 64 <594000000>;
required-opps = <&rpmhpd_opp_svs_l1>;
};
@@ -4806,7 +4806,7 @@
assigned-clock-parents = <&usb_1_ss1_qmpphy QMP_USB43DP_DP_LINK_CLK>,
<&usb_1_ss1_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
- operating-points-v2 = <&mdss_dp1_opp_table>;
+ operating-points-v2 = <&mdss_dp0_opp_table>;
power-domains = <&rpmhpd RPMHPD_MMCX>;
@@ -4837,30 +4837,6 @@
};
};
};
-
- mdss_dp1_opp_table: opp-table {
- compatible = "operating-points-v2";
-
- opp-162000000 {
- opp-hz = /bits/ 64 <162000000>;
- required-opps = <&rpmhpd_opp_low_svs>;
- };
-
- opp-270000000 {
- opp-hz = /bits/ 64 <270000000>;
- required-opps = <&rpmhpd_opp_svs>;
- };
-
- opp-540000000 {
- opp-hz = /bits/ 64 <540000000>;
- required-opps = <&rpmhpd_opp_svs_l1>;
- };
-
- opp-810000000 {
- opp-hz = /bits/ 64 <810000000>;
- required-opps = <&rpmhpd_opp_nom>;
- };
- };
};
mdss_dp2: displayport-controller@ae9a000 {
@@ -4889,7 +4865,7 @@
assigned-clock-parents = <&usb_1_ss2_qmpphy QMP_USB43DP_DP_LINK_CLK>,
<&usb_1_ss2_qmpphy QMP_USB43DP_DP_VCO_DIV_CLK>;
- operating-points-v2 = <&mdss_dp2_opp_table>;
+ operating-points-v2 = <&mdss_dp0_opp_table>;
power-domains = <&rpmhpd RPMHPD_MMCX>;
@@ -4919,30 +4895,6 @@
};
};
};
-
- mdss_dp2_opp_table: opp-table {
- compatible = "operating-points-v2";
-
- opp-162000000 {
- opp-hz = /bits/ 64 <162000000>;
- required-opps = <&rpmhpd_opp_low_svs>;
- };
-
- opp-270000000 {
- opp-hz = /bits/ 64 <270000000>;
- required-opps = <&rpmhpd_opp_svs>;
- };
-
- opp-540000000 {
- opp-hz = /bits/ 64 <540000000>;
- required-opps = <&rpmhpd_opp_svs_l1>;
- };
-
- opp-810000000 {
- opp-hz = /bits/ 64 <810000000>;
- required-opps = <&rpmhpd_opp_nom>;
- };
- };
};
mdss_dp3: displayport-controller@aea0000 {
@@ -5002,19 +4954,14 @@
mdss_dp3_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-162000000 {
- opp-hz = /bits/ 64 <162000000>;
- required-opps = <&rpmhpd_opp_low_svs>;
- };
-
opp-270000000 {
opp-hz = /bits/ 64 <270000000>;
- required-opps = <&rpmhpd_opp_svs>;
+ required-opps = <&rpmhpd_opp_low_svs>;
};
- opp-540000000 {
- opp-hz = /bits/ 64 <540000000>;
- required-opps = <&rpmhpd_opp_svs_l1>;
+ opp-594000000 {
+ opp-hz = /bits/ 64 <594000000>;
+ required-opps = <&rpmhpd_opp_svs>;
};
opp-810000000 {
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 498/602] ASoC: mediatek: mt8192-afe-pcm: Simplify probe() with local dev variable
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (496 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 497/602] arm64: dts: qcom: hamoa: Fix OPP tables for all DisplayPort controllers Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 499/602] ASoC: mediatek: mt8192: Check runtime resume during probe Greg Kroah-Hartman
` (107 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Tang Bin, Mark Brown, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tang Bin <tangbin@cmss.chinamobile.com>
[ Upstream commit 01981565c764c554cc96e2d30a71c42975171416 ]
Simplify the function mt8192_afe_pcm_dev_probe() by
using local 'dev' instead of '&pdev->dev'.
Signed-off-by: Tang Bin <tangbin@cmss.chinamobile.com>
Link: https://patch.msgid.link/20241025080026.2393-1-tangbin@cmss.chinamobile.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Stable-dep-of: e24d5dde56a5 ("ASoC: mediatek: mt8192: Check runtime resume during probe")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
sound/soc/mediatek/mt8192/mt8192-afe-pcm.c | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
--- a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c
+++ b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c
@@ -2164,27 +2164,26 @@ static int mt8192_afe_pcm_dev_probe(stru
{
struct mtk_base_afe *afe;
struct mt8192_afe_private *afe_priv;
- struct device *dev;
+ struct device *dev = &pdev->dev;
struct reset_control *rstc;
int i, ret, irq_id;
- ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(34));
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(34));
if (ret)
return ret;
- afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL);
+ afe = devm_kzalloc(dev, sizeof(*afe), GFP_KERNEL);
if (!afe)
return -ENOMEM;
platform_set_drvdata(pdev, afe);
- afe->platform_priv = devm_kzalloc(&pdev->dev, sizeof(*afe_priv),
+ afe->platform_priv = devm_kzalloc(dev, sizeof(*afe_priv),
GFP_KERNEL);
if (!afe->platform_priv)
return -ENOMEM;
afe_priv = afe->platform_priv;
- afe->dev = &pdev->dev;
- dev = afe->dev;
+ afe->dev = dev;
ret = of_reserved_mem_device_init(dev);
if (ret) {
@@ -2212,7 +2211,7 @@ static int mt8192_afe_pcm_dev_probe(stru
if (ret)
return dev_err_probe(dev, ret, "failed to trigger audio reset\n");
- ret = devm_pm_runtime_enable(&pdev->dev);
+ ret = devm_pm_runtime_enable(dev);
if (ret)
return ret;
@@ -2228,13 +2227,13 @@ static int mt8192_afe_pcm_dev_probe(stru
/* enable clock for regcache get default value from hw */
afe_priv->pm_runtime_bypass_reg_ctl = true;
- pm_runtime_get_sync(&pdev->dev);
+ pm_runtime_get_sync(dev);
ret = regmap_reinit_cache(afe->regmap, &mt8192_afe_regmap_config);
if (ret)
return dev_err_probe(dev, ret, "regmap_reinit_cache fail\n");
- pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_put_sync(dev);
afe_priv->pm_runtime_bypass_reg_ctl = false;
regcache_cache_only(afe->regmap, true);
@@ -2301,7 +2300,7 @@ static int mt8192_afe_pcm_dev_probe(stru
afe->runtime_suspend = mt8192_afe_runtime_suspend;
/* register platform */
- ret = devm_snd_soc_register_component(&pdev->dev,
+ ret = devm_snd_soc_register_component(dev,
&mtk_afe_pcm_platform,
afe->dai_drivers,
afe->num_dai_drivers);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 499/602] ASoC: mediatek: mt8192: Check runtime resume during probe
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (497 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 498/602] ASoC: mediatek: mt8192-afe-pcm: Simplify probe() with local dev variable Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 500/602] ASoC: mediatek: mt8183-afe-pcm: Shorten memif_data table using macros Greg Kroah-Hartman
` (106 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Cássio Gabriel, Mark Brown,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
[ Upstream commit e24d5dde56a50946020b134fa8448869093db76a ]
The MT8192 AFE probe enables runtime PM temporarily while reinitializing
the regmap cache from hardware, but it uses pm_runtime_get_sync()
without checking the return value. If runtime resume fails, probe keeps
going without the device necessarily being accessible, and
pm_runtime_get_sync() may leave the PM usage count incremented.
The regmap_reinit_cache() failure path also returns before dropping the
temporary PM reference and before clearing pm_runtime_bypass_reg_ctl.
Use pm_runtime_resume_and_get() so resume failures do not leak a usage
count, and clear the temporary bypass flag after dropping the probe PM
reference on all regmap_reinit_cache() outcomes.
Fixes: 125ab5d588b0 ("ASoC: mediatek: mt8192: add platform driver")
Cc: stable@vger.kernel.org
Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
Link: https://patch.msgid.link/20260527-asoc-mt8192-probe-cleanup-v1-2-1bb834d05b72@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
sound/soc/mediatek/mt8192/mt8192-afe-pcm.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
--- a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c
+++ b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c
@@ -2227,15 +2227,19 @@ static int mt8192_afe_pcm_dev_probe(stru
/* enable clock for regcache get default value from hw */
afe_priv->pm_runtime_bypass_reg_ctl = true;
- pm_runtime_get_sync(dev);
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret) {
+ afe_priv->pm_runtime_bypass_reg_ctl = false;
+ return dev_err_probe(dev, ret, "failed to resume device\n");
+ }
ret = regmap_reinit_cache(afe->regmap, &mt8192_afe_regmap_config);
- if (ret)
- return dev_err_probe(dev, ret, "regmap_reinit_cache fail\n");
-
pm_runtime_put_sync(dev);
afe_priv->pm_runtime_bypass_reg_ctl = false;
+ if (ret)
+ return dev_err_probe(dev, ret, "regmap_reinit_cache fail\n");
+
regcache_cache_only(afe->regmap, true);
regcache_mark_dirty(afe->regmap);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 500/602] ASoC: mediatek: mt8183-afe-pcm: Shorten memif_data table using macros
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (498 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 499/602] ASoC: mediatek: mt8192: Check runtime resume during probe Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 501/602] ASoC: mediatek: mt8183-afe-pcm: Support >32 bit DMA addresses Greg Kroah-Hartman
` (105 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Chen-Yu Tsai,
AngeloGioacchino Del Regno, Mark Brown, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen-Yu Tsai <wenst@chromium.org>
[ Upstream commit 91c2685430f217ae8f2866e4372948eaf123b5c4 ]
The memif_data table describes all the supported PCM channels for the
audio frontend. Most of the fields are either the same or can be derived
from the interface's name. This results in a very long table (in source
code) that can be shortened with macros.
Do just that. Some "convenience" macros were added to cover non-existent
register fields that would otherwise require multiple layers of macros
to handle.
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Link: https://patch.msgid.link/20250515073825.4155297-2-wenst@chromium.org
Signed-off-by: Mark Brown <broonie@kernel.org>
Stable-dep-of: f0334fbfd107 ("ASoC: mediatek: mt8183: Check runtime resume during probe")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
sound/soc/mediatek/mt8183/mt8183-afe-pcm.c | 243 ++++++-----------------------
1 file changed, 54 insertions(+), 189 deletions(-)
--- a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c
+++ b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c
@@ -425,196 +425,61 @@ static const struct snd_soc_component_dr
.name = "mt8183-afe-pcm-dai",
};
+#define MT8183_MEMIF_BASE(_id, _en_reg, _fs_reg, _mono_reg) \
+ [MT8183_MEMIF_##_id] = { \
+ .name = #_id, \
+ .id = MT8183_MEMIF_##_id, \
+ .reg_ofs_base = AFE_##_id##_BASE, \
+ .reg_ofs_cur = AFE_##_id##_CUR, \
+ .reg_ofs_end = AFE_##_id##_END, \
+ .fs_reg = (_fs_reg), \
+ .fs_shift = _id##_MODE_SFT, \
+ .fs_maskbit = _id##_MODE_MASK, \
+ .mono_reg = (_mono_reg), \
+ .mono_shift = _id##_DATA_SFT, \
+ .enable_reg = (_en_reg), \
+ .enable_shift = _id##_ON_SFT, \
+ .hd_reg = AFE_MEMIF_HD_MODE, \
+ .hd_align_reg = AFE_MEMIF_HDALIGN, \
+ .hd_shift = _id##_HD_SFT, \
+ .hd_align_mshift = _id##_HD_ALIGN_SFT, \
+ .agent_disable_reg = -1, \
+ .agent_disable_shift = -1, \
+ .msb_reg = -1, \
+ .msb_shift = -1, \
+ }
+
+#define MT8183_MEMIF(_id, _fs_reg, _mono_reg) \
+ MT8183_MEMIF_BASE(_id, AFE_DAC_CON0, _fs_reg, _mono_reg)
+
+/* For convenience with macros: missing register fields */
+#define MOD_DAI_DATA_SFT -1
+#define HDMI_MODE_SFT -1
+#define HDMI_MODE_MASK -1
+#define HDMI_DATA_SFT -1
+#define HDMI_ON_SFT -1
+
+/* For convenience with macros: register name differences */
+#define AFE_VUL12_BASE AFE_VUL_D2_BASE
+#define AFE_VUL12_CUR AFE_VUL_D2_CUR
+#define AFE_VUL12_END AFE_VUL_D2_END
+#define AWB2_HD_ALIGN_SFT AWB2_ALIGN_SFT
+#define VUL12_DATA_SFT VUL12_MONO_SFT
+#define AFE_HDMI_BASE AFE_HDMI_OUT_BASE
+#define AFE_HDMI_CUR AFE_HDMI_OUT_CUR
+#define AFE_HDMI_END AFE_HDMI_OUT_END
+
static const struct mtk_base_memif_data memif_data[MT8183_MEMIF_NUM] = {
- [MT8183_MEMIF_DL1] = {
- .name = "DL1",
- .id = MT8183_MEMIF_DL1,
- .reg_ofs_base = AFE_DL1_BASE,
- .reg_ofs_cur = AFE_DL1_CUR,
- .fs_reg = AFE_DAC_CON1,
- .fs_shift = DL1_MODE_SFT,
- .fs_maskbit = DL1_MODE_MASK,
- .mono_reg = AFE_DAC_CON1,
- .mono_shift = DL1_DATA_SFT,
- .enable_reg = AFE_DAC_CON0,
- .enable_shift = DL1_ON_SFT,
- .hd_reg = AFE_MEMIF_HD_MODE,
- .hd_align_reg = AFE_MEMIF_HDALIGN,
- .hd_shift = DL1_HD_SFT,
- .hd_align_mshift = DL1_HD_ALIGN_SFT,
- .agent_disable_reg = -1,
- .agent_disable_shift = -1,
- .msb_reg = -1,
- .msb_shift = -1,
- },
- [MT8183_MEMIF_DL2] = {
- .name = "DL2",
- .id = MT8183_MEMIF_DL2,
- .reg_ofs_base = AFE_DL2_BASE,
- .reg_ofs_cur = AFE_DL2_CUR,
- .fs_reg = AFE_DAC_CON1,
- .fs_shift = DL2_MODE_SFT,
- .fs_maskbit = DL2_MODE_MASK,
- .mono_reg = AFE_DAC_CON1,
- .mono_shift = DL2_DATA_SFT,
- .enable_reg = AFE_DAC_CON0,
- .enable_shift = DL2_ON_SFT,
- .hd_reg = AFE_MEMIF_HD_MODE,
- .hd_align_reg = AFE_MEMIF_HDALIGN,
- .hd_shift = DL2_HD_SFT,
- .hd_align_mshift = DL2_HD_ALIGN_SFT,
- .agent_disable_reg = -1,
- .agent_disable_shift = -1,
- .msb_reg = -1,
- .msb_shift = -1,
- },
- [MT8183_MEMIF_DL3] = {
- .name = "DL3",
- .id = MT8183_MEMIF_DL3,
- .reg_ofs_base = AFE_DL3_BASE,
- .reg_ofs_cur = AFE_DL3_CUR,
- .fs_reg = AFE_DAC_CON2,
- .fs_shift = DL3_MODE_SFT,
- .fs_maskbit = DL3_MODE_MASK,
- .mono_reg = AFE_DAC_CON1,
- .mono_shift = DL3_DATA_SFT,
- .enable_reg = AFE_DAC_CON0,
- .enable_shift = DL3_ON_SFT,
- .hd_reg = AFE_MEMIF_HD_MODE,
- .hd_align_reg = AFE_MEMIF_HDALIGN,
- .hd_shift = DL3_HD_SFT,
- .hd_align_mshift = DL3_HD_ALIGN_SFT,
- .agent_disable_reg = -1,
- .agent_disable_shift = -1,
- .msb_reg = -1,
- .msb_shift = -1,
- },
- [MT8183_MEMIF_VUL2] = {
- .name = "VUL2",
- .id = MT8183_MEMIF_VUL2,
- .reg_ofs_base = AFE_VUL2_BASE,
- .reg_ofs_cur = AFE_VUL2_CUR,
- .fs_reg = AFE_DAC_CON2,
- .fs_shift = VUL2_MODE_SFT,
- .fs_maskbit = VUL2_MODE_MASK,
- .mono_reg = AFE_DAC_CON2,
- .mono_shift = VUL2_DATA_SFT,
- .enable_reg = AFE_DAC_CON0,
- .enable_shift = VUL2_ON_SFT,
- .hd_reg = AFE_MEMIF_HD_MODE,
- .hd_align_reg = AFE_MEMIF_HDALIGN,
- .hd_shift = VUL2_HD_SFT,
- .hd_align_mshift = VUL2_HD_ALIGN_SFT,
- .agent_disable_reg = -1,
- .agent_disable_shift = -1,
- .msb_reg = -1,
- .msb_shift = -1,
- },
- [MT8183_MEMIF_AWB] = {
- .name = "AWB",
- .id = MT8183_MEMIF_AWB,
- .reg_ofs_base = AFE_AWB_BASE,
- .reg_ofs_cur = AFE_AWB_CUR,
- .fs_reg = AFE_DAC_CON1,
- .fs_shift = AWB_MODE_SFT,
- .fs_maskbit = AWB_MODE_MASK,
- .mono_reg = AFE_DAC_CON1,
- .mono_shift = AWB_DATA_SFT,
- .enable_reg = AFE_DAC_CON0,
- .enable_shift = AWB_ON_SFT,
- .hd_reg = AFE_MEMIF_HD_MODE,
- .hd_align_reg = AFE_MEMIF_HDALIGN,
- .hd_shift = AWB_HD_SFT,
- .hd_align_mshift = AWB_HD_ALIGN_SFT,
- .agent_disable_reg = -1,
- .agent_disable_shift = -1,
- .msb_reg = -1,
- .msb_shift = -1,
- },
- [MT8183_MEMIF_AWB2] = {
- .name = "AWB2",
- .id = MT8183_MEMIF_AWB2,
- .reg_ofs_base = AFE_AWB2_BASE,
- .reg_ofs_cur = AFE_AWB2_CUR,
- .fs_reg = AFE_DAC_CON2,
- .fs_shift = AWB2_MODE_SFT,
- .fs_maskbit = AWB2_MODE_MASK,
- .mono_reg = AFE_DAC_CON2,
- .mono_shift = AWB2_DATA_SFT,
- .enable_reg = AFE_DAC_CON0,
- .enable_shift = AWB2_ON_SFT,
- .hd_reg = AFE_MEMIF_HD_MODE,
- .hd_align_reg = AFE_MEMIF_HDALIGN,
- .hd_shift = AWB2_HD_SFT,
- .hd_align_mshift = AWB2_ALIGN_SFT,
- .agent_disable_reg = -1,
- .agent_disable_shift = -1,
- .msb_reg = -1,
- .msb_shift = -1,
- },
- [MT8183_MEMIF_VUL12] = {
- .name = "VUL12",
- .id = MT8183_MEMIF_VUL12,
- .reg_ofs_base = AFE_VUL_D2_BASE,
- .reg_ofs_cur = AFE_VUL_D2_CUR,
- .fs_reg = AFE_DAC_CON0,
- .fs_shift = VUL12_MODE_SFT,
- .fs_maskbit = VUL12_MODE_MASK,
- .mono_reg = AFE_DAC_CON0,
- .mono_shift = VUL12_MONO_SFT,
- .enable_reg = AFE_DAC_CON0,
- .enable_shift = VUL12_ON_SFT,
- .hd_reg = AFE_MEMIF_HD_MODE,
- .hd_align_reg = AFE_MEMIF_HDALIGN,
- .hd_shift = VUL12_HD_SFT,
- .hd_align_mshift = VUL12_HD_ALIGN_SFT,
- .agent_disable_reg = -1,
- .agent_disable_shift = -1,
- .msb_reg = -1,
- .msb_shift = -1,
- },
- [MT8183_MEMIF_MOD_DAI] = {
- .name = "MOD_DAI",
- .id = MT8183_MEMIF_MOD_DAI,
- .reg_ofs_base = AFE_MOD_DAI_BASE,
- .reg_ofs_cur = AFE_MOD_DAI_CUR,
- .fs_reg = AFE_DAC_CON1,
- .fs_shift = MOD_DAI_MODE_SFT,
- .fs_maskbit = MOD_DAI_MODE_MASK,
- .mono_reg = -1,
- .mono_shift = 0,
- .enable_reg = AFE_DAC_CON0,
- .enable_shift = MOD_DAI_ON_SFT,
- .hd_reg = AFE_MEMIF_HD_MODE,
- .hd_align_reg = AFE_MEMIF_HDALIGN,
- .hd_shift = MOD_DAI_HD_SFT,
- .hd_align_mshift = MOD_DAI_HD_ALIGN_SFT,
- .agent_disable_reg = -1,
- .agent_disable_shift = -1,
- .msb_reg = -1,
- .msb_shift = -1,
- },
- [MT8183_MEMIF_HDMI] = {
- .name = "HDMI",
- .id = MT8183_MEMIF_HDMI,
- .reg_ofs_base = AFE_HDMI_OUT_BASE,
- .reg_ofs_cur = AFE_HDMI_OUT_CUR,
- .fs_reg = -1,
- .fs_shift = -1,
- .fs_maskbit = -1,
- .mono_reg = -1,
- .mono_shift = -1,
- .enable_reg = -1, /* control in tdm for sync start */
- .enable_shift = -1,
- .hd_reg = AFE_MEMIF_HD_MODE,
- .hd_align_reg = AFE_MEMIF_HDALIGN,
- .hd_shift = HDMI_HD_SFT,
- .hd_align_mshift = HDMI_HD_ALIGN_SFT,
- .agent_disable_reg = -1,
- .agent_disable_shift = -1,
- .msb_reg = -1,
- .msb_shift = -1,
- },
+ MT8183_MEMIF(DL1, AFE_DAC_CON1, AFE_DAC_CON1),
+ MT8183_MEMIF(DL2, AFE_DAC_CON1, AFE_DAC_CON1),
+ MT8183_MEMIF(DL3, AFE_DAC_CON2, AFE_DAC_CON1),
+ MT8183_MEMIF(VUL2, AFE_DAC_CON2, AFE_DAC_CON2),
+ MT8183_MEMIF(AWB, AFE_DAC_CON1, AFE_DAC_CON1),
+ MT8183_MEMIF(AWB2, AFE_DAC_CON2, AFE_DAC_CON2),
+ MT8183_MEMIF(VUL12, AFE_DAC_CON0, AFE_DAC_CON0),
+ MT8183_MEMIF(MOD_DAI, AFE_DAC_CON1, -1),
+ /* enable control in tdm for sync start */
+ MT8183_MEMIF_BASE(HDMI, -1, -1, -1),
};
static const struct mtk_base_irq_data irq_data[MT8183_IRQ_NUM] = {
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 501/602] ASoC: mediatek: mt8183-afe-pcm: Support >32 bit DMA addresses
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (499 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 500/602] ASoC: mediatek: mt8183-afe-pcm: Shorten memif_data table using macros Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 502/602] ASoC: mediatek: mt8183-afe-pcm: use local `dev` pointer in driver callbacks Greg Kroah-Hartman
` (104 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, AngeloGioacchino Del Regno,
Chen-Yu Tsai, Mark Brown, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen-Yu Tsai <wenst@chromium.org>
[ Upstream commit 9e7bc5cb8d089d9799e17a9ac99c5da9b13b02e3 ]
The AFE DMA hardware supports up to 34 bits for DMA addresses. This is
missing from the driver and prevents reserved memory regions from
working properly when the allocated region is above the 4GB line.
Fill in the related register offsets for each DAI, and also set the
DMA mask. Also fill in the LSB end register offsets for completeness.
Fixes: a94aec035a12 ("ASoC: mediatek: mt8183: add platform driver")
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
Link: https://patch.msgid.link/20250612074901.4023253-8-wenst@chromium.org
Signed-off-by: Mark Brown <broonie@kernel.org>
Stable-dep-of: f0334fbfd107 ("ASoC: mediatek: mt8183: Check runtime resume during probe")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
sound/soc/mediatek/mt8183/mt8183-afe-pcm.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
--- a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c
+++ b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c
@@ -6,6 +6,7 @@
// Author: KaiChieh Chuang <kaichieh.chuang@mediatek.com>
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/mfd/syscon.h>
#include <linux/of.h>
@@ -432,6 +433,9 @@ static const struct snd_soc_component_dr
.reg_ofs_base = AFE_##_id##_BASE, \
.reg_ofs_cur = AFE_##_id##_CUR, \
.reg_ofs_end = AFE_##_id##_END, \
+ .reg_ofs_base_msb = AFE_##_id##_BASE_MSB, \
+ .reg_ofs_cur_msb = AFE_##_id##_CUR_MSB, \
+ .reg_ofs_end_msb = AFE_##_id##_END_MSB, \
.fs_reg = (_fs_reg), \
.fs_shift = _id##_MODE_SFT, \
.fs_maskbit = _id##_MODE_MASK, \
@@ -463,11 +467,17 @@ static const struct snd_soc_component_dr
#define AFE_VUL12_BASE AFE_VUL_D2_BASE
#define AFE_VUL12_CUR AFE_VUL_D2_CUR
#define AFE_VUL12_END AFE_VUL_D2_END
+#define AFE_VUL12_BASE_MSB AFE_VUL_D2_BASE_MSB
+#define AFE_VUL12_CUR_MSB AFE_VUL_D2_CUR_MSB
+#define AFE_VUL12_END_MSB AFE_VUL_D2_END_MSB
#define AWB2_HD_ALIGN_SFT AWB2_ALIGN_SFT
#define VUL12_DATA_SFT VUL12_MONO_SFT
#define AFE_HDMI_BASE AFE_HDMI_OUT_BASE
#define AFE_HDMI_CUR AFE_HDMI_OUT_CUR
#define AFE_HDMI_END AFE_HDMI_OUT_END
+#define AFE_HDMI_BASE_MSB AFE_HDMI_OUT_BASE_MSB
+#define AFE_HDMI_CUR_MSB AFE_HDMI_OUT_CUR_MSB
+#define AFE_HDMI_END_MSB AFE_HDMI_OUT_END_MSB
static const struct mtk_base_memif_data memif_data[MT8183_MEMIF_NUM] = {
MT8183_MEMIF(DL1, AFE_DAC_CON1, AFE_DAC_CON1),
@@ -951,6 +961,10 @@ static int mt8183_afe_pcm_dev_probe(stru
struct reset_control *rstc;
int i, irq_id, ret;
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(34));
+ if (ret)
+ return ret;
+
afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL);
if (!afe)
return -ENOMEM;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 502/602] ASoC: mediatek: mt8183-afe-pcm: use local `dev` pointer in driver callbacks
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (500 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 501/602] ASoC: mediatek: mt8183-afe-pcm: Support >32 bit DMA addresses Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 503/602] ASoC: mediatek: mt8183: Check runtime resume during probe Greg Kroah-Hartman
` (103 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, AngeloGioacchino Del Regno,
Chen-Yu Tsai, Mark Brown, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen-Yu Tsai <wenst@chromium.org>
[ Upstream commit bb8d8ba4715cb8f997d63d90ba935f6073595df5 ]
The probe and remove functions in the mt8183-afe-pcm driver repeatedly uses
`&pdev->dev` for |struct device *|, but then assigns this value to
`afe->dev` and uses that in other places in the same function.
Store `&pdev->dev` in a local pointer and use that exclusively to avoid
the numerous dereferences and to make the code more consistent. Lines
are reflowed where it makes sense.
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
Link: https://patch.msgid.link/20250612074901.4023253-10-wenst@chromium.org
Signed-off-by: Mark Brown <broonie@kernel.org>
Stable-dep-of: f0334fbfd107 ("ASoC: mediatek: mt8183: Check runtime resume during probe")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
sound/soc/mediatek/mt8183/mt8183-afe-pcm.c | 37 +++++++++++++----------------
1 file changed, 17 insertions(+), 20 deletions(-)
--- a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c
+++ b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c
@@ -957,27 +957,25 @@ static int mt8183_afe_pcm_dev_probe(stru
{
struct mtk_base_afe *afe;
struct mt8183_afe_private *afe_priv;
- struct device *dev;
+ struct device *dev = &pdev->dev;
struct reset_control *rstc;
int i, irq_id, ret;
- ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(34));
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(34));
if (ret)
return ret;
- afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL);
+ afe = devm_kzalloc(dev, sizeof(*afe), GFP_KERNEL);
if (!afe)
return -ENOMEM;
platform_set_drvdata(pdev, afe);
- afe->platform_priv = devm_kzalloc(&pdev->dev, sizeof(*afe_priv),
- GFP_KERNEL);
+ afe->platform_priv = devm_kzalloc(dev, sizeof(*afe_priv), GFP_KERNEL);
if (!afe->platform_priv)
return -ENOMEM;
afe_priv = afe->platform_priv;
- afe->dev = &pdev->dev;
- dev = afe->dev;
+ afe->dev = dev;
ret = of_reserved_mem_device_init(dev);
if (ret) {
@@ -1028,7 +1026,7 @@ static int mt8183_afe_pcm_dev_probe(stru
/* enable clock for regcache get default value from hw */
afe_priv->pm_runtime_bypass_reg_ctl = true;
- pm_runtime_get_sync(&pdev->dev);
+ pm_runtime_get_sync(dev);
ret = regmap_reinit_cache(afe->regmap, &mt8183_afe_regmap_config);
if (ret) {
@@ -1036,7 +1034,7 @@ static int mt8183_afe_pcm_dev_probe(stru
goto err_pm_disable;
}
- pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_put_sync(dev);
afe_priv->pm_runtime_bypass_reg_ctl = false;
regcache_cache_only(afe->regmap, true);
@@ -1094,7 +1092,7 @@ static int mt8183_afe_pcm_dev_probe(stru
for (i = 0; i < ARRAY_SIZE(dai_register_cbs); i++) {
ret = dai_register_cbs[i](afe);
if (ret) {
- dev_warn(afe->dev, "dai register i %d fail, ret %d\n",
+ dev_warn(dev, "dai register i %d fail, ret %d\n",
i, ret);
goto err_pm_disable;
}
@@ -1103,8 +1101,7 @@ static int mt8183_afe_pcm_dev_probe(stru
/* init dai_driver and component_driver */
ret = mtk_afe_combine_sub_dai(afe);
if (ret) {
- dev_warn(afe->dev, "mtk_afe_combine_sub_dai fail, ret %d\n",
- ret);
+ dev_warn(dev, "mtk_afe_combine_sub_dai fail, ret %d\n", ret);
goto err_pm_disable;
}
@@ -1116,16 +1113,14 @@ static int mt8183_afe_pcm_dev_probe(stru
afe->runtime_suspend = mt8183_afe_runtime_suspend;
/* register component */
- ret = devm_snd_soc_register_component(&pdev->dev,
- &mtk_afe_pcm_platform,
+ ret = devm_snd_soc_register_component(dev, &mtk_afe_pcm_platform,
NULL, 0);
if (ret) {
dev_warn(dev, "err_platform\n");
goto err_pm_disable;
}
- ret = devm_snd_soc_register_component(afe->dev,
- &mt8183_afe_pcm_dai_component,
+ ret = devm_snd_soc_register_component(dev, &mt8183_afe_pcm_dai_component,
afe->dai_drivers,
afe->num_dai_drivers);
if (ret) {
@@ -1136,15 +1131,17 @@ static int mt8183_afe_pcm_dev_probe(stru
return ret;
err_pm_disable:
- pm_runtime_disable(&pdev->dev);
+ pm_runtime_disable(dev);
return ret;
}
static void mt8183_afe_pcm_dev_remove(struct platform_device *pdev)
{
- pm_runtime_disable(&pdev->dev);
- if (!pm_runtime_status_suspended(&pdev->dev))
- mt8183_afe_runtime_suspend(&pdev->dev);
+ struct device *dev = &pdev->dev;
+
+ pm_runtime_disable(dev);
+ if (!pm_runtime_status_suspended(dev))
+ mt8183_afe_runtime_suspend(dev);
}
static const struct of_device_id mt8183_afe_pcm_dt_match[] = {
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 503/602] ASoC: mediatek: mt8183: Check runtime resume during probe
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (501 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 502/602] ASoC: mediatek: mt8183-afe-pcm: use local `dev` pointer in driver callbacks Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 504/602] netfilter: nf_conntrack_sip: remove net variable shadowing Greg Kroah-Hartman
` (102 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Cássio Gabriel, Mark Brown,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cássio Gabriel <cassiogabrielcontato@gmail.com>
[ Upstream commit f0334fbfd107682d0c95f3f71e25f6127038e2b9 ]
The MT8183 AFE probe uses pm_runtime_get_sync() before reading hardware
defaults into the regmap cache, but does not check whether runtime resume
failed. If regmap_reinit_cache() then fails, the temporary runtime PM
usage count is also not released.
Use pm_runtime_resume_and_get() so resume failures abort probe without
leaking a usage count, and release the temporary reference before
handling the regmap cache result.
Fixes: a94aec035a12 ("ASoC: mediatek: mt8183: add platform driver")
Cc: stable@vger.kernel.org
Signed-off-by: Cássio Gabriel <cassiogabrielcontato@gmail.com>
Link: https://patch.msgid.link/20260527-asoc-mt8183-probe-cleanup-v1-2-4f4f5593c8d1@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
sound/soc/mediatek/mt8183/mt8183-afe-pcm.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
--- a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c
+++ b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c
@@ -1026,17 +1026,21 @@ static int mt8183_afe_pcm_dev_probe(stru
/* enable clock for regcache get default value from hw */
afe_priv->pm_runtime_bypass_reg_ctl = true;
- pm_runtime_get_sync(dev);
-
- ret = regmap_reinit_cache(afe->regmap, &mt8183_afe_regmap_config);
+ ret = pm_runtime_resume_and_get(dev);
if (ret) {
- dev_err(dev, "regmap_reinit_cache fail, ret %d\n", ret);
+ afe_priv->pm_runtime_bypass_reg_ctl = false;
goto err_pm_disable;
}
+ ret = regmap_reinit_cache(afe->regmap, &mt8183_afe_regmap_config);
pm_runtime_put_sync(dev);
afe_priv->pm_runtime_bypass_reg_ctl = false;
+ if (ret) {
+ dev_err(dev, "regmap_reinit_cache fail, ret %d\n", ret);
+ goto err_pm_disable;
+ }
+
regcache_cache_only(afe->regmap, true);
regcache_mark_dirty(afe->regmap);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 504/602] netfilter: nf_conntrack_sip: remove net variable shadowing
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (502 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 503/602] ASoC: mediatek: mt8183: Check runtime resume during probe Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 505/602] netfilter: nf_conntrack_sip: validate skb_dst() before accessing it Greg Kroah-Hartman
` (101 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Florian Westphal, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <fw@strlen.de>
[ Upstream commit 7970d6aaf710db166de98c5356a260089896fae5 ]
net is already set, derived from nf_conn.
I don't see how the device could be living in a different netns
than the conntrack entry.
Remove the extra variable and re-use existing one.
Signed-off-by: Florian Westphal <fw@strlen.de>
Stable-dep-of: e5e24a365a5e ("netfilter: nf_conntrack_sip: validate skb_dst() before accessing it")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/netfilter/nf_conntrack_sip.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -948,9 +948,8 @@ static int set_expected_rtp_rtcp(struct
saddr = &ct->tuplehash[!dir].tuple.src.u3;
} else if (sip_external_media) {
struct net_device *dev = skb_dst(skb)->dev;
- struct net *net = dev_net(dev);
- struct flowi fl;
struct dst_entry *dst = NULL;
+ struct flowi fl;
memset(&fl, 0, sizeof(fl));
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 505/602] netfilter: nf_conntrack_sip: validate skb_dst() before accessing it
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (503 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 504/602] netfilter: nf_conntrack_sip: remove net variable shadowing Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 506/602] netfilter: bitwise: rename some boolean operation functions Greg Kroah-Hartman
` (100 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Ren Wei, Pablo Neira Ayuso,
Florian Westphal, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <pablo@netfilter.org>
[ Upstream commit e5e24a365a5e024efef63cc49abb345fbd4852c5 ]
tc ingress and openvswitch do not guarantee routing information to be
available. These subsystems use the conntrack helper infrastructure, and
the SIP helper relies on the skb_dst() to be present if
sip_external_media is set to 1 (which is disabled by default as a module
parameter).
This effectively disables the sip_external_media toggle for these
subsystems without resulting in a crash.
Fixes: cae3a2627520 ("openvswitch: Allow attaching helpers to ct action")
Fixes: b57dc7c13ea9 ("net/sched: Introduce action ct")
Cc: stable@vger.kernel.org
Reported-by: Ren Wei <n05ec@lzu.edu.cn>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/netfilter/nf_conntrack_sip.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -947,7 +947,6 @@ static int set_expected_rtp_rtcp(struct
return NF_ACCEPT;
saddr = &ct->tuplehash[!dir].tuple.src.u3;
} else if (sip_external_media) {
- struct net_device *dev = skb_dst(skb)->dev;
struct dst_entry *dst = NULL;
struct flowi fl;
@@ -969,7 +968,11 @@ static int set_expected_rtp_rtcp(struct
* through the same interface as the signalling peer.
*/
if (dst) {
- bool external_media = (dst->dev == dev);
+ const struct dst_entry *this_dst = skb_dst(skb);
+ bool external_media = false;
+
+ if (this_dst && dst->dev == this_dst->dev)
+ external_media = true;
dst_release(dst);
if (external_media)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 506/602] netfilter: bitwise: rename some boolean operation functions
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (504 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 505/602] netfilter: nf_conntrack_sip: validate skb_dst() before accessing it Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 507/602] netfilter: nf_tables: Remove unused nft_reduce_is_readonly() Greg Kroah-Hartman
` (99 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jeremy Sowden, Pablo Neira Ayuso,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeremy Sowden <jeremy@azazel.net>
[ Upstream commit a12143e6084c502fc3cfaa8b717bffc8c14cf806 ]
In the next patch we add support for doing AND, OR and XOR operations
directly in the kernel, so rename some functions and an enum constant
related to mask-and-xor boolean operations.
Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Stable-dep-of: d07955dd34ec ("netfilter: nft_fib: reject fib expression on the netdev egress hook")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/uapi/linux/netfilter/nf_tables.h | 10 ++++++---
net/netfilter/nft_bitwise.c | 34 +++++++++++++++----------------
2 files changed, 24 insertions(+), 20 deletions(-)
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -564,16 +564,20 @@ enum nft_immediate_attributes {
/**
* enum nft_bitwise_ops - nf_tables bitwise operations
*
- * @NFT_BITWISE_BOOL: mask-and-xor operation used to implement NOT, AND, OR and
- * XOR boolean operations
+ * @NFT_BITWISE_MASK_XOR: mask-and-xor operation used to implement NOT, AND, OR
+ * and XOR boolean operations
* @NFT_BITWISE_LSHIFT: left-shift operation
* @NFT_BITWISE_RSHIFT: right-shift operation
*/
enum nft_bitwise_ops {
- NFT_BITWISE_BOOL,
+ NFT_BITWISE_MASK_XOR,
NFT_BITWISE_LSHIFT,
NFT_BITWISE_RSHIFT,
};
+/*
+ * Old name for NFT_BITWISE_MASK_XOR. Retained for backwards-compatibility.
+ */
+#define NFT_BITWISE_BOOL NFT_BITWISE_MASK_XOR
/**
* enum nft_bitwise_attributes - nf_tables bitwise expression netlink attributes
--- a/net/netfilter/nft_bitwise.c
+++ b/net/netfilter/nft_bitwise.c
@@ -25,8 +25,8 @@ struct nft_bitwise {
struct nft_data data;
};
-static void nft_bitwise_eval_bool(u32 *dst, const u32 *src,
- const struct nft_bitwise *priv)
+static void nft_bitwise_eval_mask_xor(u32 *dst, const u32 *src,
+ const struct nft_bitwise *priv)
{
unsigned int i;
@@ -68,8 +68,8 @@ void nft_bitwise_eval(const struct nft_e
u32 *dst = ®s->data[priv->dreg];
switch (priv->op) {
- case NFT_BITWISE_BOOL:
- nft_bitwise_eval_bool(dst, src, priv);
+ case NFT_BITWISE_MASK_XOR:
+ nft_bitwise_eval_mask_xor(dst, src, priv);
break;
case NFT_BITWISE_LSHIFT:
nft_bitwise_eval_lshift(dst, src, priv);
@@ -90,8 +90,8 @@ static const struct nla_policy nft_bitwi
[NFTA_BITWISE_DATA] = { .type = NLA_NESTED },
};
-static int nft_bitwise_init_bool(struct nft_bitwise *priv,
- const struct nlattr *const tb[])
+static int nft_bitwise_init_mask_xor(struct nft_bitwise *priv,
+ const struct nlattr *const tb[])
{
struct nft_data_desc mask = {
.type = NFT_DATA_VALUE,
@@ -186,7 +186,7 @@ static int nft_bitwise_init(const struct
if (tb[NFTA_BITWISE_OP]) {
priv->op = ntohl(nla_get_be32(tb[NFTA_BITWISE_OP]));
switch (priv->op) {
- case NFT_BITWISE_BOOL:
+ case NFT_BITWISE_MASK_XOR:
case NFT_BITWISE_LSHIFT:
case NFT_BITWISE_RSHIFT:
break;
@@ -194,12 +194,12 @@ static int nft_bitwise_init(const struct
return -EOPNOTSUPP;
}
} else {
- priv->op = NFT_BITWISE_BOOL;
+ priv->op = NFT_BITWISE_MASK_XOR;
}
switch(priv->op) {
- case NFT_BITWISE_BOOL:
- err = nft_bitwise_init_bool(priv, tb);
+ case NFT_BITWISE_MASK_XOR:
+ err = nft_bitwise_init_mask_xor(priv, tb);
break;
case NFT_BITWISE_LSHIFT:
case NFT_BITWISE_RSHIFT:
@@ -210,8 +210,8 @@ static int nft_bitwise_init(const struct
return err;
}
-static int nft_bitwise_dump_bool(struct sk_buff *skb,
- const struct nft_bitwise *priv)
+static int nft_bitwise_dump_mask_xor(struct sk_buff *skb,
+ const struct nft_bitwise *priv)
{
if (nft_data_dump(skb, NFTA_BITWISE_MASK, &priv->mask,
NFT_DATA_VALUE, priv->len) < 0)
@@ -249,8 +249,8 @@ static int nft_bitwise_dump(struct sk_bu
return -1;
switch (priv->op) {
- case NFT_BITWISE_BOOL:
- err = nft_bitwise_dump_bool(skb, priv);
+ case NFT_BITWISE_MASK_XOR:
+ err = nft_bitwise_dump_mask_xor(skb, priv);
break;
case NFT_BITWISE_LSHIFT:
case NFT_BITWISE_RSHIFT:
@@ -270,7 +270,7 @@ static int nft_bitwise_offload(struct nf
const struct nft_bitwise *priv = nft_expr_priv(expr);
struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
- if (priv->op != NFT_BITWISE_BOOL)
+ if (priv->op != NFT_BITWISE_MASK_XOR)
return -EOPNOTSUPP;
if (memcmp(&priv->xor, &zero, sizeof(priv->xor)) ||
@@ -407,7 +407,7 @@ nft_bitwise_fast_dump(struct sk_buff *sk
return -1;
if (nla_put_be32(skb, NFTA_BITWISE_LEN, htonl(sizeof(u32))))
return -1;
- if (nla_put_be32(skb, NFTA_BITWISE_OP, htonl(NFT_BITWISE_BOOL)))
+ if (nla_put_be32(skb, NFTA_BITWISE_OP, htonl(NFT_BITWISE_MASK_XOR)))
return -1;
data.data[0] = priv->mask;
@@ -502,7 +502,7 @@ nft_bitwise_select_ops(const struct nft_
return &nft_bitwise_ops;
if (tb[NFTA_BITWISE_OP] &&
- ntohl(nla_get_be32(tb[NFTA_BITWISE_OP])) != NFT_BITWISE_BOOL)
+ ntohl(nla_get_be32(tb[NFTA_BITWISE_OP])) != NFT_BITWISE_MASK_XOR)
return &nft_bitwise_ops;
return &nft_bitwise_fast_ops;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 507/602] netfilter: nf_tables: Remove unused nft_reduce_is_readonly()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (505 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 506/602] netfilter: bitwise: rename some boolean operation functions Greg Kroah-Hartman
@ 2026-07-30 14:14 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 508/602] netfilter: nf_tables: remove register tracking infrastructure Greg Kroah-Hartman
` (98 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:14 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yue Haibing, Simon Horman,
Pablo Neira Ayuso, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yue Haibing <yuehaibing@huawei.com>
[ Upstream commit bf6788742b8d6c73de441e088a71de7154f0d4aa ]
Since commit 9e539c5b6d9c ("netfilter: nf_tables: disable expression
reduction infra") this is unused.
Signed-off-by: Yue Haibing <yuehaibing@huawei.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Stable-dep-of: d07955dd34ec ("netfilter: nft_fib: reject fib expression on the netdev egress hook")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/net/netfilter/nf_tables.h | 5 -----
1 file changed, 5 deletions(-)
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -1954,11 +1954,6 @@ static inline u64 nft_net_tstamp(const s
#define __NFT_REDUCE_READONLY 1UL
#define NFT_REDUCE_READONLY (void *)__NFT_REDUCE_READONLY
-static inline bool nft_reduce_is_readonly(const struct nft_expr *expr)
-{
- return expr->ops->reduce == NFT_REDUCE_READONLY;
-}
-
void nft_reg_track_update(struct nft_regs_track *track,
const struct nft_expr *expr, u8 dreg, u8 len);
void nft_reg_track_cancel(struct nft_regs_track *track, u8 dreg, u8 len);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 508/602] netfilter: nf_tables: remove register tracking infrastructure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (506 preceding siblings ...)
2026-07-30 14:14 ` [PATCH 6.12 507/602] netfilter: nf_tables: Remove unused nft_reduce_is_readonly() Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 509/602] netfilter: nft_fib: reject fib expression on the netdev egress hook Greg Kroah-Hartman
` (97 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Florian Westphal, Jakub Kicinski,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <fw@strlen.de>
[ Upstream commit 6b94d081f81dd524626f7aab2b98a9de335edb72 ]
This facility was disabled in commit
9e539c5b6d9c ("netfilter: nf_tables: disable expression reduction infra"),
because not all nft_exprs guarantee they will update the destination
register: some may set NFT_BREAK instead to cancel evaluation of the
rule.
This has been dead code ever since.
There are no plans to salvage this at this time, so remove this.
Signed-off-by: Florian Westphal <fw@strlen.de>
Link: https://patch.msgid.link/20260224205048.4718-10-fw@strlen.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: d07955dd34ec ("netfilter: nft_fib: reject fib expression on the netdev egress hook")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/net/netfilter/nf_tables.h | 32 ---------
include/net/netfilter/nft_fib.h | 2
include/net/netfilter/nft_meta.h | 3
net/bridge/netfilter/nft_meta_bridge.c | 20 ------
net/bridge/netfilter/nft_reject_bridge.c | 1
net/ipv4/netfilter/nft_dup_ipv4.c | 1
net/ipv4/netfilter/nft_fib_ipv4.c | 2
net/ipv4/netfilter/nft_reject_ipv4.c | 1
net/ipv6/netfilter/nft_dup_ipv6.c | 1
net/ipv6/netfilter/nft_fib_ipv6.c | 2
net/ipv6/netfilter/nft_reject_ipv6.c | 1
net/netfilter/nf_tables_api.c | 67 --------------------
net/netfilter/nft_bitwise.c | 103 -------------------------------
net/netfilter/nft_byteorder.c | 11 ---
net/netfilter/nft_cmp.c | 3
net/netfilter/nft_compat.c | 10 ---
net/netfilter/nft_connlimit.c | 1
net/netfilter/nft_counter.c | 1
net/netfilter/nft_ct.c | 46 -------------
net/netfilter/nft_dup_netdev.c | 1
net/netfilter/nft_dynset.c | 1
net/netfilter/nft_exthdr.c | 34 ----------
net/netfilter/nft_fib.c | 42 ------------
net/netfilter/nft_fib_inet.c | 1
net/netfilter/nft_fib_netdev.c | 1
net/netfilter/nft_flow_offload.c | 1
net/netfilter/nft_fwd_netdev.c | 2
net/netfilter/nft_hash.c | 36 ----------
net/netfilter/nft_immediate.c | 12 ---
net/netfilter/nft_last.c | 1
net/netfilter/nft_limit.c | 2
net/netfilter/nft_log.c | 1
net/netfilter/nft_lookup.c | 12 ---
net/netfilter/nft_masq.c | 3
net/netfilter/nft_meta.c | 45 -------------
net/netfilter/nft_nat.c | 2
net/netfilter/nft_numgen.c | 22 ------
net/netfilter/nft_objref.c | 2
net/netfilter/nft_osf.c | 25 -------
net/netfilter/nft_payload.c | 47 --------------
net/netfilter/nft_queue.c | 2
net/netfilter/nft_quota.c | 1
net/netfilter/nft_range.c | 1
net/netfilter/nft_redir.c | 3
net/netfilter/nft_reject_inet.c | 1
net/netfilter/nft_reject_netdev.c | 1
net/netfilter/nft_rt.c | 1
net/netfilter/nft_socket.c | 26 -------
net/netfilter/nft_synproxy.c | 1
net/netfilter/nft_tproxy.c | 1
net/netfilter/nft_tunnel.c | 26 -------
net/netfilter/nft_xfrm.c | 27 --------
52 files changed, 692 deletions(-)
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -123,17 +123,6 @@ struct nft_regs {
};
};
-struct nft_regs_track {
- struct {
- const struct nft_expr *selector;
- const struct nft_expr *bitwise;
- u8 num_reg;
- } regs[NFT_REG32_NUM];
-
- const struct nft_expr *cur;
- const struct nft_expr *last;
-};
-
/* Store/load an u8, u16 or u64 integer to/from the u32 data register.
*
* Note, when using concatenations, register allocation happens at 32-bit
@@ -424,8 +413,6 @@ int nft_expr_clone(struct nft_expr *dst,
void nft_expr_destroy(const struct nft_ctx *ctx, struct nft_expr *expr);
int nft_expr_dump(struct sk_buff *skb, unsigned int attr,
const struct nft_expr *expr, bool reset);
-bool nft_expr_reduce_bitwise(struct nft_regs_track *track,
- const struct nft_expr *expr);
struct nft_set_ext;
@@ -940,7 +927,6 @@ struct nft_offload_ctx;
* @destroy_clone: destruction clone function
* @dump: function to dump parameters
* @validate: validate expression, called during loop detection
- * @reduce: reduce expression
* @gc: garbage collection expression
* @offload: hardware offload expression
* @offload_action: function to report true/false to allocate one slot or not in the flow
@@ -974,8 +960,6 @@ struct nft_expr_ops {
bool reset);
int (*validate)(const struct nft_ctx *ctx,
const struct nft_expr *expr);
- bool (*reduce)(struct nft_regs_track *track,
- const struct nft_expr *expr);
bool (*gc)(struct net *net,
const struct nft_expr *expr);
int (*offload)(struct nft_offload_ctx *ctx,
@@ -1951,20 +1935,4 @@ static inline u64 nft_net_tstamp(const s
return nft_pernet(net)->tstamp;
}
-#define __NFT_REDUCE_READONLY 1UL
-#define NFT_REDUCE_READONLY (void *)__NFT_REDUCE_READONLY
-
-void nft_reg_track_update(struct nft_regs_track *track,
- const struct nft_expr *expr, u8 dreg, u8 len);
-void nft_reg_track_cancel(struct nft_regs_track *track, u8 dreg, u8 len);
-void __nft_reg_track_cancel(struct nft_regs_track *track, u8 dreg);
-
-static inline bool nft_reg_track_cmp(struct nft_regs_track *track,
- const struct nft_expr *expr, u8 dreg)
-{
- return track->regs[dreg].selector &&
- track->regs[dreg].selector->ops == expr->ops &&
- track->regs[dreg].num_reg == 0;
-}
-
#endif /* _NET_NF_TABLES_H */
--- a/include/net/netfilter/nft_fib.h
+++ b/include/net/netfilter/nft_fib.h
@@ -66,6 +66,4 @@ void nft_fib6_eval(const struct nft_expr
void nft_fib_store_result(void *reg, const struct nft_fib *priv,
const struct net_device *dev);
-bool nft_fib_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr);
#endif
--- a/include/net/netfilter/nft_meta.h
+++ b/include/net/netfilter/nft_meta.h
@@ -43,9 +43,6 @@ void nft_meta_set_destroy(const struct n
int nft_meta_set_validate(const struct nft_ctx *ctx,
const struct nft_expr *expr);
-bool nft_meta_get_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr);
-
struct nft_inner_tun_ctx;
void nft_meta_inner_eval(const struct nft_expr *expr,
struct nft_regs *regs, const struct nft_pktinfo *pkt,
--- a/net/bridge/netfilter/nft_meta_bridge.c
+++ b/net/bridge/netfilter/nft_meta_bridge.c
@@ -104,7 +104,6 @@ static const struct nft_expr_ops nft_met
.eval = nft_meta_bridge_get_eval,
.init = nft_meta_bridge_get_init,
.dump = nft_meta_get_dump,
- .reduce = nft_meta_get_reduce,
};
static void nft_meta_bridge_set_eval(const struct nft_expr *expr,
@@ -151,24 +150,6 @@ static int nft_meta_bridge_set_init(cons
return 0;
}
-static bool nft_meta_bridge_set_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- int i;
-
- for (i = 0; i < NFT_REG32_NUM; i++) {
- if (!track->regs[i].selector)
- continue;
-
- if (track->regs[i].selector->ops != &nft_meta_bridge_get_ops)
- continue;
-
- __nft_reg_track_cancel(track, i);
- }
-
- return false;
-}
-
static int nft_meta_bridge_set_validate(const struct nft_ctx *ctx,
const struct nft_expr *expr)
{
@@ -193,7 +174,6 @@ static const struct nft_expr_ops nft_met
.init = nft_meta_bridge_set_init,
.destroy = nft_meta_set_destroy,
.dump = nft_meta_set_dump,
- .reduce = nft_meta_bridge_set_reduce,
.validate = nft_meta_bridge_set_validate,
};
--- a/net/bridge/netfilter/nft_reject_bridge.c
+++ b/net/bridge/netfilter/nft_reject_bridge.c
@@ -184,7 +184,6 @@ static const struct nft_expr_ops nft_rej
.init = nft_reject_init,
.dump = nft_reject_dump,
.validate = nft_reject_bridge_validate,
- .reduce = NFT_REDUCE_READONLY,
};
static struct nft_expr_type nft_reject_bridge_type __read_mostly = {
--- a/net/ipv4/netfilter/nft_dup_ipv4.c
+++ b/net/ipv4/netfilter/nft_dup_ipv4.c
@@ -76,7 +76,6 @@ static const struct nft_expr_ops nft_dup
.eval = nft_dup_ipv4_eval,
.init = nft_dup_ipv4_init,
.dump = nft_dup_ipv4_dump,
- .reduce = NFT_REDUCE_READONLY,
};
static const struct nla_policy nft_dup_ipv4_policy[NFTA_DUP_MAX + 1] = {
--- a/net/ipv4/netfilter/nft_fib_ipv4.c
+++ b/net/ipv4/netfilter/nft_fib_ipv4.c
@@ -162,7 +162,6 @@ static const struct nft_expr_ops nft_fib
.init = nft_fib_init,
.dump = nft_fib_dump,
.validate = nft_fib_validate,
- .reduce = nft_fib_reduce,
};
static const struct nft_expr_ops nft_fib4_ops = {
@@ -172,7 +171,6 @@ static const struct nft_expr_ops nft_fib
.init = nft_fib_init,
.dump = nft_fib_dump,
.validate = nft_fib_validate,
- .reduce = nft_fib_reduce,
};
static const struct nft_expr_ops *
--- a/net/ipv4/netfilter/nft_reject_ipv4.c
+++ b/net/ipv4/netfilter/nft_reject_ipv4.c
@@ -45,7 +45,6 @@ static const struct nft_expr_ops nft_rej
.init = nft_reject_init,
.dump = nft_reject_dump,
.validate = nft_reject_validate,
- .reduce = NFT_REDUCE_READONLY,
};
static struct nft_expr_type nft_reject_ipv4_type __read_mostly = {
--- a/net/ipv6/netfilter/nft_dup_ipv6.c
+++ b/net/ipv6/netfilter/nft_dup_ipv6.c
@@ -74,7 +74,6 @@ static const struct nft_expr_ops nft_dup
.eval = nft_dup_ipv6_eval,
.init = nft_dup_ipv6_init,
.dump = nft_dup_ipv6_dump,
- .reduce = NFT_REDUCE_READONLY,
};
static const struct nla_policy nft_dup_ipv6_policy[NFTA_DUP_MAX + 1] = {
--- a/net/ipv6/netfilter/nft_fib_ipv6.c
+++ b/net/ipv6/netfilter/nft_fib_ipv6.c
@@ -225,7 +225,6 @@ static const struct nft_expr_ops nft_fib
.init = nft_fib_init,
.dump = nft_fib_dump,
.validate = nft_fib_validate,
- .reduce = nft_fib_reduce,
};
static const struct nft_expr_ops nft_fib6_ops = {
@@ -235,7 +234,6 @@ static const struct nft_expr_ops nft_fib
.init = nft_fib_init,
.dump = nft_fib_dump,
.validate = nft_fib_validate,
- .reduce = nft_fib_reduce,
};
static const struct nft_expr_ops *
--- a/net/ipv6/netfilter/nft_reject_ipv6.c
+++ b/net/ipv6/netfilter/nft_reject_ipv6.c
@@ -46,7 +46,6 @@ static const struct nft_expr_ops nft_rej
.init = nft_reject_init,
.dump = nft_reject_dump,
.validate = nft_reject_validate,
- .reduce = NFT_REDUCE_READONLY,
};
static struct nft_expr_type nft_reject_ipv6_type __read_mostly = {
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -802,58 +802,6 @@ static int nft_delflowtable(struct nft_c
return 0;
}
-static void __nft_reg_track_clobber(struct nft_regs_track *track, u8 dreg)
-{
- int i;
-
- for (i = track->regs[dreg].num_reg; i > 0; i--)
- __nft_reg_track_cancel(track, dreg - i);
-}
-
-static void __nft_reg_track_update(struct nft_regs_track *track,
- const struct nft_expr *expr,
- u8 dreg, u8 num_reg)
-{
- track->regs[dreg].selector = expr;
- track->regs[dreg].bitwise = NULL;
- track->regs[dreg].num_reg = num_reg;
-}
-
-void nft_reg_track_update(struct nft_regs_track *track,
- const struct nft_expr *expr, u8 dreg, u8 len)
-{
- unsigned int regcount;
- int i;
-
- __nft_reg_track_clobber(track, dreg);
-
- regcount = DIV_ROUND_UP(len, NFT_REG32_SIZE);
- for (i = 0; i < regcount; i++, dreg++)
- __nft_reg_track_update(track, expr, dreg, i);
-}
-EXPORT_SYMBOL_GPL(nft_reg_track_update);
-
-void nft_reg_track_cancel(struct nft_regs_track *track, u8 dreg, u8 len)
-{
- unsigned int regcount;
- int i;
-
- __nft_reg_track_clobber(track, dreg);
-
- regcount = DIV_ROUND_UP(len, NFT_REG32_SIZE);
- for (i = 0; i < regcount; i++, dreg++)
- __nft_reg_track_cancel(track, dreg);
-}
-EXPORT_SYMBOL_GPL(nft_reg_track_cancel);
-
-void __nft_reg_track_cancel(struct nft_regs_track *track, u8 dreg)
-{
- track->regs[dreg].selector = NULL;
- track->regs[dreg].bitwise = NULL;
- track->regs[dreg].num_reg = 0;
-}
-EXPORT_SYMBOL_GPL(__nft_reg_track_cancel);
-
/*
* Tables
*/
@@ -9685,16 +9633,9 @@ void nf_tables_trans_destroy_flush_work(
}
EXPORT_SYMBOL_GPL(nf_tables_trans_destroy_flush_work);
-static bool nft_expr_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- return false;
-}
-
static int nf_tables_commit_chain_prepare(struct net *net, struct nft_chain *chain)
{
const struct nft_expr *expr, *last;
- struct nft_regs_track track = {};
unsigned int size, data_size;
void *data, *data_boundary;
struct nft_rule_dp *prule;
@@ -9731,15 +9672,7 @@ static int nf_tables_commit_chain_prepar
return -ENOMEM;
size = 0;
- track.last = nft_expr_last(rule);
nft_rule_for_each_expr(expr, last, rule) {
- track.cur = expr;
-
- if (nft_expr_reduce(&track, expr)) {
- expr = track.cur;
- continue;
- }
-
if (WARN_ON_ONCE(data + size + expr->ops->size > data_boundary))
return -ENOMEM;
--- a/net/netfilter/nft_bitwise.c
+++ b/net/netfilter/nft_bitwise.c
@@ -282,60 +282,12 @@ static int nft_bitwise_offload(struct nf
return 0;
}
-static bool nft_bitwise_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- const struct nft_bitwise *priv = nft_expr_priv(expr);
- const struct nft_bitwise *bitwise;
- unsigned int regcount;
- u8 dreg;
- int i;
-
- if (!track->regs[priv->sreg].selector)
- return false;
-
- bitwise = nft_expr_priv(track->regs[priv->dreg].selector);
- if (track->regs[priv->sreg].selector == track->regs[priv->dreg].selector &&
- track->regs[priv->sreg].num_reg == 0 &&
- track->regs[priv->dreg].bitwise &&
- track->regs[priv->dreg].bitwise->ops == expr->ops &&
- priv->sreg == bitwise->sreg &&
- priv->dreg == bitwise->dreg &&
- priv->op == bitwise->op &&
- priv->len == bitwise->len &&
- !memcmp(&priv->mask, &bitwise->mask, sizeof(priv->mask)) &&
- !memcmp(&priv->xor, &bitwise->xor, sizeof(priv->xor)) &&
- !memcmp(&priv->data, &bitwise->data, sizeof(priv->data))) {
- track->cur = expr;
- return true;
- }
-
- if (track->regs[priv->sreg].bitwise ||
- track->regs[priv->sreg].num_reg != 0) {
- nft_reg_track_cancel(track, priv->dreg, priv->len);
- return false;
- }
-
- if (priv->sreg != priv->dreg) {
- nft_reg_track_update(track, track->regs[priv->sreg].selector,
- priv->dreg, priv->len);
- }
-
- dreg = priv->dreg;
- regcount = DIV_ROUND_UP(priv->len, NFT_REG32_SIZE);
- for (i = 0; i < regcount; i++, dreg++)
- track->regs[dreg].bitwise = expr;
-
- return false;
-}
-
static const struct nft_expr_ops nft_bitwise_ops = {
.type = &nft_bitwise_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_bitwise)),
.eval = nft_bitwise_eval,
.init = nft_bitwise_init,
.dump = nft_bitwise_dump,
- .reduce = nft_bitwise_reduce,
.offload = nft_bitwise_offload,
};
@@ -437,48 +389,12 @@ static int nft_bitwise_fast_offload(stru
return 0;
}
-static bool nft_bitwise_fast_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- const struct nft_bitwise_fast_expr *priv = nft_expr_priv(expr);
- const struct nft_bitwise_fast_expr *bitwise;
-
- if (!track->regs[priv->sreg].selector)
- return false;
-
- bitwise = nft_expr_priv(track->regs[priv->dreg].selector);
- if (track->regs[priv->sreg].selector == track->regs[priv->dreg].selector &&
- track->regs[priv->dreg].bitwise &&
- track->regs[priv->dreg].bitwise->ops == expr->ops &&
- priv->sreg == bitwise->sreg &&
- priv->dreg == bitwise->dreg &&
- priv->mask == bitwise->mask &&
- priv->xor == bitwise->xor) {
- track->cur = expr;
- return true;
- }
-
- if (track->regs[priv->sreg].bitwise) {
- nft_reg_track_cancel(track, priv->dreg, NFT_REG32_SIZE);
- return false;
- }
-
- if (priv->sreg != priv->dreg) {
- track->regs[priv->dreg].selector =
- track->regs[priv->sreg].selector;
- }
- track->regs[priv->dreg].bitwise = expr;
-
- return false;
-}
-
const struct nft_expr_ops nft_bitwise_fast_ops = {
.type = &nft_bitwise_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_bitwise_fast_expr)),
.eval = NULL, /* inlined */
.init = nft_bitwise_fast_init,
.dump = nft_bitwise_fast_dump,
- .reduce = nft_bitwise_fast_reduce,
.offload = nft_bitwise_fast_offload,
};
@@ -515,22 +431,3 @@ struct nft_expr_type nft_bitwise_type __
.maxattr = NFTA_BITWISE_MAX,
.owner = THIS_MODULE,
};
-
-bool nft_expr_reduce_bitwise(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- const struct nft_expr *last = track->last;
- const struct nft_expr *next;
-
- if (expr == last)
- return false;
-
- next = nft_expr_next(expr);
- if (next->ops == &nft_bitwise_ops)
- return nft_bitwise_reduce(track, next);
- else if (next->ops == &nft_bitwise_fast_ops)
- return nft_bitwise_fast_reduce(track, next);
-
- return false;
-}
-EXPORT_SYMBOL_GPL(nft_expr_reduce_bitwise);
--- a/net/netfilter/nft_byteorder.c
+++ b/net/netfilter/nft_byteorder.c
@@ -170,23 +170,12 @@ nla_put_failure:
return -1;
}
-static bool nft_byteorder_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- struct nft_byteorder *priv = nft_expr_priv(expr);
-
- nft_reg_track_cancel(track, priv->dreg, priv->len);
-
- return false;
-}
-
static const struct nft_expr_ops nft_byteorder_ops = {
.type = &nft_byteorder_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_byteorder)),
.eval = nft_byteorder_eval,
.init = nft_byteorder_init,
.dump = nft_byteorder_dump,
- .reduce = nft_byteorder_reduce,
};
struct nft_expr_type nft_byteorder_type __read_mostly = {
--- a/net/netfilter/nft_cmp.c
+++ b/net/netfilter/nft_cmp.c
@@ -190,7 +190,6 @@ static const struct nft_expr_ops nft_cmp
.eval = nft_cmp_eval,
.init = nft_cmp_init,
.dump = nft_cmp_dump,
- .reduce = NFT_REDUCE_READONLY,
.offload = nft_cmp_offload,
};
@@ -282,7 +281,6 @@ const struct nft_expr_ops nft_cmp_fast_o
.eval = NULL, /* inlined */
.init = nft_cmp_fast_init,
.dump = nft_cmp_fast_dump,
- .reduce = NFT_REDUCE_READONLY,
.offload = nft_cmp_fast_offload,
};
@@ -376,7 +374,6 @@ const struct nft_expr_ops nft_cmp16_fast
.eval = NULL, /* inlined */
.init = nft_cmp16_fast_init,
.dump = nft_cmp16_fast_dump,
- .reduce = NFT_REDUCE_READONLY,
.offload = nft_cmp16_fast_offload,
};
--- a/net/netfilter/nft_compat.c
+++ b/net/netfilter/nft_compat.c
@@ -794,14 +794,6 @@ static const struct nfnetlink_subsystem
static struct nft_expr_type nft_match_type;
-static bool nft_match_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- const struct xt_match *match = expr->ops->data;
-
- return strcmp(match->name, "comment") == 0;
-}
-
static const struct nft_expr_ops *
nft_match_select_ops(const struct nft_ctx *ctx,
const struct nlattr * const tb[])
@@ -844,7 +836,6 @@ nft_match_select_ops(const struct nft_ct
ops->dump = nft_match_dump;
ops->validate = nft_match_validate;
ops->data = match;
- ops->reduce = nft_match_reduce;
matchsize = NFT_EXPR_SIZE(XT_ALIGN(match->matchsize));
if (matchsize > NFT_MATCH_LARGE_THRESH) {
@@ -933,7 +924,6 @@ nft_target_select_ops(const struct nft_c
ops->destroy = nft_target_destroy;
ops->dump = nft_target_dump;
ops->data = target;
- ops->reduce = NFT_REDUCE_READONLY;
if (family == NFPROTO_BRIDGE) {
ops->eval = nft_target_eval_bridge;
--- a/net/netfilter/nft_connlimit.c
+++ b/net/netfilter/nft_connlimit.c
@@ -247,7 +247,6 @@ static const struct nft_expr_ops nft_con
.destroy_clone = nft_connlimit_destroy_clone,
.dump = nft_connlimit_dump,
.gc = nft_connlimit_gc,
- .reduce = NFT_REDUCE_READONLY,
};
static struct nft_expr_type nft_connlimit_type __read_mostly = {
--- a/net/netfilter/nft_counter.c
+++ b/net/netfilter/nft_counter.c
@@ -313,7 +313,6 @@ static const struct nft_expr_ops nft_cou
.destroy_clone = nft_counter_destroy,
.dump = nft_counter_dump,
.clone = nft_counter_clone,
- .reduce = NFT_REDUCE_READONLY,
.offload = nft_counter_offload,
.offload_stats = nft_counter_offload_stats,
};
--- a/net/netfilter/nft_ct.c
+++ b/net/netfilter/nft_ct.c
@@ -679,29 +679,6 @@ nla_put_failure:
return -1;
}
-static bool nft_ct_get_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- const struct nft_ct *priv = nft_expr_priv(expr);
- const struct nft_ct *ct;
-
- if (!nft_reg_track_cmp(track, expr, priv->dreg)) {
- nft_reg_track_update(track, expr, priv->dreg, priv->len);
- return false;
- }
-
- ct = nft_expr_priv(track->regs[priv->dreg].selector);
- if (priv->key != ct->key) {
- nft_reg_track_update(track, expr, priv->dreg, priv->len);
- return false;
- }
-
- if (!track->regs[priv->dreg].bitwise)
- return true;
-
- return nft_expr_reduce_bitwise(track, expr);
-}
-
static int nft_ct_set_dump(struct sk_buff *skb,
const struct nft_expr *expr, bool reset)
{
@@ -736,27 +713,8 @@ static const struct nft_expr_ops nft_ct_
.init = nft_ct_get_init,
.destroy = nft_ct_get_destroy,
.dump = nft_ct_get_dump,
- .reduce = nft_ct_get_reduce,
};
-static bool nft_ct_set_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- int i;
-
- for (i = 0; i < NFT_REG32_NUM; i++) {
- if (!track->regs[i].selector)
- continue;
-
- if (track->regs[i].selector->ops != &nft_ct_get_ops)
- continue;
-
- __nft_reg_track_cancel(track, i);
- }
-
- return false;
-}
-
#ifdef CONFIG_MITIGATION_RETPOLINE
static const struct nft_expr_ops nft_ct_get_fast_ops = {
.type = &nft_ct_type,
@@ -765,7 +723,6 @@ static const struct nft_expr_ops nft_ct_
.init = nft_ct_get_init,
.destroy = nft_ct_get_destroy,
.dump = nft_ct_get_dump,
- .reduce = nft_ct_set_reduce,
};
#endif
@@ -776,7 +733,6 @@ static const struct nft_expr_ops nft_ct_
.init = nft_ct_set_init,
.destroy = nft_ct_set_destroy,
.dump = nft_ct_set_dump,
- .reduce = nft_ct_set_reduce,
};
#ifdef CONFIG_NF_CONNTRACK_ZONES
@@ -787,7 +743,6 @@ static const struct nft_expr_ops nft_ct_
.init = nft_ct_set_init,
.destroy = nft_ct_set_destroy,
.dump = nft_ct_set_dump,
- .reduce = nft_ct_set_reduce,
};
#endif
@@ -857,7 +812,6 @@ static const struct nft_expr_ops nft_not
.type = &nft_notrack_type,
.size = NFT_EXPR_SIZE(0),
.eval = nft_notrack_eval,
- .reduce = NFT_REDUCE_READONLY,
};
static struct nft_expr_type nft_notrack_type __read_mostly = {
--- a/net/netfilter/nft_dup_netdev.c
+++ b/net/netfilter/nft_dup_netdev.c
@@ -80,7 +80,6 @@ static const struct nft_expr_ops nft_dup
.eval = nft_dup_netdev_eval,
.init = nft_dup_netdev_init,
.dump = nft_dup_netdev_dump,
- .reduce = NFT_REDUCE_READONLY,
.offload = nft_dup_netdev_offload,
.offload_action = nft_dup_netdev_offload_action,
};
--- a/net/netfilter/nft_dynset.c
+++ b/net/netfilter/nft_dynset.c
@@ -430,7 +430,6 @@ static const struct nft_expr_ops nft_dyn
.activate = nft_dynset_activate,
.deactivate = nft_dynset_deactivate,
.dump = nft_dynset_dump,
- .reduce = NFT_REDUCE_READONLY,
};
struct nft_expr_type nft_dynset_type __read_mostly = {
--- a/net/netfilter/nft_exthdr.c
+++ b/net/netfilter/nft_exthdr.c
@@ -701,40 +701,12 @@ static int nft_exthdr_dump_strip(struct
return nft_exthdr_dump_common(skb, priv);
}
-static bool nft_exthdr_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- const struct nft_exthdr *priv = nft_expr_priv(expr);
- const struct nft_exthdr *exthdr;
-
- if (!nft_reg_track_cmp(track, expr, priv->dreg)) {
- nft_reg_track_update(track, expr, priv->dreg, priv->len);
- return false;
- }
-
- exthdr = nft_expr_priv(track->regs[priv->dreg].selector);
- if (priv->type != exthdr->type ||
- priv->op != exthdr->op ||
- priv->flags != exthdr->flags ||
- priv->offset != exthdr->offset ||
- priv->len != exthdr->len) {
- nft_reg_track_update(track, expr, priv->dreg, priv->len);
- return false;
- }
-
- if (!track->regs[priv->dreg].bitwise)
- return true;
-
- return nft_expr_reduce_bitwise(track, expr);
-}
-
static const struct nft_expr_ops nft_exthdr_ipv6_ops = {
.type = &nft_exthdr_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_exthdr)),
.eval = nft_exthdr_ipv6_eval,
.init = nft_exthdr_init,
.dump = nft_exthdr_dump,
- .reduce = nft_exthdr_reduce,
};
static const struct nft_expr_ops nft_exthdr_ipv4_ops = {
@@ -743,7 +715,6 @@ static const struct nft_expr_ops nft_ext
.eval = nft_exthdr_ipv4_eval,
.init = nft_exthdr_ipv4_init,
.dump = nft_exthdr_dump,
- .reduce = nft_exthdr_reduce,
};
static const struct nft_expr_ops nft_exthdr_tcp_ops = {
@@ -752,7 +723,6 @@ static const struct nft_expr_ops nft_ext
.eval = nft_exthdr_tcp_eval,
.init = nft_exthdr_init,
.dump = nft_exthdr_dump,
- .reduce = nft_exthdr_reduce,
};
static const struct nft_expr_ops nft_exthdr_tcp_set_ops = {
@@ -761,7 +731,6 @@ static const struct nft_expr_ops nft_ext
.eval = nft_exthdr_tcp_set_eval,
.init = nft_exthdr_tcp_set_init,
.dump = nft_exthdr_dump_set,
- .reduce = NFT_REDUCE_READONLY,
};
static const struct nft_expr_ops nft_exthdr_tcp_strip_ops = {
@@ -770,7 +739,6 @@ static const struct nft_expr_ops nft_ext
.eval = nft_exthdr_tcp_strip_eval,
.init = nft_exthdr_tcp_strip_init,
.dump = nft_exthdr_dump_strip,
- .reduce = NFT_REDUCE_READONLY,
};
static const struct nft_expr_ops nft_exthdr_sctp_ops = {
@@ -779,7 +747,6 @@ static const struct nft_expr_ops nft_ext
.eval = nft_exthdr_sctp_eval,
.init = nft_exthdr_init,
.dump = nft_exthdr_dump,
- .reduce = nft_exthdr_reduce,
};
static const struct nft_expr_ops nft_exthdr_dccp_ops = {
@@ -788,7 +755,6 @@ static const struct nft_expr_ops nft_ext
.eval = nft_exthdr_dccp_eval,
.init = nft_exthdr_dccp_init,
.dump = nft_exthdr_dump,
- .reduce = nft_exthdr_reduce,
};
static const struct nft_expr_ops *
--- a/net/netfilter/nft_fib.c
+++ b/net/netfilter/nft_fib.c
@@ -168,48 +168,6 @@ void nft_fib_store_result(void *reg, con
}
EXPORT_SYMBOL_GPL(nft_fib_store_result);
-bool nft_fib_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- const struct nft_fib *priv = nft_expr_priv(expr);
- unsigned int len = NFT_REG32_SIZE;
- const struct nft_fib *fib;
-
- switch (priv->result) {
- case NFT_FIB_RESULT_OIF:
- break;
- case NFT_FIB_RESULT_OIFNAME:
- if (priv->flags & NFTA_FIB_F_PRESENT)
- len = NFT_REG32_SIZE;
- else
- len = IFNAMSIZ;
- break;
- case NFT_FIB_RESULT_ADDRTYPE:
- break;
- default:
- WARN_ON_ONCE(1);
- break;
- }
-
- if (!nft_reg_track_cmp(track, expr, priv->dreg)) {
- nft_reg_track_update(track, expr, priv->dreg, len);
- return false;
- }
-
- fib = nft_expr_priv(track->regs[priv->dreg].selector);
- if (priv->result != fib->result ||
- priv->flags != fib->flags) {
- nft_reg_track_update(track, expr, priv->dreg, len);
- return false;
- }
-
- if (!track->regs[priv->dreg].bitwise)
- return true;
-
- return false;
-}
-EXPORT_SYMBOL_GPL(nft_fib_reduce);
-
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Query routing table from nftables");
MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");
--- a/net/netfilter/nft_fib_inet.c
+++ b/net/netfilter/nft_fib_inet.c
@@ -49,7 +49,6 @@ static const struct nft_expr_ops nft_fib
.init = nft_fib_init,
.dump = nft_fib_dump,
.validate = nft_fib_validate,
- .reduce = nft_fib_reduce,
};
static struct nft_expr_type nft_fib_inet_type __read_mostly = {
--- a/net/netfilter/nft_fib_netdev.c
+++ b/net/netfilter/nft_fib_netdev.c
@@ -58,7 +58,6 @@ static const struct nft_expr_ops nft_fib
.init = nft_fib_init,
.dump = nft_fib_dump,
.validate = nft_fib_validate,
- .reduce = nft_fib_reduce,
};
static struct nft_expr_type nft_fib_netdev_type __read_mostly = {
--- a/net/netfilter/nft_flow_offload.c
+++ b/net/netfilter/nft_flow_offload.c
@@ -483,7 +483,6 @@ static const struct nft_expr_ops nft_flo
.destroy = nft_flow_offload_destroy,
.validate = nft_flow_offload_validate,
.dump = nft_flow_offload_dump,
- .reduce = NFT_REDUCE_READONLY,
};
static struct nft_expr_type nft_flow_offload_type __read_mostly = {
--- a/net/netfilter/nft_fwd_netdev.c
+++ b/net/netfilter/nft_fwd_netdev.c
@@ -228,7 +228,6 @@ static const struct nft_expr_ops nft_fwd
.init = nft_fwd_neigh_init,
.dump = nft_fwd_neigh_dump,
.validate = nft_fwd_validate,
- .reduce = NFT_REDUCE_READONLY,
};
static const struct nft_expr_ops nft_fwd_netdev_ops = {
@@ -238,7 +237,6 @@ static const struct nft_expr_ops nft_fwd
.init = nft_fwd_netdev_init,
.dump = nft_fwd_netdev_dump,
.validate = nft_fwd_validate,
- .reduce = NFT_REDUCE_READONLY,
.offload = nft_fwd_netdev_offload,
.offload_action = nft_fwd_netdev_offload_action,
};
--- a/net/netfilter/nft_hash.c
+++ b/net/netfilter/nft_hash.c
@@ -166,16 +166,6 @@ nla_put_failure:
return -1;
}
-static bool nft_jhash_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- const struct nft_jhash *priv = nft_expr_priv(expr);
-
- nft_reg_track_cancel(track, priv->dreg, sizeof(u32));
-
- return false;
-}
-
static int nft_symhash_dump(struct sk_buff *skb,
const struct nft_expr *expr, bool reset)
{
@@ -196,30 +186,6 @@ nla_put_failure:
return -1;
}
-static bool nft_symhash_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- struct nft_symhash *priv = nft_expr_priv(expr);
- struct nft_symhash *symhash;
-
- if (!nft_reg_track_cmp(track, expr, priv->dreg)) {
- nft_reg_track_update(track, expr, priv->dreg, sizeof(u32));
- return false;
- }
-
- symhash = nft_expr_priv(track->regs[priv->dreg].selector);
- if (priv->offset != symhash->offset ||
- priv->modulus != symhash->modulus) {
- nft_reg_track_update(track, expr, priv->dreg, sizeof(u32));
- return false;
- }
-
- if (!track->regs[priv->dreg].bitwise)
- return true;
-
- return false;
-}
-
static struct nft_expr_type nft_hash_type;
static const struct nft_expr_ops nft_jhash_ops = {
.type = &nft_hash_type,
@@ -227,7 +193,6 @@ static const struct nft_expr_ops nft_jha
.eval = nft_jhash_eval,
.init = nft_jhash_init,
.dump = nft_jhash_dump,
- .reduce = nft_jhash_reduce,
};
static const struct nft_expr_ops nft_symhash_ops = {
@@ -236,7 +201,6 @@ static const struct nft_expr_ops nft_sym
.eval = nft_symhash_eval,
.init = nft_symhash_init,
.dump = nft_symhash_dump,
- .reduce = nft_symhash_reduce,
};
static const struct nft_expr_ops *
--- a/net/netfilter/nft_immediate.c
+++ b/net/netfilter/nft_immediate.c
@@ -320,17 +320,6 @@ static bool nft_immediate_offload_action
return false;
}
-static bool nft_immediate_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- const struct nft_immediate_expr *priv = nft_expr_priv(expr);
-
- if (priv->dreg != NFT_REG_VERDICT)
- nft_reg_track_cancel(track, priv->dreg, priv->dlen);
-
- return false;
-}
-
static const struct nft_expr_ops nft_imm_ops = {
.type = &nft_imm_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_immediate_expr)),
@@ -341,7 +330,6 @@ static const struct nft_expr_ops nft_imm
.destroy = nft_immediate_destroy,
.dump = nft_immediate_dump,
.validate = nft_immediate_validate,
- .reduce = nft_immediate_reduce,
.offload = nft_immediate_offload,
.offload_action = nft_immediate_offload_action,
};
--- a/net/netfilter/nft_last.c
+++ b/net/netfilter/nft_last.c
@@ -125,7 +125,6 @@ static const struct nft_expr_ops nft_las
.destroy = nft_last_destroy,
.clone = nft_last_clone,
.dump = nft_last_dump,
- .reduce = NFT_REDUCE_READONLY,
};
struct nft_expr_type nft_last_type __read_mostly = {
--- a/net/netfilter/nft_limit.c
+++ b/net/netfilter/nft_limit.c
@@ -243,7 +243,6 @@ static const struct nft_expr_ops nft_lim
.destroy = nft_limit_pkts_destroy,
.clone = nft_limit_pkts_clone,
.dump = nft_limit_pkts_dump,
- .reduce = NFT_REDUCE_READONLY,
};
static void nft_limit_bytes_eval(const struct nft_expr *expr,
@@ -299,7 +298,6 @@ static const struct nft_expr_ops nft_lim
.dump = nft_limit_bytes_dump,
.clone = nft_limit_bytes_clone,
.destroy = nft_limit_bytes_destroy,
- .reduce = NFT_REDUCE_READONLY,
};
static const struct nft_expr_ops *
--- a/net/netfilter/nft_log.c
+++ b/net/netfilter/nft_log.c
@@ -291,7 +291,6 @@ static const struct nft_expr_ops nft_log
.init = nft_log_init,
.destroy = nft_log_destroy,
.dump = nft_log_dump,
- .reduce = NFT_REDUCE_READONLY,
};
static struct nft_expr_type nft_log_type __read_mostly = {
--- a/net/netfilter/nft_lookup.c
+++ b/net/netfilter/nft_lookup.c
@@ -269,17 +269,6 @@ static int nft_lookup_validate(const str
return 0;
}
-static bool nft_lookup_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- const struct nft_lookup *priv = nft_expr_priv(expr);
-
- if (priv->set->flags & NFT_SET_MAP)
- nft_reg_track_cancel(track, priv->dreg, priv->set->dlen);
-
- return false;
-}
-
static const struct nft_expr_ops nft_lookup_ops = {
.type = &nft_lookup_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_lookup)),
@@ -290,7 +279,6 @@ static const struct nft_expr_ops nft_loo
.destroy = nft_lookup_destroy,
.dump = nft_lookup_dump,
.validate = nft_lookup_validate,
- .reduce = nft_lookup_reduce,
};
struct nft_expr_type nft_lookup_type __read_mostly = {
--- a/net/netfilter/nft_masq.c
+++ b/net/netfilter/nft_masq.c
@@ -143,7 +143,6 @@ static const struct nft_expr_ops nft_mas
.destroy = nft_masq_ipv4_destroy,
.dump = nft_masq_dump,
.validate = nft_masq_validate,
- .reduce = NFT_REDUCE_READONLY,
};
static struct nft_expr_type nft_masq_ipv4_type __read_mostly = {
@@ -171,7 +170,6 @@ static const struct nft_expr_ops nft_mas
.destroy = nft_masq_ipv6_destroy,
.dump = nft_masq_dump,
.validate = nft_masq_validate,
- .reduce = NFT_REDUCE_READONLY,
};
static struct nft_expr_type nft_masq_ipv6_type __read_mostly = {
@@ -213,7 +211,6 @@ static const struct nft_expr_ops nft_mas
.destroy = nft_masq_inet_destroy,
.dump = nft_masq_dump,
.validate = nft_masq_validate,
- .reduce = NFT_REDUCE_READONLY,
};
static struct nft_expr_type nft_masq_inet_type __read_mostly = {
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -742,60 +742,16 @@ static int nft_meta_get_offload(struct n
return 0;
}
-bool nft_meta_get_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- const struct nft_meta *priv = nft_expr_priv(expr);
- const struct nft_meta *meta;
-
- if (!nft_reg_track_cmp(track, expr, priv->dreg)) {
- nft_reg_track_update(track, expr, priv->dreg, priv->len);
- return false;
- }
-
- meta = nft_expr_priv(track->regs[priv->dreg].selector);
- if (priv->key != meta->key ||
- priv->dreg != meta->dreg) {
- nft_reg_track_update(track, expr, priv->dreg, priv->len);
- return false;
- }
-
- if (!track->regs[priv->dreg].bitwise)
- return true;
-
- return nft_expr_reduce_bitwise(track, expr);
-}
-EXPORT_SYMBOL_GPL(nft_meta_get_reduce);
-
static const struct nft_expr_ops nft_meta_get_ops = {
.type = &nft_meta_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_meta)),
.eval = nft_meta_get_eval,
.init = nft_meta_get_init,
.dump = nft_meta_get_dump,
- .reduce = nft_meta_get_reduce,
.validate = nft_meta_get_validate,
.offload = nft_meta_get_offload,
};
-static bool nft_meta_set_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- int i;
-
- for (i = 0; i < NFT_REG32_NUM; i++) {
- if (!track->regs[i].selector)
- continue;
-
- if (track->regs[i].selector->ops != &nft_meta_get_ops)
- continue;
-
- __nft_reg_track_cancel(track, i);
- }
-
- return false;
-}
-
static const struct nft_expr_ops nft_meta_set_ops = {
.type = &nft_meta_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_meta)),
@@ -803,7 +759,6 @@ static const struct nft_expr_ops nft_met
.init = nft_meta_set_init,
.destroy = nft_meta_set_destroy,
.dump = nft_meta_set_dump,
- .reduce = nft_meta_set_reduce,
.validate = nft_meta_set_validate,
};
--- a/net/netfilter/nft_nat.c
+++ b/net/netfilter/nft_nat.c
@@ -320,7 +320,6 @@ static const struct nft_expr_ops nft_nat
.destroy = nft_nat_destroy,
.dump = nft_nat_dump,
.validate = nft_nat_validate,
- .reduce = NFT_REDUCE_READONLY,
};
static struct nft_expr_type nft_nat_type __read_mostly = {
@@ -351,7 +350,6 @@ static const struct nft_expr_ops nft_nat
.destroy = nft_nat_destroy,
.dump = nft_nat_dump,
.validate = nft_nat_validate,
- .reduce = NFT_REDUCE_READONLY,
};
static struct nft_expr_type nft_inet_nat_type __read_mostly = {
--- a/net/netfilter/nft_numgen.c
+++ b/net/netfilter/nft_numgen.c
@@ -84,16 +84,6 @@ err:
return err;
}
-static bool nft_ng_inc_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- const struct nft_ng_inc *priv = nft_expr_priv(expr);
-
- nft_reg_track_cancel(track, priv->dreg, NFT_REG32_SIZE);
-
- return false;
-}
-
static int nft_ng_dump(struct sk_buff *skb, enum nft_registers dreg,
u32 modulus, enum nft_ng_types type, u32 offset)
{
@@ -178,16 +168,6 @@ static int nft_ng_random_dump(struct sk_
priv->offset);
}
-static bool nft_ng_random_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- const struct nft_ng_random *priv = nft_expr_priv(expr);
-
- nft_reg_track_cancel(track, priv->dreg, NFT_REG32_SIZE);
-
- return false;
-}
-
static struct nft_expr_type nft_ng_type;
static const struct nft_expr_ops nft_ng_inc_ops = {
.type = &nft_ng_type,
@@ -196,7 +176,6 @@ static const struct nft_expr_ops nft_ng_
.init = nft_ng_inc_init,
.destroy = nft_ng_inc_destroy,
.dump = nft_ng_inc_dump,
- .reduce = nft_ng_inc_reduce,
};
static const struct nft_expr_ops nft_ng_random_ops = {
@@ -205,7 +184,6 @@ static const struct nft_expr_ops nft_ng_
.eval = nft_ng_random_eval,
.init = nft_ng_random_init,
.dump = nft_ng_random_dump,
- .reduce = nft_ng_random_reduce,
};
static const struct nft_expr_ops *
--- a/net/netfilter/nft_objref.c
+++ b/net/netfilter/nft_objref.c
@@ -123,7 +123,6 @@ static const struct nft_expr_ops nft_obj
.deactivate = nft_objref_deactivate,
.dump = nft_objref_dump,
.validate = nft_objref_validate,
- .reduce = NFT_REDUCE_READONLY,
};
struct nft_objref_map {
@@ -245,7 +244,6 @@ static const struct nft_expr_ops nft_obj
.destroy = nft_objref_map_destroy,
.dump = nft_objref_map_dump,
.validate = nft_objref_map_validate,
- .reduce = NFT_REDUCE_READONLY,
};
static const struct nft_expr_ops *
--- a/net/netfilter/nft_osf.c
+++ b/net/netfilter/nft_osf.c
@@ -131,30 +131,6 @@ static int nft_osf_validate(const struct
return nft_chain_validate_hooks(ctx->chain, hooks);
}
-static bool nft_osf_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- struct nft_osf *priv = nft_expr_priv(expr);
- struct nft_osf *osf;
-
- if (!nft_reg_track_cmp(track, expr, priv->dreg)) {
- nft_reg_track_update(track, expr, priv->dreg, NFT_OSF_MAXGENRELEN);
- return false;
- }
-
- osf = nft_expr_priv(track->regs[priv->dreg].selector);
- if (priv->flags != osf->flags ||
- priv->ttl != osf->ttl) {
- nft_reg_track_update(track, expr, priv->dreg, NFT_OSF_MAXGENRELEN);
- return false;
- }
-
- if (!track->regs[priv->dreg].bitwise)
- return true;
-
- return false;
-}
-
static struct nft_expr_type nft_osf_type;
static const struct nft_expr_ops nft_osf_op = {
.eval = nft_osf_eval,
@@ -163,7 +139,6 @@ static const struct nft_expr_ops nft_osf
.dump = nft_osf_dump,
.type = &nft_osf_type,
.validate = nft_osf_validate,
- .reduce = nft_osf_reduce,
};
static struct nft_expr_type nft_osf_type __read_mostly = {
--- a/net/netfilter/nft_payload.c
+++ b/net/netfilter/nft_payload.c
@@ -250,31 +250,6 @@ nla_put_failure:
return -1;
}
-static bool nft_payload_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- const struct nft_payload *priv = nft_expr_priv(expr);
- const struct nft_payload *payload;
-
- if (!nft_reg_track_cmp(track, expr, priv->dreg)) {
- nft_reg_track_update(track, expr, priv->dreg, priv->len);
- return false;
- }
-
- payload = nft_expr_priv(track->regs[priv->dreg].selector);
- if (priv->base != payload->base ||
- priv->offset != payload->offset ||
- priv->len != payload->len) {
- nft_reg_track_update(track, expr, priv->dreg, priv->len);
- return false;
- }
-
- if (!track->regs[priv->dreg].bitwise)
- return true;
-
- return nft_expr_reduce_bitwise(track, expr);
-}
-
static bool nft_payload_offload_mask(struct nft_offload_reg *reg,
u32 priv_len, u32 field_len)
{
@@ -578,7 +553,6 @@ static const struct nft_expr_ops nft_pay
.eval = nft_payload_eval,
.init = nft_payload_init,
.dump = nft_payload_dump,
- .reduce = nft_payload_reduce,
.offload = nft_payload_offload,
};
@@ -588,7 +562,6 @@ const struct nft_expr_ops nft_payload_fa
.eval = nft_payload_eval,
.init = nft_payload_init,
.dump = nft_payload_dump,
- .reduce = nft_payload_reduce,
.offload = nft_payload_offload,
};
@@ -1008,32 +981,12 @@ nla_put_failure:
return -1;
}
-static bool nft_payload_set_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- int i;
-
- for (i = 0; i < NFT_REG32_NUM; i++) {
- if (!track->regs[i].selector)
- continue;
-
- if (track->regs[i].selector->ops != &nft_payload_ops &&
- track->regs[i].selector->ops != &nft_payload_fast_ops)
- continue;
-
- __nft_reg_track_cancel(track, i);
- }
-
- return false;
-}
-
static const struct nft_expr_ops nft_payload_set_ops = {
.type = &nft_payload_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_payload_set)),
.eval = nft_payload_set_eval,
.init = nft_payload_set_init,
.dump = nft_payload_set_dump,
- .reduce = nft_payload_set_reduce,
};
static const struct nft_expr_ops *
--- a/net/netfilter/nft_queue.c
+++ b/net/netfilter/nft_queue.c
@@ -191,7 +191,6 @@ static const struct nft_expr_ops nft_que
.init = nft_queue_init,
.dump = nft_queue_dump,
.validate = nft_queue_validate,
- .reduce = NFT_REDUCE_READONLY,
};
static const struct nft_expr_ops nft_queue_sreg_ops = {
@@ -201,7 +200,6 @@ static const struct nft_expr_ops nft_que
.init = nft_queue_sreg_init,
.dump = nft_queue_sreg_dump,
.validate = nft_queue_validate,
- .reduce = NFT_REDUCE_READONLY,
};
static const struct nft_expr_ops *
--- a/net/netfilter/nft_quota.c
+++ b/net/netfilter/nft_quota.c
@@ -266,7 +266,6 @@ static const struct nft_expr_ops nft_quo
.destroy = nft_quota_destroy,
.clone = nft_quota_clone,
.dump = nft_quota_dump,
- .reduce = NFT_REDUCE_READONLY,
};
static struct nft_expr_type nft_quota_type __read_mostly = {
--- a/net/netfilter/nft_range.c
+++ b/net/netfilter/nft_range.c
@@ -138,7 +138,6 @@ static const struct nft_expr_ops nft_ran
.eval = nft_range_eval,
.init = nft_range_init,
.dump = nft_range_dump,
- .reduce = NFT_REDUCE_READONLY,
};
struct nft_expr_type nft_range_type __read_mostly = {
--- a/net/netfilter/nft_redir.c
+++ b/net/netfilter/nft_redir.c
@@ -146,7 +146,6 @@ static const struct nft_expr_ops nft_red
.destroy = nft_redir_ipv4_destroy,
.dump = nft_redir_dump,
.validate = nft_redir_validate,
- .reduce = NFT_REDUCE_READONLY,
};
static struct nft_expr_type nft_redir_ipv4_type __read_mostly = {
@@ -174,7 +173,6 @@ static const struct nft_expr_ops nft_red
.destroy = nft_redir_ipv6_destroy,
.dump = nft_redir_dump,
.validate = nft_redir_validate,
- .reduce = NFT_REDUCE_READONLY,
};
static struct nft_expr_type nft_redir_ipv6_type __read_mostly = {
@@ -203,7 +201,6 @@ static const struct nft_expr_ops nft_red
.destroy = nft_redir_inet_destroy,
.dump = nft_redir_dump,
.validate = nft_redir_validate,
- .reduce = NFT_REDUCE_READONLY,
};
static struct nft_expr_type nft_redir_inet_type __read_mostly = {
--- a/net/netfilter/nft_reject_inet.c
+++ b/net/netfilter/nft_reject_inet.c
@@ -79,7 +79,6 @@ static const struct nft_expr_ops nft_rej
.init = nft_reject_init,
.dump = nft_reject_dump,
.validate = nft_reject_inet_validate,
- .reduce = NFT_REDUCE_READONLY,
};
static struct nft_expr_type nft_reject_inet_type __read_mostly = {
--- a/net/netfilter/nft_reject_netdev.c
+++ b/net/netfilter/nft_reject_netdev.c
@@ -158,7 +158,6 @@ static const struct nft_expr_ops nft_rej
.init = nft_reject_init,
.dump = nft_reject_dump,
.validate = nft_reject_netdev_validate,
- .reduce = NFT_REDUCE_READONLY,
};
static struct nft_expr_type nft_reject_netdev_type __read_mostly = {
--- a/net/netfilter/nft_rt.c
+++ b/net/netfilter/nft_rt.c
@@ -195,7 +195,6 @@ static const struct nft_expr_ops nft_rt_
.init = nft_rt_get_init,
.dump = nft_rt_get_dump,
.validate = nft_rt_validate,
- .reduce = NFT_REDUCE_READONLY,
};
struct nft_expr_type nft_rt_type __read_mostly = {
--- a/net/netfilter/nft_socket.c
+++ b/net/netfilter/nft_socket.c
@@ -249,31 +249,6 @@ static int nft_socket_dump(struct sk_buf
return 0;
}
-static bool nft_socket_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- const struct nft_socket *priv = nft_expr_priv(expr);
- const struct nft_socket *socket;
-
- if (!nft_reg_track_cmp(track, expr, priv->dreg)) {
- nft_reg_track_update(track, expr, priv->dreg, priv->len);
- return false;
- }
-
- socket = nft_expr_priv(track->regs[priv->dreg].selector);
- if (priv->key != socket->key ||
- priv->dreg != socket->dreg ||
- priv->level != socket->level) {
- nft_reg_track_update(track, expr, priv->dreg, priv->len);
- return false;
- }
-
- if (!track->regs[priv->dreg].bitwise)
- return true;
-
- return nft_expr_reduce_bitwise(track, expr);
-}
-
static int nft_socket_validate(const struct nft_ctx *ctx,
const struct nft_expr *expr)
{
@@ -296,7 +271,6 @@ static const struct nft_expr_ops nft_soc
.init = nft_socket_init,
.dump = nft_socket_dump,
.validate = nft_socket_validate,
- .reduce = nft_socket_reduce,
};
static struct nft_expr_type nft_socket_type __read_mostly = {
--- a/net/netfilter/nft_synproxy.c
+++ b/net/netfilter/nft_synproxy.c
@@ -290,7 +290,6 @@ static const struct nft_expr_ops nft_syn
.dump = nft_synproxy_dump,
.type = &nft_synproxy_type,
.validate = nft_synproxy_validate,
- .reduce = NFT_REDUCE_READONLY,
};
static struct nft_expr_type nft_synproxy_type __read_mostly = {
--- a/net/netfilter/nft_tproxy.c
+++ b/net/netfilter/nft_tproxy.c
@@ -331,7 +331,6 @@ static const struct nft_expr_ops nft_tpr
.init = nft_tproxy_init,
.destroy = nft_tproxy_destroy,
.dump = nft_tproxy_dump,
- .reduce = NFT_REDUCE_READONLY,
.validate = nft_tproxy_validate,
};
--- a/net/netfilter/nft_tunnel.c
+++ b/net/netfilter/nft_tunnel.c
@@ -124,31 +124,6 @@ nla_put_failure:
return -1;
}
-static bool nft_tunnel_get_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- const struct nft_tunnel *priv = nft_expr_priv(expr);
- const struct nft_tunnel *tunnel;
-
- if (!nft_reg_track_cmp(track, expr, priv->dreg)) {
- nft_reg_track_update(track, expr, priv->dreg, priv->len);
- return false;
- }
-
- tunnel = nft_expr_priv(track->regs[priv->dreg].selector);
- if (priv->key != tunnel->key ||
- priv->dreg != tunnel->dreg ||
- priv->mode != tunnel->mode) {
- nft_reg_track_update(track, expr, priv->dreg, priv->len);
- return false;
- }
-
- if (!track->regs[priv->dreg].bitwise)
- return true;
-
- return false;
-}
-
static struct nft_expr_type nft_tunnel_type;
static const struct nft_expr_ops nft_tunnel_get_ops = {
.type = &nft_tunnel_type,
@@ -156,7 +131,6 @@ static const struct nft_expr_ops nft_tun
.eval = nft_tunnel_get_eval,
.init = nft_tunnel_get_init,
.dump = nft_tunnel_get_dump,
- .reduce = nft_tunnel_get_reduce,
};
static struct nft_expr_type nft_tunnel_type __read_mostly = {
--- a/net/netfilter/nft_xfrm.c
+++ b/net/netfilter/nft_xfrm.c
@@ -258,32 +258,6 @@ static int nft_xfrm_validate(const struc
return nft_chain_validate_hooks(ctx->chain, hooks);
}
-static bool nft_xfrm_reduce(struct nft_regs_track *track,
- const struct nft_expr *expr)
-{
- const struct nft_xfrm *priv = nft_expr_priv(expr);
- const struct nft_xfrm *xfrm;
-
- if (!nft_reg_track_cmp(track, expr, priv->dreg)) {
- nft_reg_track_update(track, expr, priv->dreg, priv->len);
- return false;
- }
-
- xfrm = nft_expr_priv(track->regs[priv->dreg].selector);
- if (priv->key != xfrm->key ||
- priv->dreg != xfrm->dreg ||
- priv->dir != xfrm->dir ||
- priv->spnum != xfrm->spnum) {
- nft_reg_track_update(track, expr, priv->dreg, priv->len);
- return false;
- }
-
- if (!track->regs[priv->dreg].bitwise)
- return true;
-
- return nft_expr_reduce_bitwise(track, expr);
-}
-
static struct nft_expr_type nft_xfrm_type;
static const struct nft_expr_ops nft_xfrm_get_ops = {
.type = &nft_xfrm_type,
@@ -292,7 +266,6 @@ static const struct nft_expr_ops nft_xfr
.init = nft_xfrm_get_init,
.dump = nft_xfrm_get_dump,
.validate = nft_xfrm_validate,
- .reduce = nft_xfrm_reduce,
};
static struct nft_expr_type nft_xfrm_type __read_mostly = {
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 509/602] netfilter: nft_fib: reject fib expression on the netdev egress hook
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (507 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 508/602] netfilter: nf_tables: remove register tracking infrastructure Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 510/602] gpu: Move DRM buddy allocator one level up (part two) Greg Kroah-Hartman
` (96 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Theodor Arsenij Larionov-Trichkine,
Florian Westphal, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Theodor Arsenij Larionov-Trichkine <theodorlarionov@gmail.com>
[ Upstream commit d07955dd34ecae17d35d8c7d0a273a3fba653a8c ]
A fib expression in a netdev egress base chain dereferences nft_in(pkt),
NULL on the transmit path, causing a NULL pointer dereference at eval.
nft_fib_validate() masks the hook with NF_INET_* values, but netdev hook
numbers are a separate enum that aliases them (NF_NETDEV_EGRESS ==
NF_INET_LOCAL_IN), so an egress chain passes validation and then faults.
Add nft_fib_netdev_validate() that limits each result/flag to the netdev
hook where the device it reads exists: the input-device cases (OIF,
OIFNAME, ADDRTYPE with F_IIF) to ingress, the output-device case (ADDRTYPE
with F_OIF) to egress, ADDRTYPE with no device flag to both. Also restrict
nft_fib_validate() to NFPROTO_IPV4/IPV6/INET so its NF_INET_* masks are
not applied to another family's hooks.
Fixes: 42df6e1d221d ("netfilter: Introduce egress hook")
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/netfilter-devel/ajxsjcDOnwllMfoR@strlen.de/
Signed-off-by: Theodor Arsenij Larionov-Trichkine <theodorlarionov@gmail.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/netfilter/nft_fib.c | 9 +++++++++
net/netfilter/nft_fib_netdev.c | 29 ++++++++++++++++++++++++++++-
2 files changed, 37 insertions(+), 1 deletion(-)
--- a/net/netfilter/nft_fib.c
+++ b/net/netfilter/nft_fib.c
@@ -31,6 +31,15 @@ int nft_fib_validate(const struct nft_ct
const struct nft_fib *priv = nft_expr_priv(expr);
unsigned int hooks;
+ switch (ctx->family) {
+ case NFPROTO_IPV4:
+ case NFPROTO_IPV6:
+ case NFPROTO_INET:
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
switch (priv->result) {
case NFT_FIB_RESULT_OIF:
case NFT_FIB_RESULT_OIFNAME:
--- a/net/netfilter/nft_fib_netdev.c
+++ b/net/netfilter/nft_fib_netdev.c
@@ -50,6 +50,33 @@ static void nft_fib_netdev_eval(const st
regs->verdict.code = NFT_BREAK;
}
+static int nft_fib_netdev_validate(const struct nft_ctx *ctx,
+ const struct nft_expr *expr)
+{
+ const struct nft_fib *priv = nft_expr_priv(expr);
+ unsigned int hooks;
+
+ switch (priv->result) {
+ case NFT_FIB_RESULT_OIF:
+ case NFT_FIB_RESULT_OIFNAME:
+ hooks = (1 << NF_NETDEV_INGRESS);
+ break;
+ case NFT_FIB_RESULT_ADDRTYPE:
+ if (priv->flags & NFTA_FIB_F_IIF)
+ hooks = (1 << NF_NETDEV_INGRESS);
+ else if (priv->flags & NFTA_FIB_F_OIF)
+ hooks = (1 << NF_NETDEV_EGRESS);
+ else
+ hooks = (1 << NF_NETDEV_INGRESS) |
+ (1 << NF_NETDEV_EGRESS);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return nft_chain_validate_hooks(ctx->chain, hooks);
+}
+
static struct nft_expr_type nft_fib_netdev_type;
static const struct nft_expr_ops nft_fib_netdev_ops = {
.type = &nft_fib_netdev_type,
@@ -57,7 +84,7 @@ static const struct nft_expr_ops nft_fib
.eval = nft_fib_netdev_eval,
.init = nft_fib_init,
.dump = nft_fib_dump,
- .validate = nft_fib_validate,
+ .validate = nft_fib_netdev_validate,
};
static struct nft_expr_type nft_fib_netdev_type __read_mostly = {
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 510/602] gpu: Move DRM buddy allocator one level up (part two)
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (508 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 509/602] netfilter: nft_fib: reject fib expression on the netdev egress hook Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 511/602] gpu/buddy: bail out of try_harder when alignment cannot be honoured Greg Kroah-Hartman
` (95 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Joel Fernandes, Dave Airlie,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joel Fernandes <joelagnelf@nvidia.com>
[ Upstream commit ba110db8e1bc206c13fd7d985e79b033f53bfdea ]
Move the DRM buddy allocator one level up so that it can be used by GPU
drivers (example, nova-core) that have usecases other than DRM (such as
VFIO vGPU support). Modify the API, structures and Kconfigs to use
"gpu_buddy" terminology. Adapt the drivers and tests to use the new API.
The commit cannot be split due to bisectability, however no functional
change is intended. Verified by running K-UNIT tests and build tested
various configurations.
Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
Reviewed-by: Dave Airlie <airlied@redhat.com>
[airlied: I've split this into two so git can find copies easier.
I've also just nuked drm_random library, that stuff needs to be done
elsewhere and only the buddy tests seem to be using it].
Signed-off-by: Dave Airlie <airlied@redhat.com>
Stable-dep-of: 56bc6384314f ("gpu/buddy: bail out of try_harder when alignment cannot be honoured")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
Documentation/gpu/drm-mm.rst | 10
drivers/gpu/Kconfig | 13
drivers/gpu/Makefile | 3
drivers/gpu/buddy.c | 1322 +++++++++++++++++++
drivers/gpu/drm/Kconfig | 6
drivers/gpu/drm/Makefile | 1
drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h | 12
drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 77 -
drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h | 18
drivers/gpu/drm/drm_buddy.c | 1279 ------------------
drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 2
drivers/gpu/drm/i915/i915_scatterlist.c | 10
drivers/gpu/drm/i915/i915_ttm_buddy_manager.c | 55
drivers/gpu/drm/i915/i915_ttm_buddy_manager.h | 4
drivers/gpu/drm/i915/selftests/intel_memory_region.c | 20
drivers/gpu/drm/lib/drm_random.c | 43
drivers/gpu/drm/lib/drm_random.h | 28
drivers/gpu/drm/tests/Makefile | 1
drivers/gpu/drm/tests/drm_buddy_test.c | 778 -----------
drivers/gpu/drm/tests/drm_exec_test.c | 2
drivers/gpu/drm/tests/drm_mm_test.c | 2
drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c | 4
drivers/gpu/drm/ttm/tests/ttm_mock_manager.c | 18
drivers/gpu/drm/ttm/tests/ttm_mock_manager.h | 4
drivers/gpu/drm/xe/xe_res_cursor.h | 34
drivers/gpu/drm/xe/xe_ttm_vram_mgr.c | 73 -
drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h | 4
drivers/gpu/tests/Makefile | 4
drivers/gpu/tests/gpu_buddy_test.c | 778 +++++++++++
drivers/gpu/tests/gpu_random.c | 43
drivers/gpu/tests/gpu_random.h | 28
drivers/video/Kconfig | 1
include/drm/drm_buddy.h | 174 --
include/linux/gpu_buddy.h | 188 ++
34 files changed, 2576 insertions(+), 2463 deletions(-)
create mode 100644 drivers/gpu/Kconfig
create mode 100644 drivers/gpu/buddy.c
create mode 100644 drivers/gpu/tests/Makefile
rename drivers/gpu/{drm/tests/drm_buddy_test.c => tests/gpu_buddy_test.c} (70%)
rename drivers/gpu/{drm/lib/drm_random.c => tests/gpu_random.c} (58%)
rename drivers/gpu/{drm/lib/drm_random.h => tests/gpu_random.h} (53%)
create mode 100644 include/linux/gpu_buddy.h
--- a/Documentation/gpu/drm-mm.rst
+++ b/Documentation/gpu/drm-mm.rst
@@ -509,8 +509,14 @@ DRM GPUVM Function References
DRM Buddy Allocator
===================
-DRM Buddy Function References
------------------------------
+Buddy Allocator Function References (GPU buddy)
+-----------------------------------------------
+
+.. kernel-doc:: drivers/gpu/buddy.c
+ :export:
+
+DRM Buddy Specific Logging Function References
+----------------------------------------------
.. kernel-doc:: drivers/gpu/drm/drm_buddy.c
:export:
--- /dev/null
+++ b/drivers/gpu/Kconfig
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0
+
+config GPU_BUDDY
+ bool
+ help
+ A page based buddy allocator for GPU memory.
+
+config GPU_BUDDY_KUNIT_TEST
+ tristate "KUnit tests for GPU buddy allocator" if !KUNIT_ALL_TESTS
+ depends on GPU_BUDDY && KUNIT
+ default KUNIT_ALL_TESTS
+ help
+ KUnit tests for the GPU buddy allocator.
--- a/drivers/gpu/Makefile
+++ b/drivers/gpu/Makefile
@@ -2,6 +2,7 @@
# drm/tegra depends on host1x, so if both drivers are built-in care must be
# taken to initialize them in the correct order. Link order is the only way
# to ensure this currently.
-obj-y += host1x/ drm/ vga/
+obj-y += host1x/ drm/ vga/ tests/
obj-$(CONFIG_IMX_IPUV3_CORE) += ipu-v3/
obj-$(CONFIG_TRACE_GPU_MEM) += trace/
+obj-$(CONFIG_GPU_BUDDY) += buddy.o
--- /dev/null
+++ b/drivers/gpu/buddy.c
@@ -0,0 +1,1322 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#include <kunit/test-bug.h>
+
+#include <linux/export.h>
+#include <linux/kmemleak.h>
+#include <linux/module.h>
+#include <linux/sizes.h>
+
+#include <linux/gpu_buddy.h>
+
+static struct kmem_cache *slab_blocks;
+
+static struct gpu_buddy_block *gpu_block_alloc(struct gpu_buddy *mm,
+ struct gpu_buddy_block *parent,
+ unsigned int order,
+ u64 offset)
+{
+ struct gpu_buddy_block *block;
+
+ BUG_ON(order > GPU_BUDDY_MAX_ORDER);
+
+ block = kmem_cache_zalloc(slab_blocks, GFP_KERNEL);
+ if (!block)
+ return NULL;
+
+ block->header = offset;
+ block->header |= order;
+ block->parent = parent;
+
+ RB_CLEAR_NODE(&block->rb);
+
+ BUG_ON(block->header & GPU_BUDDY_HEADER_UNUSED);
+ return block;
+}
+
+static void gpu_block_free(struct gpu_buddy *mm,
+ struct gpu_buddy_block *block)
+{
+ kmem_cache_free(slab_blocks, block);
+}
+
+static enum gpu_buddy_free_tree
+get_block_tree(struct gpu_buddy_block *block)
+{
+ return gpu_buddy_block_is_clear(block) ?
+ GPU_BUDDY_CLEAR_TREE : GPU_BUDDY_DIRTY_TREE;
+}
+
+static struct gpu_buddy_block *
+rbtree_get_free_block(const struct rb_node *node)
+{
+ return node ? rb_entry(node, struct gpu_buddy_block, rb) : NULL;
+}
+
+static struct gpu_buddy_block *
+rbtree_last_free_block(struct rb_root *root)
+{
+ return rbtree_get_free_block(rb_last(root));
+}
+
+static bool rbtree_is_empty(struct rb_root *root)
+{
+ return RB_EMPTY_ROOT(root);
+}
+
+static bool gpu_buddy_block_offset_less(const struct gpu_buddy_block *block,
+ const struct gpu_buddy_block *node)
+{
+ return gpu_buddy_block_offset(block) < gpu_buddy_block_offset(node);
+}
+
+static bool rbtree_block_offset_less(struct rb_node *block,
+ const struct rb_node *node)
+{
+ return gpu_buddy_block_offset_less(rbtree_get_free_block(block),
+ rbtree_get_free_block(node));
+}
+
+static void rbtree_insert(struct gpu_buddy *mm,
+ struct gpu_buddy_block *block,
+ enum gpu_buddy_free_tree tree)
+{
+ rb_add(&block->rb,
+ &mm->free_trees[tree][gpu_buddy_block_order(block)],
+ rbtree_block_offset_less);
+}
+
+static void rbtree_remove(struct gpu_buddy *mm,
+ struct gpu_buddy_block *block)
+{
+ unsigned int order = gpu_buddy_block_order(block);
+ enum gpu_buddy_free_tree tree;
+ struct rb_root *root;
+
+ tree = get_block_tree(block);
+ root = &mm->free_trees[tree][order];
+
+ rb_erase(&block->rb, root);
+ RB_CLEAR_NODE(&block->rb);
+}
+
+static void clear_reset(struct gpu_buddy_block *block)
+{
+ block->header &= ~GPU_BUDDY_HEADER_CLEAR;
+}
+
+static void mark_cleared(struct gpu_buddy_block *block)
+{
+ block->header |= GPU_BUDDY_HEADER_CLEAR;
+}
+
+static void mark_allocated(struct gpu_buddy *mm,
+ struct gpu_buddy_block *block)
+{
+ block->header &= ~GPU_BUDDY_HEADER_STATE;
+ block->header |= GPU_BUDDY_ALLOCATED;
+
+ rbtree_remove(mm, block);
+}
+
+static void mark_free(struct gpu_buddy *mm,
+ struct gpu_buddy_block *block)
+{
+ enum gpu_buddy_free_tree tree;
+
+ block->header &= ~GPU_BUDDY_HEADER_STATE;
+ block->header |= GPU_BUDDY_FREE;
+
+ tree = get_block_tree(block);
+ rbtree_insert(mm, block, tree);
+}
+
+static void mark_split(struct gpu_buddy *mm,
+ struct gpu_buddy_block *block)
+{
+ block->header &= ~GPU_BUDDY_HEADER_STATE;
+ block->header |= GPU_BUDDY_SPLIT;
+
+ rbtree_remove(mm, block);
+}
+
+static inline bool overlaps(u64 s1, u64 e1, u64 s2, u64 e2)
+{
+ return s1 <= e2 && e1 >= s2;
+}
+
+static inline bool contains(u64 s1, u64 e1, u64 s2, u64 e2)
+{
+ return s1 <= s2 && e1 >= e2;
+}
+
+static struct gpu_buddy_block *
+__get_buddy(struct gpu_buddy_block *block)
+{
+ struct gpu_buddy_block *parent;
+
+ parent = block->parent;
+ if (!parent)
+ return NULL;
+
+ if (parent->left == block)
+ return parent->right;
+
+ return parent->left;
+}
+
+static unsigned int __gpu_buddy_free(struct gpu_buddy *mm,
+ struct gpu_buddy_block *block,
+ bool force_merge)
+{
+ struct gpu_buddy_block *parent;
+ unsigned int order;
+
+ while ((parent = block->parent)) {
+ struct gpu_buddy_block *buddy;
+
+ buddy = __get_buddy(block);
+
+ if (!gpu_buddy_block_is_free(buddy))
+ break;
+
+ if (!force_merge) {
+ /*
+ * Check the block and its buddy clear state and exit
+ * the loop if they both have the dissimilar state.
+ */
+ if (gpu_buddy_block_is_clear(block) !=
+ gpu_buddy_block_is_clear(buddy))
+ break;
+
+ if (gpu_buddy_block_is_clear(block))
+ mark_cleared(parent);
+ }
+
+ rbtree_remove(mm, buddy);
+ if (force_merge && gpu_buddy_block_is_clear(buddy))
+ mm->clear_avail -= gpu_buddy_block_size(mm, buddy);
+
+ gpu_block_free(mm, block);
+ gpu_block_free(mm, buddy);
+
+ block = parent;
+ }
+
+ order = gpu_buddy_block_order(block);
+ mark_free(mm, block);
+
+ return order;
+}
+
+static int __force_merge(struct gpu_buddy *mm,
+ u64 start,
+ u64 end,
+ unsigned int min_order)
+{
+ unsigned int tree, order;
+ int i;
+
+ if (!min_order)
+ return -ENOMEM;
+
+ if (min_order > mm->max_order)
+ return -EINVAL;
+
+ for_each_free_tree(tree) {
+ for (i = min_order - 1; i >= 0; i--) {
+ struct rb_node *iter = rb_last(&mm->free_trees[tree][i]);
+
+ while (iter) {
+ struct gpu_buddy_block *block, *buddy;
+ u64 block_start, block_end;
+
+ block = rbtree_get_free_block(iter);
+ iter = rb_prev(iter);
+
+ if (!block || !block->parent)
+ continue;
+
+ block_start = gpu_buddy_block_offset(block);
+ block_end = block_start + gpu_buddy_block_size(mm, block) - 1;
+
+ if (!contains(start, end, block_start, block_end))
+ continue;
+
+ buddy = __get_buddy(block);
+ if (!gpu_buddy_block_is_free(buddy))
+ continue;
+
+ WARN_ON(gpu_buddy_block_is_clear(block) ==
+ gpu_buddy_block_is_clear(buddy));
+
+ /*
+ * Advance to the next node when the current node is the buddy,
+ * as freeing the block will also remove its buddy from the tree.
+ */
+ if (iter == &buddy->rb)
+ iter = rb_prev(iter);
+
+ rbtree_remove(mm, block);
+ if (gpu_buddy_block_is_clear(block))
+ mm->clear_avail -= gpu_buddy_block_size(mm, block);
+
+ order = __gpu_buddy_free(mm, block, true);
+ if (order >= min_order)
+ return 0;
+ }
+ }
+ }
+
+ return -ENOMEM;
+}
+
+/**
+ * gpu_buddy_init - init memory manager
+ *
+ * @mm: GPU buddy manager to initialize
+ * @size: size in bytes to manage
+ * @chunk_size: minimum page size in bytes for our allocations
+ *
+ * Initializes the memory manager and its resources.
+ *
+ * Returns:
+ * 0 on success, error code on failure.
+ */
+int gpu_buddy_init(struct gpu_buddy *mm, u64 size, u64 chunk_size)
+{
+ unsigned int i, j, root_count = 0;
+ u64 offset = 0;
+
+ if (size < chunk_size)
+ return -EINVAL;
+
+ if (chunk_size < SZ_4K)
+ return -EINVAL;
+
+ if (!is_power_of_2(chunk_size))
+ return -EINVAL;
+
+ size = round_down(size, chunk_size);
+
+ mm->size = size;
+ mm->avail = size;
+ mm->clear_avail = 0;
+ mm->chunk_size = chunk_size;
+ mm->max_order = ilog2(size) - ilog2(chunk_size);
+
+ BUG_ON(mm->max_order > GPU_BUDDY_MAX_ORDER);
+
+ mm->free_trees = kmalloc_array(GPU_BUDDY_MAX_FREE_TREES,
+ sizeof(*mm->free_trees),
+ GFP_KERNEL);
+ if (!mm->free_trees)
+ return -ENOMEM;
+
+ for_each_free_tree(i) {
+ mm->free_trees[i] = kmalloc_array(mm->max_order + 1,
+ sizeof(struct rb_root),
+ GFP_KERNEL);
+ if (!mm->free_trees[i])
+ goto out_free_tree;
+
+ for (j = 0; j <= mm->max_order; ++j)
+ mm->free_trees[i][j] = RB_ROOT;
+ }
+
+ mm->n_roots = hweight64(size);
+
+ mm->roots = kmalloc_array(mm->n_roots,
+ sizeof(struct gpu_buddy_block *),
+ GFP_KERNEL);
+ if (!mm->roots)
+ goto out_free_tree;
+
+ /*
+ * Split into power-of-two blocks, in case we are given a size that is
+ * not itself a power-of-two.
+ */
+ do {
+ struct gpu_buddy_block *root;
+ unsigned int order;
+ u64 root_size;
+
+ order = ilog2(size) - ilog2(chunk_size);
+ root_size = chunk_size << order;
+
+ root = gpu_block_alloc(mm, NULL, order, offset);
+ if (!root)
+ goto out_free_roots;
+
+ mark_free(mm, root);
+
+ BUG_ON(root_count > mm->max_order);
+ BUG_ON(gpu_buddy_block_size(mm, root) < chunk_size);
+
+ mm->roots[root_count] = root;
+
+ offset += root_size;
+ size -= root_size;
+ root_count++;
+ } while (size);
+
+ return 0;
+
+out_free_roots:
+ while (root_count--)
+ gpu_block_free(mm, mm->roots[root_count]);
+ kfree(mm->roots);
+out_free_tree:
+ while (i--)
+ kfree(mm->free_trees[i]);
+ kfree(mm->free_trees);
+ return -ENOMEM;
+}
+EXPORT_SYMBOL(gpu_buddy_init);
+
+/**
+ * gpu_buddy_fini - tear down the memory manager
+ *
+ * @mm: GPU buddy manager to free
+ *
+ * Cleanup memory manager resources and the freetree
+ */
+void gpu_buddy_fini(struct gpu_buddy *mm)
+{
+ u64 root_size, size, start;
+ unsigned int order;
+ int i;
+
+ size = mm->size;
+
+ for (i = 0; i < mm->n_roots; ++i) {
+ order = ilog2(size) - ilog2(mm->chunk_size);
+ start = gpu_buddy_block_offset(mm->roots[i]);
+ __force_merge(mm, start, start + size, order);
+
+ if (WARN_ON(!gpu_buddy_block_is_free(mm->roots[i])))
+ kunit_fail_current_test("buddy_fini() root");
+
+ gpu_block_free(mm, mm->roots[i]);
+
+ root_size = mm->chunk_size << order;
+ size -= root_size;
+ }
+
+ WARN_ON(mm->avail != mm->size);
+
+ for_each_free_tree(i)
+ kfree(mm->free_trees[i]);
+ kfree(mm->free_trees);
+ kfree(mm->roots);
+}
+EXPORT_SYMBOL(gpu_buddy_fini);
+
+static int split_block(struct gpu_buddy *mm,
+ struct gpu_buddy_block *block)
+{
+ unsigned int block_order = gpu_buddy_block_order(block) - 1;
+ u64 offset = gpu_buddy_block_offset(block);
+
+ BUG_ON(!gpu_buddy_block_is_free(block));
+ BUG_ON(!gpu_buddy_block_order(block));
+
+ block->left = gpu_block_alloc(mm, block, block_order, offset);
+ if (!block->left)
+ return -ENOMEM;
+
+ block->right = gpu_block_alloc(mm, block, block_order,
+ offset + (mm->chunk_size << block_order));
+ if (!block->right) {
+ gpu_block_free(mm, block->left);
+ return -ENOMEM;
+ }
+
+ mark_split(mm, block);
+
+ if (gpu_buddy_block_is_clear(block)) {
+ mark_cleared(block->left);
+ mark_cleared(block->right);
+ clear_reset(block);
+ }
+
+ mark_free(mm, block->left);
+ mark_free(mm, block->right);
+
+ return 0;
+}
+
+/**
+ * gpu_get_buddy - get buddy address
+ *
+ * @block: GPU buddy block
+ *
+ * Returns the corresponding buddy block for @block, or NULL
+ * if this is a root block and can't be merged further.
+ * Requires some kind of locking to protect against
+ * any concurrent allocate and free operations.
+ */
+struct gpu_buddy_block *
+gpu_get_buddy(struct gpu_buddy_block *block)
+{
+ return __get_buddy(block);
+}
+EXPORT_SYMBOL(gpu_get_buddy);
+
+/**
+ * gpu_buddy_reset_clear - reset blocks clear state
+ *
+ * @mm: GPU buddy manager
+ * @is_clear: blocks clear state
+ *
+ * Reset the clear state based on @is_clear value for each block
+ * in the freetree.
+ */
+void gpu_buddy_reset_clear(struct gpu_buddy *mm, bool is_clear)
+{
+ enum gpu_buddy_free_tree src_tree, dst_tree;
+ u64 root_size, size, start;
+ unsigned int order;
+ int i;
+
+ size = mm->size;
+ for (i = 0; i < mm->n_roots; ++i) {
+ order = ilog2(size) - ilog2(mm->chunk_size);
+ start = gpu_buddy_block_offset(mm->roots[i]);
+ __force_merge(mm, start, start + size, order);
+
+ root_size = mm->chunk_size << order;
+ size -= root_size;
+ }
+
+ src_tree = is_clear ? GPU_BUDDY_DIRTY_TREE : GPU_BUDDY_CLEAR_TREE;
+ dst_tree = is_clear ? GPU_BUDDY_CLEAR_TREE : GPU_BUDDY_DIRTY_TREE;
+
+ for (i = 0; i <= mm->max_order; ++i) {
+ struct rb_root *root = &mm->free_trees[src_tree][i];
+ struct gpu_buddy_block *block, *tmp;
+
+ rbtree_postorder_for_each_entry_safe(block, tmp, root, rb) {
+ rbtree_remove(mm, block);
+ if (is_clear) {
+ mark_cleared(block);
+ mm->clear_avail += gpu_buddy_block_size(mm, block);
+ } else {
+ clear_reset(block);
+ mm->clear_avail -= gpu_buddy_block_size(mm, block);
+ }
+
+ rbtree_insert(mm, block, dst_tree);
+ }
+ }
+}
+EXPORT_SYMBOL(gpu_buddy_reset_clear);
+
+/**
+ * gpu_buddy_free_block - free a block
+ *
+ * @mm: GPU buddy manager
+ * @block: block to be freed
+ */
+void gpu_buddy_free_block(struct gpu_buddy *mm,
+ struct gpu_buddy_block *block)
+{
+ BUG_ON(!gpu_buddy_block_is_allocated(block));
+ mm->avail += gpu_buddy_block_size(mm, block);
+ if (gpu_buddy_block_is_clear(block))
+ mm->clear_avail += gpu_buddy_block_size(mm, block);
+
+ __gpu_buddy_free(mm, block, false);
+}
+EXPORT_SYMBOL(gpu_buddy_free_block);
+
+static void __gpu_buddy_free_list(struct gpu_buddy *mm,
+ struct list_head *objects,
+ bool mark_clear,
+ bool mark_dirty)
+{
+ struct gpu_buddy_block *block, *on;
+
+ WARN_ON(mark_dirty && mark_clear);
+
+ list_for_each_entry_safe(block, on, objects, link) {
+ if (mark_clear)
+ mark_cleared(block);
+ else if (mark_dirty)
+ clear_reset(block);
+ gpu_buddy_free_block(mm, block);
+ cond_resched();
+ }
+ INIT_LIST_HEAD(objects);
+}
+
+static void gpu_buddy_free_list_internal(struct gpu_buddy *mm,
+ struct list_head *objects)
+{
+ /*
+ * Don't touch the clear/dirty bit, since allocation is still internal
+ * at this point. For example we might have just failed part of the
+ * allocation.
+ */
+ __gpu_buddy_free_list(mm, objects, false, false);
+}
+
+/**
+ * gpu_buddy_free_list - free blocks
+ *
+ * @mm: GPU buddy manager
+ * @objects: input list head to free blocks
+ * @flags: optional flags like GPU_BUDDY_CLEARED
+ */
+void gpu_buddy_free_list(struct gpu_buddy *mm,
+ struct list_head *objects,
+ unsigned int flags)
+{
+ bool mark_clear = flags & GPU_BUDDY_CLEARED;
+
+ __gpu_buddy_free_list(mm, objects, mark_clear, !mark_clear);
+}
+EXPORT_SYMBOL(gpu_buddy_free_list);
+
+static bool block_incompatible(struct gpu_buddy_block *block, unsigned int flags)
+{
+ bool needs_clear = flags & GPU_BUDDY_CLEAR_ALLOCATION;
+
+ return needs_clear != gpu_buddy_block_is_clear(block);
+}
+
+static struct gpu_buddy_block *
+__alloc_range_bias(struct gpu_buddy *mm,
+ u64 start, u64 end,
+ unsigned int order,
+ unsigned long flags,
+ bool fallback)
+{
+ u64 req_size = mm->chunk_size << order;
+ struct gpu_buddy_block *block;
+ struct gpu_buddy_block *buddy;
+ LIST_HEAD(dfs);
+ int err;
+ int i;
+
+ end = end - 1;
+
+ for (i = 0; i < mm->n_roots; ++i)
+ list_add_tail(&mm->roots[i]->tmp_link, &dfs);
+
+ do {
+ u64 block_start;
+ u64 block_end;
+
+ block = list_first_entry_or_null(&dfs,
+ struct gpu_buddy_block,
+ tmp_link);
+ if (!block)
+ break;
+
+ list_del(&block->tmp_link);
+
+ if (gpu_buddy_block_order(block) < order)
+ continue;
+
+ block_start = gpu_buddy_block_offset(block);
+ block_end = block_start + gpu_buddy_block_size(mm, block) - 1;
+
+ if (!overlaps(start, end, block_start, block_end))
+ continue;
+
+ if (gpu_buddy_block_is_allocated(block))
+ continue;
+
+ if (block_start < start || block_end > end) {
+ u64 adjusted_start = max(block_start, start);
+ u64 adjusted_end = min(block_end, end);
+
+ if (round_down(adjusted_end + 1, req_size) <=
+ round_up(adjusted_start, req_size))
+ continue;
+ }
+
+ if (!fallback && block_incompatible(block, flags))
+ continue;
+
+ if (contains(start, end, block_start, block_end) &&
+ order == gpu_buddy_block_order(block)) {
+ /*
+ * Find the free block within the range.
+ */
+ if (gpu_buddy_block_is_free(block))
+ return block;
+
+ continue;
+ }
+
+ if (!gpu_buddy_block_is_split(block)) {
+ err = split_block(mm, block);
+ if (unlikely(err))
+ goto err_undo;
+ }
+
+ list_add(&block->right->tmp_link, &dfs);
+ list_add(&block->left->tmp_link, &dfs);
+ } while (1);
+
+ return ERR_PTR(-ENOSPC);
+
+err_undo:
+ /*
+ * We really don't want to leave around a bunch of split blocks, since
+ * bigger is better, so make sure we merge everything back before we
+ * free the allocated blocks.
+ */
+ buddy = __get_buddy(block);
+ if (buddy &&
+ (gpu_buddy_block_is_free(block) &&
+ gpu_buddy_block_is_free(buddy)))
+ __gpu_buddy_free(mm, block, false);
+ return ERR_PTR(err);
+}
+
+static struct gpu_buddy_block *
+__gpu_buddy_alloc_range_bias(struct gpu_buddy *mm,
+ u64 start, u64 end,
+ unsigned int order,
+ unsigned long flags)
+{
+ struct gpu_buddy_block *block;
+ bool fallback = false;
+
+ block = __alloc_range_bias(mm, start, end, order,
+ flags, fallback);
+ if (IS_ERR(block))
+ return __alloc_range_bias(mm, start, end, order,
+ flags, !fallback);
+
+ return block;
+}
+
+static struct gpu_buddy_block *
+get_maxblock(struct gpu_buddy *mm,
+ unsigned int order,
+ enum gpu_buddy_free_tree tree)
+{
+ struct gpu_buddy_block *max_block = NULL, *block = NULL;
+ struct rb_root *root;
+ unsigned int i;
+
+ for (i = order; i <= mm->max_order; ++i) {
+ root = &mm->free_trees[tree][i];
+ block = rbtree_last_free_block(root);
+ if (!block)
+ continue;
+
+ if (!max_block) {
+ max_block = block;
+ continue;
+ }
+
+ if (gpu_buddy_block_offset(block) >
+ gpu_buddy_block_offset(max_block)) {
+ max_block = block;
+ }
+ }
+
+ return max_block;
+}
+
+static struct gpu_buddy_block *
+alloc_from_freetree(struct gpu_buddy *mm,
+ unsigned int order,
+ unsigned long flags)
+{
+ struct gpu_buddy_block *block = NULL;
+ struct rb_root *root;
+ enum gpu_buddy_free_tree tree;
+ unsigned int tmp;
+ int err;
+
+ tree = (flags & GPU_BUDDY_CLEAR_ALLOCATION) ?
+ GPU_BUDDY_CLEAR_TREE : GPU_BUDDY_DIRTY_TREE;
+
+ if (flags & GPU_BUDDY_TOPDOWN_ALLOCATION) {
+ block = get_maxblock(mm, order, tree);
+ if (block)
+ /* Store the obtained block order */
+ tmp = gpu_buddy_block_order(block);
+ } else {
+ for (tmp = order; tmp <= mm->max_order; ++tmp) {
+ /* Get RB tree root for this order and tree */
+ root = &mm->free_trees[tree][tmp];
+ block = rbtree_last_free_block(root);
+ if (block)
+ break;
+ }
+ }
+
+ if (!block) {
+ /* Try allocating from the other tree */
+ tree = (tree == GPU_BUDDY_CLEAR_TREE) ?
+ GPU_BUDDY_DIRTY_TREE : GPU_BUDDY_CLEAR_TREE;
+
+ for (tmp = order; tmp <= mm->max_order; ++tmp) {
+ root = &mm->free_trees[tree][tmp];
+ block = rbtree_last_free_block(root);
+ if (block)
+ break;
+ }
+
+ if (!block)
+ return ERR_PTR(-ENOSPC);
+ }
+
+ BUG_ON(!gpu_buddy_block_is_free(block));
+
+ while (tmp != order) {
+ err = split_block(mm, block);
+ if (unlikely(err))
+ goto err_undo;
+
+ block = block->right;
+ tmp--;
+ }
+ return block;
+
+err_undo:
+ if (tmp != order)
+ __gpu_buddy_free(mm, block, false);
+ return ERR_PTR(err);
+}
+
+static int __alloc_range(struct gpu_buddy *mm,
+ struct list_head *dfs,
+ u64 start, u64 size,
+ struct list_head *blocks,
+ u64 *total_allocated_on_err)
+{
+ struct gpu_buddy_block *block;
+ struct gpu_buddy_block *buddy;
+ u64 total_allocated = 0;
+ LIST_HEAD(allocated);
+ u64 end;
+ int err;
+
+ end = start + size - 1;
+
+ do {
+ u64 block_start;
+ u64 block_end;
+
+ block = list_first_entry_or_null(dfs,
+ struct gpu_buddy_block,
+ tmp_link);
+ if (!block)
+ break;
+
+ list_del(&block->tmp_link);
+
+ block_start = gpu_buddy_block_offset(block);
+ block_end = block_start + gpu_buddy_block_size(mm, block) - 1;
+
+ if (!overlaps(start, end, block_start, block_end))
+ continue;
+
+ if (gpu_buddy_block_is_allocated(block)) {
+ err = -ENOSPC;
+ goto err_free;
+ }
+
+ if (contains(start, end, block_start, block_end)) {
+ if (gpu_buddy_block_is_free(block)) {
+ mark_allocated(mm, block);
+ total_allocated += gpu_buddy_block_size(mm, block);
+ mm->avail -= gpu_buddy_block_size(mm, block);
+ if (gpu_buddy_block_is_clear(block))
+ mm->clear_avail -= gpu_buddy_block_size(mm, block);
+ list_add_tail(&block->link, &allocated);
+ continue;
+ } else if (!mm->clear_avail) {
+ err = -ENOSPC;
+ goto err_free;
+ }
+ }
+
+ if (!gpu_buddy_block_is_split(block)) {
+ err = split_block(mm, block);
+ if (unlikely(err))
+ goto err_undo;
+ }
+
+ list_add(&block->right->tmp_link, dfs);
+ list_add(&block->left->tmp_link, dfs);
+ } while (1);
+
+ if (total_allocated < size) {
+ err = -ENOSPC;
+ goto err_free;
+ }
+
+ list_splice_tail(&allocated, blocks);
+
+ return 0;
+
+err_undo:
+ /*
+ * We really don't want to leave around a bunch of split blocks, since
+ * bigger is better, so make sure we merge everything back before we
+ * free the allocated blocks.
+ */
+ buddy = __get_buddy(block);
+ if (buddy &&
+ (gpu_buddy_block_is_free(block) &&
+ gpu_buddy_block_is_free(buddy)))
+ __gpu_buddy_free(mm, block, false);
+
+err_free:
+ if (err == -ENOSPC && total_allocated_on_err) {
+ list_splice_tail(&allocated, blocks);
+ *total_allocated_on_err = total_allocated;
+ } else {
+ gpu_buddy_free_list_internal(mm, &allocated);
+ }
+
+ return err;
+}
+
+static int __gpu_buddy_alloc_range(struct gpu_buddy *mm,
+ u64 start,
+ u64 size,
+ u64 *total_allocated_on_err,
+ struct list_head *blocks)
+{
+ LIST_HEAD(dfs);
+ int i;
+
+ for (i = 0; i < mm->n_roots; ++i)
+ list_add_tail(&mm->roots[i]->tmp_link, &dfs);
+
+ return __alloc_range(mm, &dfs, start, size,
+ blocks, total_allocated_on_err);
+}
+
+static int __alloc_contig_try_harder(struct gpu_buddy *mm,
+ u64 size,
+ u64 min_block_size,
+ struct list_head *blocks)
+{
+ u64 rhs_offset, lhs_offset, lhs_size, filled;
+ struct gpu_buddy_block *block;
+ unsigned int tree, order;
+ LIST_HEAD(blocks_lhs);
+ unsigned long pages;
+ u64 modify_size;
+ int err;
+
+ modify_size = rounddown_pow_of_two(size);
+ pages = modify_size >> ilog2(mm->chunk_size);
+ order = fls(pages) - 1;
+ if (order == 0)
+ return -ENOSPC;
+
+ for_each_free_tree(tree) {
+ struct rb_root *root;
+ struct rb_node *iter;
+
+ root = &mm->free_trees[tree][order];
+ if (rbtree_is_empty(root))
+ continue;
+
+ iter = rb_last(root);
+ while (iter) {
+ block = rbtree_get_free_block(iter);
+
+ /* Allocate blocks traversing RHS */
+ rhs_offset = gpu_buddy_block_offset(block);
+ err = __gpu_buddy_alloc_range(mm, rhs_offset, size,
+ &filled, blocks);
+ if (!err || err != -ENOSPC)
+ return err;
+
+ lhs_size = max((size - filled), min_block_size);
+ if (!IS_ALIGNED(lhs_size, min_block_size))
+ lhs_size = round_up(lhs_size, min_block_size);
+
+ /* Allocate blocks traversing LHS */
+ lhs_offset = gpu_buddy_block_offset(block) - lhs_size;
+ err = __gpu_buddy_alloc_range(mm, lhs_offset, lhs_size,
+ NULL, &blocks_lhs);
+ if (!err) {
+ list_splice(&blocks_lhs, blocks);
+ return 0;
+ } else if (err != -ENOSPC) {
+ gpu_buddy_free_list_internal(mm, blocks);
+ return err;
+ }
+ /* Free blocks for the next iteration */
+ gpu_buddy_free_list_internal(mm, blocks);
+
+ iter = rb_prev(iter);
+ }
+ }
+
+ return -ENOSPC;
+}
+
+/**
+ * gpu_buddy_block_trim - free unused pages
+ *
+ * @mm: GPU buddy manager
+ * @start: start address to begin the trimming.
+ * @new_size: original size requested
+ * @blocks: Input and output list of allocated blocks.
+ * MUST contain single block as input to be trimmed.
+ * On success will contain the newly allocated blocks
+ * making up the @new_size. Blocks always appear in
+ * ascending order
+ *
+ * For contiguous allocation, we round up the size to the nearest
+ * power of two value, drivers consume *actual* size, so remaining
+ * portions are unused and can be optionally freed with this function
+ *
+ * Returns:
+ * 0 on success, error code on failure.
+ */
+int gpu_buddy_block_trim(struct gpu_buddy *mm,
+ u64 *start,
+ u64 new_size,
+ struct list_head *blocks)
+{
+ struct gpu_buddy_block *parent;
+ struct gpu_buddy_block *block;
+ u64 block_start, block_end;
+ LIST_HEAD(dfs);
+ u64 new_start;
+ int err;
+
+ if (!list_is_singular(blocks))
+ return -EINVAL;
+
+ block = list_first_entry(blocks,
+ struct gpu_buddy_block,
+ link);
+
+ block_start = gpu_buddy_block_offset(block);
+ block_end = block_start + gpu_buddy_block_size(mm, block);
+
+ if (WARN_ON(!gpu_buddy_block_is_allocated(block)))
+ return -EINVAL;
+
+ if (new_size > gpu_buddy_block_size(mm, block))
+ return -EINVAL;
+
+ if (!new_size || !IS_ALIGNED(new_size, mm->chunk_size))
+ return -EINVAL;
+
+ if (new_size == gpu_buddy_block_size(mm, block))
+ return 0;
+
+ new_start = block_start;
+ if (start) {
+ new_start = *start;
+
+ if (new_start < block_start)
+ return -EINVAL;
+
+ if (!IS_ALIGNED(new_start, mm->chunk_size))
+ return -EINVAL;
+
+ if (range_overflows(new_start, new_size, block_end))
+ return -EINVAL;
+ }
+
+ list_del(&block->link);
+ mark_free(mm, block);
+ mm->avail += gpu_buddy_block_size(mm, block);
+ if (gpu_buddy_block_is_clear(block))
+ mm->clear_avail += gpu_buddy_block_size(mm, block);
+
+ /* Prevent recursively freeing this node */
+ parent = block->parent;
+ block->parent = NULL;
+
+ list_add(&block->tmp_link, &dfs);
+ err = __alloc_range(mm, &dfs, new_start, new_size, blocks, NULL);
+ if (err) {
+ mark_allocated(mm, block);
+ mm->avail -= gpu_buddy_block_size(mm, block);
+ if (gpu_buddy_block_is_clear(block))
+ mm->clear_avail -= gpu_buddy_block_size(mm, block);
+ list_add(&block->link, blocks);
+ }
+
+ block->parent = parent;
+ return err;
+}
+EXPORT_SYMBOL(gpu_buddy_block_trim);
+
+static struct gpu_buddy_block *
+__gpu_buddy_alloc_blocks(struct gpu_buddy *mm,
+ u64 start, u64 end,
+ unsigned int order,
+ unsigned long flags)
+{
+ if (flags & GPU_BUDDY_RANGE_ALLOCATION)
+ /* Allocate traversing within the range */
+ return __gpu_buddy_alloc_range_bias(mm, start, end,
+ order, flags);
+ else
+ /* Allocate from freetree */
+ return alloc_from_freetree(mm, order, flags);
+}
+
+/**
+ * gpu_buddy_alloc_blocks - allocate power-of-two blocks
+ *
+ * @mm: GPU buddy manager to allocate from
+ * @start: start of the allowed range for this block
+ * @end: end of the allowed range for this block
+ * @size: size of the allocation in bytes
+ * @min_block_size: alignment of the allocation
+ * @blocks: output list head to add allocated blocks
+ * @flags: GPU_BUDDY_*_ALLOCATION flags
+ *
+ * alloc_range_bias() called on range limitations, which traverses
+ * the tree and returns the desired block.
+ *
+ * alloc_from_freetree() called when *no* range restrictions
+ * are enforced, which picks the block from the freetree.
+ *
+ * Returns:
+ * 0 on success, error code on failure.
+ */
+int gpu_buddy_alloc_blocks(struct gpu_buddy *mm,
+ u64 start, u64 end, u64 size,
+ u64 min_block_size,
+ struct list_head *blocks,
+ unsigned long flags)
+{
+ struct gpu_buddy_block *block = NULL;
+ u64 original_size, original_min_size;
+ unsigned int min_order, order;
+ LIST_HEAD(allocated);
+ unsigned long pages;
+ int err;
+
+ if (size < mm->chunk_size)
+ return -EINVAL;
+
+ if (min_block_size < mm->chunk_size)
+ return -EINVAL;
+
+ if (!is_power_of_2(min_block_size))
+ return -EINVAL;
+
+ if (!IS_ALIGNED(start | end | size, mm->chunk_size))
+ return -EINVAL;
+
+ if (end > mm->size)
+ return -EINVAL;
+
+ if (range_overflows(start, size, mm->size))
+ return -EINVAL;
+
+ /* Actual range allocation */
+ if (start + size == end) {
+ if (!IS_ALIGNED(start | end, min_block_size))
+ return -EINVAL;
+
+ return __gpu_buddy_alloc_range(mm, start, size, NULL, blocks);
+ }
+
+ original_size = size;
+ original_min_size = min_block_size;
+
+ /* Roundup the size to power of 2 */
+ if (flags & GPU_BUDDY_CONTIGUOUS_ALLOCATION) {
+ size = roundup_pow_of_two(size);
+ min_block_size = size;
+ /* Align size value to min_block_size */
+ } else if (!IS_ALIGNED(size, min_block_size)) {
+ size = round_up(size, min_block_size);
+ }
+
+ pages = size >> ilog2(mm->chunk_size);
+ order = fls(pages) - 1;
+ min_order = ilog2(min_block_size) - ilog2(mm->chunk_size);
+
+ if (order > mm->max_order || size > mm->size) {
+ if ((flags & GPU_BUDDY_CONTIGUOUS_ALLOCATION) &&
+ !(flags & GPU_BUDDY_RANGE_ALLOCATION))
+ return __alloc_contig_try_harder(mm, original_size,
+ original_min_size, blocks);
+
+ return -EINVAL;
+ }
+
+ do {
+ order = min(order, (unsigned int)fls(pages) - 1);
+ BUG_ON(order > mm->max_order);
+ BUG_ON(order < min_order);
+
+ do {
+ block = __gpu_buddy_alloc_blocks(mm, start,
+ end,
+ order,
+ flags);
+ if (!IS_ERR(block))
+ break;
+
+ if (order-- == min_order) {
+ /* Try allocation through force merge method */
+ if (mm->clear_avail &&
+ !__force_merge(mm, start, end, min_order)) {
+ block = __gpu_buddy_alloc_blocks(mm, start,
+ end,
+ min_order,
+ flags);
+ if (!IS_ERR(block)) {
+ order = min_order;
+ break;
+ }
+ }
+
+ /*
+ * Try contiguous block allocation through
+ * try harder method.
+ */
+ if (flags & GPU_BUDDY_CONTIGUOUS_ALLOCATION &&
+ !(flags & GPU_BUDDY_RANGE_ALLOCATION))
+ return __alloc_contig_try_harder(mm,
+ original_size,
+ original_min_size,
+ blocks);
+ err = -ENOSPC;
+ goto err_free;
+ }
+ } while (1);
+
+ mark_allocated(mm, block);
+ mm->avail -= gpu_buddy_block_size(mm, block);
+ if (gpu_buddy_block_is_clear(block))
+ mm->clear_avail -= gpu_buddy_block_size(mm, block);
+ kmemleak_update_trace(block);
+ list_add_tail(&block->link, &allocated);
+
+ pages -= BIT(order);
+
+ if (!pages)
+ break;
+ } while (1);
+
+ /* Trim the allocated block to the required size */
+ if (!(flags & GPU_BUDDY_TRIM_DISABLE) &&
+ original_size != size) {
+ struct list_head *trim_list;
+ LIST_HEAD(temp);
+ u64 trim_size;
+
+ trim_list = &allocated;
+ trim_size = original_size;
+
+ if (!list_is_singular(&allocated)) {
+ block = list_last_entry(&allocated, typeof(*block), link);
+ list_move(&block->link, &temp);
+ trim_list = &temp;
+ trim_size = gpu_buddy_block_size(mm, block) -
+ (size - original_size);
+ }
+
+ gpu_buddy_block_trim(mm,
+ NULL,
+ trim_size,
+ trim_list);
+
+ if (!list_empty(&temp))
+ list_splice_tail(trim_list, &allocated);
+ }
+
+ list_splice_tail(&allocated, blocks);
+ return 0;
+
+err_free:
+ gpu_buddy_free_list_internal(mm, &allocated);
+ return err;
+}
+EXPORT_SYMBOL(gpu_buddy_alloc_blocks);
+
+/**
+ * gpu_buddy_block_print - print block information
+ *
+ * @mm: GPU buddy manager
+ * @block: GPU buddy block
+ */
+void gpu_buddy_block_print(struct gpu_buddy *mm,
+ struct gpu_buddy_block *block)
+{
+ u64 start = gpu_buddy_block_offset(block);
+ u64 size = gpu_buddy_block_size(mm, block);
+
+ pr_info("%#018llx-%#018llx: %llu\n", start, start + size, size);
+}
+EXPORT_SYMBOL(gpu_buddy_block_print);
+
+/**
+ * gpu_buddy_print - print allocator state
+ *
+ * @mm: GPU buddy manager
+ * @p: GPU printer to use
+ */
+void gpu_buddy_print(struct gpu_buddy *mm)
+{
+ int order;
+
+ pr_info("chunk_size: %lluKiB, total: %lluMiB, free: %lluMiB, clear_free: %lluMiB\n",
+ mm->chunk_size >> 10, mm->size >> 20, mm->avail >> 20, mm->clear_avail >> 20);
+
+ for (order = mm->max_order; order >= 0; order--) {
+ struct gpu_buddy_block *block, *tmp;
+ struct rb_root *root;
+ u64 count = 0, free;
+ unsigned int tree;
+
+ for_each_free_tree(tree) {
+ root = &mm->free_trees[tree][order];
+
+ rbtree_postorder_for_each_entry_safe(block, tmp, root, rb) {
+ BUG_ON(!gpu_buddy_block_is_free(block));
+ count++;
+ }
+ }
+
+ free = count * (mm->chunk_size << order);
+ if (free < SZ_1M)
+ pr_info("order-%2d free: %8llu KiB, blocks: %llu\n",
+ order, free >> 10, count);
+ else
+ pr_info("order-%2d free: %8llu MiB, blocks: %llu\n",
+ order, free >> 20, count);
+ }
+}
+EXPORT_SYMBOL(gpu_buddy_print);
+
+static void gpu_buddy_module_exit(void)
+{
+ kmem_cache_destroy(slab_blocks);
+}
+
+static int __init gpu_buddy_module_init(void)
+{
+ slab_blocks = KMEM_CACHE(gpu_buddy_block, 0);
+ if (!slab_blocks)
+ return -ENOMEM;
+
+ return 0;
+}
+
+module_init(gpu_buddy_module_init);
+module_exit(gpu_buddy_module_exit);
+
+MODULE_DESCRIPTION("GPU Buddy Allocator");
+MODULE_LICENSE("Dual MIT/GPL");
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -85,7 +85,6 @@ config DRM_KUNIT_TEST
select DRM_EXPORT_FOR_TESTS if m
select DRM_GEM_SHMEM_HELPER
select DRM_KUNIT_TEST_HELPERS
- select DRM_LIB_RANDOM
select PRIME_NUMBERS
default KUNIT_ALL_TESTS
help
@@ -325,6 +324,7 @@ config DRM_GPUVM
config DRM_BUDDY
tristate
depends on DRM
+ select GPU_BUDDY
help
A page based buddy allocator
@@ -507,10 +507,6 @@ config DRM_EXPORT_FOR_TESTS
config DRM_PANEL_BACKLIGHT_QUIRKS
tristate
-config DRM_LIB_RANDOM
- bool
- default n
-
config DRM_PRIVACY_SCREEN
bool
default n
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -75,7 +75,6 @@ drm-y := \
drm_vblank_work.o \
drm_vma_manager.o \
drm_writeback.o
-drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
drm-$(CONFIG_COMPAT) += drm_ioc32.o
drm-$(CONFIG_DRM_PANEL) += drm_panel.o
drm-$(CONFIG_OF) += drm_of.o
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h
@@ -55,7 +55,7 @@ static inline void amdgpu_res_first(stru
uint64_t start, uint64_t size,
struct amdgpu_res_cursor *cur)
{
- struct drm_buddy_block *block;
+ struct gpu_buddy_block *block;
struct list_head *head, *next;
struct drm_mm_node *node;
@@ -71,7 +71,7 @@ static inline void amdgpu_res_first(stru
head = &to_amdgpu_vram_mgr_resource(res)->blocks;
block = list_first_entry_or_null(head,
- struct drm_buddy_block,
+ struct gpu_buddy_block,
link);
if (!block)
goto fallback;
@@ -81,7 +81,7 @@ static inline void amdgpu_res_first(stru
next = block->link.next;
if (next != head)
- block = list_entry(next, struct drm_buddy_block, link);
+ block = list_entry(next, struct gpu_buddy_block, link);
}
cur->start = amdgpu_vram_mgr_block_start(block) + start;
@@ -124,7 +124,7 @@ fallback:
*/
static inline void amdgpu_res_next(struct amdgpu_res_cursor *cur, uint64_t size)
{
- struct drm_buddy_block *block;
+ struct gpu_buddy_block *block;
struct drm_mm_node *node;
struct list_head *next;
@@ -145,7 +145,7 @@ static inline void amdgpu_res_next(struc
block = cur->node;
next = block->link.next;
- block = list_entry(next, struct drm_buddy_block, link);
+ block = list_entry(next, struct gpu_buddy_block, link);
cur->node = block;
cur->start = amdgpu_vram_mgr_block_start(block);
@@ -173,7 +173,7 @@ static inline void amdgpu_res_next(struc
*/
static inline bool amdgpu_res_cleared(struct amdgpu_res_cursor *cur)
{
- struct drm_buddy_block *block;
+ struct gpu_buddy_block *block;
switch (cur->mem_type) {
case TTM_PL_VRAM:
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
@@ -24,6 +24,7 @@
#include <linux/dma-mapping.h>
#include <drm/ttm/ttm_range_manager.h>
+#include <drm/drm_buddy.h>
#include "amdgpu.h"
#include "amdgpu_vm.h"
@@ -52,15 +53,15 @@ to_amdgpu_device(struct amdgpu_vram_mgr
return container_of(mgr, struct amdgpu_device, mman.vram_mgr);
}
-static inline struct drm_buddy_block *
+static inline struct gpu_buddy_block *
amdgpu_vram_mgr_first_block(struct list_head *list)
{
- return list_first_entry_or_null(list, struct drm_buddy_block, link);
+ return list_first_entry_or_null(list, struct gpu_buddy_block, link);
}
static inline bool amdgpu_is_vram_mgr_blocks_contiguous(struct list_head *head)
{
- struct drm_buddy_block *block;
+ struct gpu_buddy_block *block;
u64 start, size;
block = amdgpu_vram_mgr_first_block(head);
@@ -71,7 +72,7 @@ static inline bool amdgpu_is_vram_mgr_bl
start = amdgpu_vram_mgr_block_start(block);
size = amdgpu_vram_mgr_block_size(block);
- block = list_entry(block->link.next, struct drm_buddy_block, link);
+ block = list_entry(block->link.next, struct gpu_buddy_block, link);
if (start + size != amdgpu_vram_mgr_block_start(block))
return false;
}
@@ -81,7 +82,7 @@ static inline bool amdgpu_is_vram_mgr_bl
static inline u64 amdgpu_vram_mgr_blocks_size(struct list_head *head)
{
- struct drm_buddy_block *block;
+ struct gpu_buddy_block *block;
u64 size = 0;
list_for_each_entry(block, head, link)
@@ -254,7 +255,7 @@ const struct attribute_group amdgpu_vram
* Calculate how many bytes of the DRM BUDDY block are inside visible VRAM
*/
static u64 amdgpu_vram_mgr_vis_size(struct amdgpu_device *adev,
- struct drm_buddy_block *block)
+ struct gpu_buddy_block *block)
{
u64 start = amdgpu_vram_mgr_block_start(block);
u64 end = start + amdgpu_vram_mgr_block_size(block);
@@ -279,7 +280,7 @@ u64 amdgpu_vram_mgr_bo_visible_size(stru
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
struct ttm_resource *res = bo->tbo.resource;
struct amdgpu_vram_mgr_resource *vres = to_amdgpu_vram_mgr_resource(res);
- struct drm_buddy_block *block;
+ struct gpu_buddy_block *block;
u64 usage = 0;
if (amdgpu_gmc_vram_full_visible(&adev->gmc))
@@ -299,15 +300,15 @@ static void amdgpu_vram_mgr_do_reserve(s
{
struct amdgpu_vram_mgr *mgr = to_vram_mgr(man);
struct amdgpu_device *adev = to_amdgpu_device(mgr);
- struct drm_buddy *mm = &mgr->mm;
+ struct gpu_buddy *mm = &mgr->mm;
struct amdgpu_vram_reservation *rsv, *temp;
- struct drm_buddy_block *block;
+ struct gpu_buddy_block *block;
uint64_t vis_usage;
list_for_each_entry_safe(rsv, temp, &mgr->reservations_pending, blocks) {
- if (drm_buddy_alloc_blocks(mm, rsv->start, rsv->start + rsv->size,
+ if (gpu_buddy_alloc_blocks(mm, rsv->start, rsv->start + rsv->size,
rsv->size, mm->chunk_size, &rsv->allocated,
- DRM_BUDDY_RANGE_ALLOCATION))
+ GPU_BUDDY_RANGE_ALLOCATION))
continue;
block = amdgpu_vram_mgr_first_block(&rsv->allocated);
@@ -460,8 +461,8 @@ static int amdgpu_vram_mgr_new(struct tt
struct amdgpu_vram_mgr_resource *vres;
u64 size, remaining_size, lpfn, fpfn;
unsigned int adjust_dcc_size = 0;
- struct drm_buddy *mm = &mgr->mm;
- struct drm_buddy_block *block;
+ struct gpu_buddy *mm = &mgr->mm;
+ struct gpu_buddy_block *block;
unsigned long pages_per_block;
int r;
@@ -503,17 +504,17 @@ static int amdgpu_vram_mgr_new(struct tt
INIT_LIST_HEAD(&vres->blocks);
if (place->flags & TTM_PL_FLAG_TOPDOWN)
- vres->flags |= DRM_BUDDY_TOPDOWN_ALLOCATION;
+ vres->flags |= GPU_BUDDY_TOPDOWN_ALLOCATION;
if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS)
- vres->flags |= DRM_BUDDY_CONTIGUOUS_ALLOCATION;
+ vres->flags |= GPU_BUDDY_CONTIGUOUS_ALLOCATION;
if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CLEARED)
- vres->flags |= DRM_BUDDY_CLEAR_ALLOCATION;
+ vres->flags |= GPU_BUDDY_CLEAR_ALLOCATION;
if (fpfn || lpfn != mgr->mm.size)
/* Allocate blocks in desired range */
- vres->flags |= DRM_BUDDY_RANGE_ALLOCATION;
+ vres->flags |= GPU_BUDDY_RANGE_ALLOCATION;
if (bo->flags & AMDGPU_GEM_CREATE_GFX12_DCC &&
adev->gmc.gmc_funcs->get_dcc_alignment)
@@ -526,7 +527,7 @@ static int amdgpu_vram_mgr_new(struct tt
dcc_size = roundup_pow_of_two(vres->base.size + adjust_dcc_size);
remaining_size = (u64)dcc_size;
- vres->flags |= DRM_BUDDY_TRIM_DISABLE;
+ vres->flags |= GPU_BUDDY_TRIM_DISABLE;
}
mutex_lock(&mgr->lock);
@@ -546,7 +547,7 @@ static int amdgpu_vram_mgr_new(struct tt
BUG_ON(min_block_size < mm->chunk_size);
- r = drm_buddy_alloc_blocks(mm, fpfn,
+ r = gpu_buddy_alloc_blocks(mm, fpfn,
lpfn,
size,
min_block_size,
@@ -555,7 +556,7 @@ static int amdgpu_vram_mgr_new(struct tt
if (unlikely(r == -ENOSPC) && pages_per_block == ~0ul &&
!(place->flags & TTM_PL_FLAG_CONTIGUOUS)) {
- vres->flags &= ~DRM_BUDDY_CONTIGUOUS_ALLOCATION;
+ vres->flags &= ~GPU_BUDDY_CONTIGUOUS_ALLOCATION;
pages_per_block = max_t(u32, 2UL << (20UL - PAGE_SHIFT),
tbo->page_alignment);
@@ -572,7 +573,7 @@ static int amdgpu_vram_mgr_new(struct tt
}
if (bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS && adjust_dcc_size) {
- struct drm_buddy_block *dcc_block;
+ struct gpu_buddy_block *dcc_block;
unsigned long dcc_start;
u64 trim_start;
@@ -582,7 +583,7 @@ static int amdgpu_vram_mgr_new(struct tt
roundup((unsigned long)amdgpu_vram_mgr_block_start(dcc_block),
adjust_dcc_size);
trim_start = (u64)dcc_start;
- drm_buddy_block_trim(mm, &trim_start,
+ gpu_buddy_block_trim(mm, &trim_start,
(u64)vres->base.size,
&vres->blocks);
}
@@ -620,7 +621,7 @@ static int amdgpu_vram_mgr_new(struct tt
return 0;
error_free_blocks:
- drm_buddy_free_list(mm, &vres->blocks, 0);
+ gpu_buddy_free_list(mm, &vres->blocks, 0);
mutex_unlock(&mgr->lock);
error_fini:
ttm_resource_fini(man, &vres->base);
@@ -643,15 +644,15 @@ static void amdgpu_vram_mgr_del(struct t
struct amdgpu_vram_mgr_resource *vres = to_amdgpu_vram_mgr_resource(res);
struct amdgpu_vram_mgr *mgr = to_vram_mgr(man);
struct amdgpu_device *adev = to_amdgpu_device(mgr);
- struct drm_buddy *mm = &mgr->mm;
- struct drm_buddy_block *block;
+ struct gpu_buddy *mm = &mgr->mm;
+ struct gpu_buddy_block *block;
uint64_t vis_usage = 0;
mutex_lock(&mgr->lock);
list_for_each_entry(block, &vres->blocks, link)
vis_usage += amdgpu_vram_mgr_vis_size(adev, block);
- drm_buddy_free_list(mm, &vres->blocks, vres->flags);
+ gpu_buddy_free_list(mm, &vres->blocks, vres->flags);
amdgpu_vram_mgr_do_reserve(man);
mutex_unlock(&mgr->lock);
@@ -690,7 +691,7 @@ int amdgpu_vram_mgr_alloc_sgt(struct amd
if (!*sgt)
return -ENOMEM;
- /* Determine the number of DRM_BUDDY blocks to export */
+ /* Determine the number of GPU_BUDDY blocks to export */
amdgpu_res_first(res, offset, length, &cursor);
while (cursor.remaining) {
num_entries++;
@@ -706,10 +707,10 @@ int amdgpu_vram_mgr_alloc_sgt(struct amd
sg->length = 0;
/*
- * Walk down DRM_BUDDY blocks to populate scatterlist nodes
- * @note: Use iterator api to get first the DRM_BUDDY block
+ * Walk down GPU_BUDDY blocks to populate scatterlist nodes
+ * @note: Use iterator api to get first the GPU_BUDDY block
* and the number of bytes from it. Access the following
- * DRM_BUDDY block(s) if more buffer needs to exported
+ * GPU_BUDDY block(s) if more buffer needs to exported
*/
amdgpu_res_first(res, offset, length, &cursor);
for_each_sgtable_sg((*sgt), sg, i) {
@@ -794,10 +795,10 @@ uint64_t amdgpu_vram_mgr_vis_usage(struc
void amdgpu_vram_mgr_clear_reset_blocks(struct amdgpu_device *adev)
{
struct amdgpu_vram_mgr *mgr = &adev->mman.vram_mgr;
- struct drm_buddy *mm = &mgr->mm;
+ struct gpu_buddy *mm = &mgr->mm;
mutex_lock(&mgr->lock);
- drm_buddy_reset_clear(mm, false);
+ gpu_buddy_reset_clear(mm, false);
mutex_unlock(&mgr->lock);
}
@@ -817,7 +818,7 @@ static bool amdgpu_vram_mgr_intersects(s
size_t size)
{
struct amdgpu_vram_mgr_resource *mgr = to_amdgpu_vram_mgr_resource(res);
- struct drm_buddy_block *block;
+ struct gpu_buddy_block *block;
/* Check each drm buddy block individually */
list_for_each_entry(block, &mgr->blocks, link) {
@@ -850,7 +851,7 @@ static bool amdgpu_vram_mgr_compatible(s
size_t size)
{
struct amdgpu_vram_mgr_resource *mgr = to_amdgpu_vram_mgr_resource(res);
- struct drm_buddy_block *block;
+ struct gpu_buddy_block *block;
/* Check each drm buddy block individually */
list_for_each_entry(block, &mgr->blocks, link) {
@@ -879,7 +880,7 @@ static void amdgpu_vram_mgr_debug(struct
struct drm_printer *printer)
{
struct amdgpu_vram_mgr *mgr = to_vram_mgr(man);
- struct drm_buddy *mm = &mgr->mm;
+ struct gpu_buddy *mm = &mgr->mm;
struct amdgpu_vram_reservation *rsv;
drm_printf(printer, " vis usage:%llu\n",
@@ -938,7 +939,7 @@ int amdgpu_vram_mgr_init(struct amdgpu_d
if (!adev->gmc.is_app_apu) {
man->func = &amdgpu_vram_mgr_func;
- err = drm_buddy_init(&mgr->mm, man->size, PAGE_SIZE);
+ err = gpu_buddy_init(&mgr->mm, man->size, PAGE_SIZE);
if (err)
return err;
} else {
@@ -977,11 +978,11 @@ void amdgpu_vram_mgr_fini(struct amdgpu_
kfree(rsv);
list_for_each_entry_safe(rsv, temp, &mgr->reserved_pages, blocks) {
- drm_buddy_free_list(&mgr->mm, &rsv->allocated, 0);
+ gpu_buddy_free_list(&mgr->mm, &rsv->allocated, 0);
kfree(rsv);
}
if (!adev->gmc.is_app_apu)
- drm_buddy_fini(&mgr->mm);
+ gpu_buddy_fini(&mgr->mm);
mutex_unlock(&mgr->lock);
ttm_resource_manager_cleanup(man);
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h
@@ -24,11 +24,11 @@
#ifndef __AMDGPU_VRAM_MGR_H__
#define __AMDGPU_VRAM_MGR_H__
-#include <drm/drm_buddy.h>
+#include <linux/gpu_buddy.h>
struct amdgpu_vram_mgr {
struct ttm_resource_manager manager;
- struct drm_buddy mm;
+ struct gpu_buddy mm;
/* protects access to buffer objects */
struct mutex lock;
struct list_head reservations_pending;
@@ -43,19 +43,19 @@ struct amdgpu_vram_mgr_resource {
unsigned long flags;
};
-static inline u64 amdgpu_vram_mgr_block_start(struct drm_buddy_block *block)
+static inline u64 amdgpu_vram_mgr_block_start(struct gpu_buddy_block *block)
{
- return drm_buddy_block_offset(block);
+ return gpu_buddy_block_offset(block);
}
-static inline u64 amdgpu_vram_mgr_block_size(struct drm_buddy_block *block)
+static inline u64 amdgpu_vram_mgr_block_size(struct gpu_buddy_block *block)
{
- return (u64)PAGE_SIZE << drm_buddy_block_order(block);
+ return (u64)PAGE_SIZE << gpu_buddy_block_order(block);
}
-static inline bool amdgpu_vram_mgr_is_cleared(struct drm_buddy_block *block)
+static inline bool amdgpu_vram_mgr_is_cleared(struct gpu_buddy_block *block)
{
- return drm_buddy_block_is_clear(block);
+ return gpu_buddy_block_is_clear(block);
}
static inline struct amdgpu_vram_mgr_resource *
@@ -66,7 +66,7 @@ to_amdgpu_vram_mgr_resource(struct ttm_r
static inline void amdgpu_vram_mgr_set_cleared(struct ttm_resource *res)
{
- to_amdgpu_vram_mgr_resource(res)->flags |= DRM_BUDDY_CLEARED;
+ to_amdgpu_vram_mgr_resource(res)->flags |= GPU_BUDDY_CLEARED;
}
#endif
--- a/drivers/gpu/drm/drm_buddy.c
+++ b/drivers/gpu/drm/drm_buddy.c
@@ -3,1252 +3,16 @@
* Copyright © 2021 Intel Corporation
*/
+#include <kunit/test-bug.h>
+
+#include <linux/export.h>
#include <linux/kmemleak.h>
#include <linux/module.h>
#include <linux/sizes.h>
+#include <linux/gpu_buddy.h>
#include <drm/drm_buddy.h>
-
-enum drm_buddy_free_tree {
- DRM_BUDDY_CLEAR_TREE = 0,
- DRM_BUDDY_DIRTY_TREE,
- DRM_BUDDY_MAX_FREE_TREES,
-};
-
-static struct kmem_cache *slab_blocks;
-
-#define for_each_free_tree(tree) \
- for ((tree) = 0; (tree) < DRM_BUDDY_MAX_FREE_TREES; (tree)++)
-
-static struct drm_buddy_block *drm_block_alloc(struct drm_buddy *mm,
- struct drm_buddy_block *parent,
- unsigned int order,
- u64 offset)
-{
- struct drm_buddy_block *block;
-
- BUG_ON(order > DRM_BUDDY_MAX_ORDER);
-
- block = kmem_cache_zalloc(slab_blocks, GFP_KERNEL);
- if (!block)
- return NULL;
-
- block->header = offset;
- block->header |= order;
- block->parent = parent;
-
- RB_CLEAR_NODE(&block->rb);
-
- BUG_ON(block->header & DRM_BUDDY_HEADER_UNUSED);
- return block;
-}
-
-static void drm_block_free(struct drm_buddy *mm,
- struct drm_buddy_block *block)
-{
- kmem_cache_free(slab_blocks, block);
-}
-
-static enum drm_buddy_free_tree
-get_block_tree(struct drm_buddy_block *block)
-{
- return drm_buddy_block_is_clear(block) ?
- DRM_BUDDY_CLEAR_TREE : DRM_BUDDY_DIRTY_TREE;
-}
-
-static struct drm_buddy_block *
-rbtree_get_free_block(const struct rb_node *node)
-{
- return node ? rb_entry(node, struct drm_buddy_block, rb) : NULL;
-}
-
-static struct drm_buddy_block *
-rbtree_last_free_block(struct rb_root *root)
-{
- return rbtree_get_free_block(rb_last(root));
-}
-
-static bool rbtree_is_empty(struct rb_root *root)
-{
- return RB_EMPTY_ROOT(root);
-}
-
-static bool drm_buddy_block_offset_less(const struct drm_buddy_block *block,
- const struct drm_buddy_block *node)
-{
- return drm_buddy_block_offset(block) < drm_buddy_block_offset(node);
-}
-
-static bool rbtree_block_offset_less(struct rb_node *block,
- const struct rb_node *node)
-{
- return drm_buddy_block_offset_less(rbtree_get_free_block(block),
- rbtree_get_free_block(node));
-}
-
-static void rbtree_insert(struct drm_buddy *mm,
- struct drm_buddy_block *block,
- enum drm_buddy_free_tree tree)
-{
- rb_add(&block->rb,
- &mm->free_trees[tree][drm_buddy_block_order(block)],
- rbtree_block_offset_less);
-}
-
-static void rbtree_remove(struct drm_buddy *mm,
- struct drm_buddy_block *block)
-{
- unsigned int order = drm_buddy_block_order(block);
- enum drm_buddy_free_tree tree;
- struct rb_root *root;
-
- tree = get_block_tree(block);
- root = &mm->free_trees[tree][order];
-
- rb_erase(&block->rb, root);
- RB_CLEAR_NODE(&block->rb);
-}
-
-static void clear_reset(struct drm_buddy_block *block)
-{
- block->header &= ~DRM_BUDDY_HEADER_CLEAR;
-}
-
-static void mark_cleared(struct drm_buddy_block *block)
-{
- block->header |= DRM_BUDDY_HEADER_CLEAR;
-}
-
-static void mark_allocated(struct drm_buddy *mm,
- struct drm_buddy_block *block)
-{
- block->header &= ~DRM_BUDDY_HEADER_STATE;
- block->header |= DRM_BUDDY_ALLOCATED;
-
- rbtree_remove(mm, block);
-}
-
-static void mark_free(struct drm_buddy *mm,
- struct drm_buddy_block *block)
-{
- enum drm_buddy_free_tree tree;
-
- block->header &= ~DRM_BUDDY_HEADER_STATE;
- block->header |= DRM_BUDDY_FREE;
-
- tree = get_block_tree(block);
- rbtree_insert(mm, block, tree);
-}
-
-static void mark_split(struct drm_buddy *mm,
- struct drm_buddy_block *block)
-{
- block->header &= ~DRM_BUDDY_HEADER_STATE;
- block->header |= DRM_BUDDY_SPLIT;
-
- rbtree_remove(mm, block);
-}
-
-static inline bool overlaps(u64 s1, u64 e1, u64 s2, u64 e2)
-{
- return s1 <= e2 && e1 >= s2;
-}
-
-static inline bool contains(u64 s1, u64 e1, u64 s2, u64 e2)
-{
- return s1 <= s2 && e1 >= e2;
-}
-
-static struct drm_buddy_block *
-__get_buddy(struct drm_buddy_block *block)
-{
- struct drm_buddy_block *parent;
-
- parent = block->parent;
- if (!parent)
- return NULL;
-
- if (parent->left == block)
- return parent->right;
-
- return parent->left;
-}
-
-static unsigned int __drm_buddy_free(struct drm_buddy *mm,
- struct drm_buddy_block *block,
- bool force_merge)
-{
- struct drm_buddy_block *parent;
- unsigned int order;
-
- while ((parent = block->parent)) {
- struct drm_buddy_block *buddy;
-
- buddy = __get_buddy(block);
-
- if (!drm_buddy_block_is_free(buddy))
- break;
-
- if (!force_merge) {
- /*
- * Check the block and its buddy clear state and exit
- * the loop if they both have the dissimilar state.
- */
- if (drm_buddy_block_is_clear(block) !=
- drm_buddy_block_is_clear(buddy))
- break;
-
- if (drm_buddy_block_is_clear(block))
- mark_cleared(parent);
- }
-
- rbtree_remove(mm, buddy);
- if (force_merge && drm_buddy_block_is_clear(buddy))
- mm->clear_avail -= drm_buddy_block_size(mm, buddy);
-
- drm_block_free(mm, block);
- drm_block_free(mm, buddy);
-
- block = parent;
- }
-
- order = drm_buddy_block_order(block);
- mark_free(mm, block);
-
- return order;
-}
-
-static int __force_merge(struct drm_buddy *mm,
- u64 start,
- u64 end,
- unsigned int min_order)
-{
- unsigned int tree, order;
- int i;
-
- if (!min_order)
- return -ENOMEM;
-
- if (min_order > mm->max_order)
- return -EINVAL;
-
- for_each_free_tree(tree) {
- for (i = min_order - 1; i >= 0; i--) {
- struct rb_node *iter = rb_last(&mm->free_trees[tree][i]);
-
- while (iter) {
- struct drm_buddy_block *block, *buddy;
- u64 block_start, block_end;
-
- block = rbtree_get_free_block(iter);
- iter = rb_prev(iter);
-
- if (!block || !block->parent)
- continue;
-
- block_start = drm_buddy_block_offset(block);
- block_end = block_start + drm_buddy_block_size(mm, block) - 1;
-
- if (!contains(start, end, block_start, block_end))
- continue;
-
- buddy = __get_buddy(block);
- if (!drm_buddy_block_is_free(buddy))
- continue;
-
- WARN_ON(drm_buddy_block_is_clear(block) ==
- drm_buddy_block_is_clear(buddy));
-
- /*
- * Advance to the next node when the current node is the buddy,
- * as freeing the block will also remove its buddy from the tree.
- */
- if (iter == &buddy->rb)
- iter = rb_prev(iter);
-
- rbtree_remove(mm, block);
- if (drm_buddy_block_is_clear(block))
- mm->clear_avail -= drm_buddy_block_size(mm, block);
-
- order = __drm_buddy_free(mm, block, true);
- if (order >= min_order)
- return 0;
- }
- }
- }
-
- return -ENOMEM;
-}
-
-/**
- * drm_buddy_init - init memory manager
- *
- * @mm: DRM buddy manager to initialize
- * @size: size in bytes to manage
- * @chunk_size: minimum page size in bytes for our allocations
- *
- * Initializes the memory manager and its resources.
- *
- * Returns:
- * 0 on success, error code on failure.
- */
-int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size)
-{
- unsigned int i, j, root_count = 0;
- u64 offset = 0;
-
- if (size < chunk_size)
- return -EINVAL;
-
- if (chunk_size < SZ_4K)
- return -EINVAL;
-
- if (!is_power_of_2(chunk_size))
- return -EINVAL;
-
- size = round_down(size, chunk_size);
-
- mm->size = size;
- mm->avail = size;
- mm->clear_avail = 0;
- mm->chunk_size = chunk_size;
- mm->max_order = ilog2(size) - ilog2(chunk_size);
-
- BUG_ON(mm->max_order > DRM_BUDDY_MAX_ORDER);
-
- mm->free_trees = kmalloc_array(DRM_BUDDY_MAX_FREE_TREES,
- sizeof(*mm->free_trees),
- GFP_KERNEL);
- if (!mm->free_trees)
- return -ENOMEM;
-
- for_each_free_tree(i) {
- mm->free_trees[i] = kmalloc_array(mm->max_order + 1,
- sizeof(struct rb_root),
- GFP_KERNEL);
- if (!mm->free_trees[i])
- goto out_free_tree;
-
- for (j = 0; j <= mm->max_order; ++j)
- mm->free_trees[i][j] = RB_ROOT;
- }
-
- mm->n_roots = hweight64(size);
-
- mm->roots = kmalloc_array(mm->n_roots,
- sizeof(struct drm_buddy_block *),
- GFP_KERNEL);
- if (!mm->roots)
- goto out_free_tree;
-
- /*
- * Split into power-of-two blocks, in case we are given a size that is
- * not itself a power-of-two.
- */
- do {
- struct drm_buddy_block *root;
- unsigned int order;
- u64 root_size;
-
- order = ilog2(size) - ilog2(chunk_size);
- root_size = chunk_size << order;
-
- root = drm_block_alloc(mm, NULL, order, offset);
- if (!root)
- goto out_free_roots;
-
- mark_free(mm, root);
-
- BUG_ON(root_count > mm->max_order);
- BUG_ON(drm_buddy_block_size(mm, root) < chunk_size);
-
- mm->roots[root_count] = root;
-
- offset += root_size;
- size -= root_size;
- root_count++;
- } while (size);
-
- return 0;
-
-out_free_roots:
- while (root_count--)
- drm_block_free(mm, mm->roots[root_count]);
- kfree(mm->roots);
-out_free_tree:
- while (i--)
- kfree(mm->free_trees[i]);
- kfree(mm->free_trees);
- return -ENOMEM;
-}
-EXPORT_SYMBOL(drm_buddy_init);
-
-/**
- * drm_buddy_fini - tear down the memory manager
- *
- * @mm: DRM buddy manager to free
- *
- * Cleanup memory manager resources and the freetree
- */
-void drm_buddy_fini(struct drm_buddy *mm)
-{
- u64 root_size, size, start;
- unsigned int order;
- int i;
-
- size = mm->size;
-
- for (i = 0; i < mm->n_roots; ++i) {
- order = ilog2(size) - ilog2(mm->chunk_size);
- start = drm_buddy_block_offset(mm->roots[i]);
- __force_merge(mm, start, start + size, order);
-
- WARN_ON(!drm_buddy_block_is_free(mm->roots[i]));
- drm_block_free(mm, mm->roots[i]);
-
- root_size = mm->chunk_size << order;
- size -= root_size;
- }
-
- WARN_ON(mm->avail != mm->size);
-
- for_each_free_tree(i)
- kfree(mm->free_trees[i]);
- kfree(mm->free_trees);
- kfree(mm->roots);
-}
-EXPORT_SYMBOL(drm_buddy_fini);
-
-static int split_block(struct drm_buddy *mm,
- struct drm_buddy_block *block)
-{
- unsigned int block_order = drm_buddy_block_order(block) - 1;
- u64 offset = drm_buddy_block_offset(block);
-
- BUG_ON(!drm_buddy_block_is_free(block));
- BUG_ON(!drm_buddy_block_order(block));
-
- block->left = drm_block_alloc(mm, block, block_order, offset);
- if (!block->left)
- return -ENOMEM;
-
- block->right = drm_block_alloc(mm, block, block_order,
- offset + (mm->chunk_size << block_order));
- if (!block->right) {
- drm_block_free(mm, block->left);
- return -ENOMEM;
- }
-
- mark_split(mm, block);
-
- if (drm_buddy_block_is_clear(block)) {
- mark_cleared(block->left);
- mark_cleared(block->right);
- clear_reset(block);
- }
-
- mark_free(mm, block->left);
- mark_free(mm, block->right);
-
- return 0;
-}
-
-/**
- * drm_get_buddy - get buddy address
- *
- * @block: DRM buddy block
- *
- * Returns the corresponding buddy block for @block, or NULL
- * if this is a root block and can't be merged further.
- * Requires some kind of locking to protect against
- * any concurrent allocate and free operations.
- */
-struct drm_buddy_block *
-drm_get_buddy(struct drm_buddy_block *block)
-{
- return __get_buddy(block);
-}
-EXPORT_SYMBOL(drm_get_buddy);
-
-/**
- * drm_buddy_reset_clear - reset blocks clear state
- *
- * @mm: DRM buddy manager
- * @is_clear: blocks clear state
- *
- * Reset the clear state based on @is_clear value for each block
- * in the freetree.
- */
-void drm_buddy_reset_clear(struct drm_buddy *mm, bool is_clear)
-{
- enum drm_buddy_free_tree src_tree, dst_tree;
- u64 root_size, size, start;
- unsigned int order;
- int i;
-
- size = mm->size;
- for (i = 0; i < mm->n_roots; ++i) {
- order = ilog2(size) - ilog2(mm->chunk_size);
- start = drm_buddy_block_offset(mm->roots[i]);
- __force_merge(mm, start, start + size, order);
-
- root_size = mm->chunk_size << order;
- size -= root_size;
- }
-
- src_tree = is_clear ? DRM_BUDDY_DIRTY_TREE : DRM_BUDDY_CLEAR_TREE;
- dst_tree = is_clear ? DRM_BUDDY_CLEAR_TREE : DRM_BUDDY_DIRTY_TREE;
-
- for (i = 0; i <= mm->max_order; ++i) {
- struct rb_root *root = &mm->free_trees[src_tree][i];
- struct drm_buddy_block *block, *tmp;
-
- rbtree_postorder_for_each_entry_safe(block, tmp, root, rb) {
- rbtree_remove(mm, block);
- if (is_clear) {
- mark_cleared(block);
- mm->clear_avail += drm_buddy_block_size(mm, block);
- } else {
- clear_reset(block);
- mm->clear_avail -= drm_buddy_block_size(mm, block);
- }
-
- rbtree_insert(mm, block, dst_tree);
- }
- }
-}
-EXPORT_SYMBOL(drm_buddy_reset_clear);
-
-/**
- * drm_buddy_free_block - free a block
- *
- * @mm: DRM buddy manager
- * @block: block to be freed
- */
-void drm_buddy_free_block(struct drm_buddy *mm,
- struct drm_buddy_block *block)
-{
- BUG_ON(!drm_buddy_block_is_allocated(block));
- mm->avail += drm_buddy_block_size(mm, block);
- if (drm_buddy_block_is_clear(block))
- mm->clear_avail += drm_buddy_block_size(mm, block);
-
- __drm_buddy_free(mm, block, false);
-}
-EXPORT_SYMBOL(drm_buddy_free_block);
-
-static void __drm_buddy_free_list(struct drm_buddy *mm,
- struct list_head *objects,
- bool mark_clear,
- bool mark_dirty)
-{
- struct drm_buddy_block *block, *on;
-
- WARN_ON(mark_dirty && mark_clear);
-
- list_for_each_entry_safe(block, on, objects, link) {
- if (mark_clear)
- mark_cleared(block);
- else if (mark_dirty)
- clear_reset(block);
- drm_buddy_free_block(mm, block);
- cond_resched();
- }
- INIT_LIST_HEAD(objects);
-}
-
-static void drm_buddy_free_list_internal(struct drm_buddy *mm,
- struct list_head *objects)
-{
- /*
- * Don't touch the clear/dirty bit, since allocation is still internal
- * at this point. For example we might have just failed part of the
- * allocation.
- */
- __drm_buddy_free_list(mm, objects, false, false);
-}
-
-/**
- * drm_buddy_free_list - free blocks
- *
- * @mm: DRM buddy manager
- * @objects: input list head to free blocks
- * @flags: optional flags like DRM_BUDDY_CLEARED
- */
-void drm_buddy_free_list(struct drm_buddy *mm,
- struct list_head *objects,
- unsigned int flags)
-{
- bool mark_clear = flags & DRM_BUDDY_CLEARED;
-
- __drm_buddy_free_list(mm, objects, mark_clear, !mark_clear);
-}
-EXPORT_SYMBOL(drm_buddy_free_list);
-
-static bool block_incompatible(struct drm_buddy_block *block, unsigned int flags)
-{
- bool needs_clear = flags & DRM_BUDDY_CLEAR_ALLOCATION;
-
- return needs_clear != drm_buddy_block_is_clear(block);
-}
-
-static struct drm_buddy_block *
-__alloc_range_bias(struct drm_buddy *mm,
- u64 start, u64 end,
- unsigned int order,
- unsigned long flags,
- bool fallback)
-{
- u64 req_size = mm->chunk_size << order;
- struct drm_buddy_block *block;
- struct drm_buddy_block *buddy;
- LIST_HEAD(dfs);
- int err;
- int i;
-
- end = end - 1;
-
- for (i = 0; i < mm->n_roots; ++i)
- list_add_tail(&mm->roots[i]->tmp_link, &dfs);
-
- do {
- u64 block_start;
- u64 block_end;
-
- block = list_first_entry_or_null(&dfs,
- struct drm_buddy_block,
- tmp_link);
- if (!block)
- break;
-
- list_del(&block->tmp_link);
-
- if (drm_buddy_block_order(block) < order)
- continue;
-
- block_start = drm_buddy_block_offset(block);
- block_end = block_start + drm_buddy_block_size(mm, block) - 1;
-
- if (!overlaps(start, end, block_start, block_end))
- continue;
-
- if (drm_buddy_block_is_allocated(block))
- continue;
-
- if (block_start < start || block_end > end) {
- u64 adjusted_start = max(block_start, start);
- u64 adjusted_end = min(block_end, end);
-
- if (round_down(adjusted_end + 1, req_size) <=
- round_up(adjusted_start, req_size))
- continue;
- }
-
- if (!fallback && block_incompatible(block, flags))
- continue;
-
- if (contains(start, end, block_start, block_end) &&
- order == drm_buddy_block_order(block)) {
- /*
- * Find the free block within the range.
- */
- if (drm_buddy_block_is_free(block))
- return block;
-
- continue;
- }
-
- if (!drm_buddy_block_is_split(block)) {
- err = split_block(mm, block);
- if (unlikely(err))
- goto err_undo;
- }
-
- list_add(&block->right->tmp_link, &dfs);
- list_add(&block->left->tmp_link, &dfs);
- } while (1);
-
- return ERR_PTR(-ENOSPC);
-
-err_undo:
- /*
- * We really don't want to leave around a bunch of split blocks, since
- * bigger is better, so make sure we merge everything back before we
- * free the allocated blocks.
- */
- buddy = __get_buddy(block);
- if (buddy &&
- (drm_buddy_block_is_free(block) &&
- drm_buddy_block_is_free(buddy)))
- __drm_buddy_free(mm, block, false);
- return ERR_PTR(err);
-}
-
-static struct drm_buddy_block *
-__drm_buddy_alloc_range_bias(struct drm_buddy *mm,
- u64 start, u64 end,
- unsigned int order,
- unsigned long flags)
-{
- struct drm_buddy_block *block;
- bool fallback = false;
-
- block = __alloc_range_bias(mm, start, end, order,
- flags, fallback);
- if (IS_ERR(block))
- return __alloc_range_bias(mm, start, end, order,
- flags, !fallback);
-
- return block;
-}
-
-static struct drm_buddy_block *
-get_maxblock(struct drm_buddy *mm,
- unsigned int order,
- enum drm_buddy_free_tree tree)
-{
- struct drm_buddy_block *max_block = NULL, *block = NULL;
- struct rb_root *root;
- unsigned int i;
-
- for (i = order; i <= mm->max_order; ++i) {
- root = &mm->free_trees[tree][i];
- block = rbtree_last_free_block(root);
- if (!block)
- continue;
-
- if (!max_block) {
- max_block = block;
- continue;
- }
-
- if (drm_buddy_block_offset(block) >
- drm_buddy_block_offset(max_block)) {
- max_block = block;
- }
- }
-
- return max_block;
-}
-
-static struct drm_buddy_block *
-alloc_from_freetree(struct drm_buddy *mm,
- unsigned int order,
- unsigned long flags)
-{
- struct drm_buddy_block *block = NULL;
- struct rb_root *root;
- enum drm_buddy_free_tree tree;
- unsigned int tmp;
- int err;
-
- tree = (flags & DRM_BUDDY_CLEAR_ALLOCATION) ?
- DRM_BUDDY_CLEAR_TREE : DRM_BUDDY_DIRTY_TREE;
-
- if (flags & DRM_BUDDY_TOPDOWN_ALLOCATION) {
- block = get_maxblock(mm, order, tree);
- if (block)
- /* Store the obtained block order */
- tmp = drm_buddy_block_order(block);
- } else {
- for (tmp = order; tmp <= mm->max_order; ++tmp) {
- /* Get RB tree root for this order and tree */
- root = &mm->free_trees[tree][tmp];
- block = rbtree_last_free_block(root);
- if (block)
- break;
- }
- }
-
- if (!block) {
- /* Try allocating from the other tree */
- tree = (tree == DRM_BUDDY_CLEAR_TREE) ?
- DRM_BUDDY_DIRTY_TREE : DRM_BUDDY_CLEAR_TREE;
-
- for (tmp = order; tmp <= mm->max_order; ++tmp) {
- root = &mm->free_trees[tree][tmp];
- block = rbtree_last_free_block(root);
- if (block)
- break;
- }
-
- if (!block)
- return ERR_PTR(-ENOSPC);
- }
-
- BUG_ON(!drm_buddy_block_is_free(block));
-
- while (tmp != order) {
- err = split_block(mm, block);
- if (unlikely(err))
- goto err_undo;
-
- block = block->right;
- tmp--;
- }
- return block;
-
-err_undo:
- if (tmp != order)
- __drm_buddy_free(mm, block, false);
- return ERR_PTR(err);
-}
-
-static int __alloc_range(struct drm_buddy *mm,
- struct list_head *dfs,
- u64 start, u64 size,
- struct list_head *blocks,
- u64 *total_allocated_on_err)
-{
- struct drm_buddy_block *block;
- struct drm_buddy_block *buddy;
- u64 total_allocated = 0;
- LIST_HEAD(allocated);
- u64 end;
- int err;
-
- end = start + size - 1;
-
- do {
- u64 block_start;
- u64 block_end;
-
- block = list_first_entry_or_null(dfs,
- struct drm_buddy_block,
- tmp_link);
- if (!block)
- break;
-
- list_del(&block->tmp_link);
-
- block_start = drm_buddy_block_offset(block);
- block_end = block_start + drm_buddy_block_size(mm, block) - 1;
-
- if (!overlaps(start, end, block_start, block_end))
- continue;
-
- if (drm_buddy_block_is_allocated(block)) {
- err = -ENOSPC;
- goto err_free;
- }
-
- if (contains(start, end, block_start, block_end)) {
- if (drm_buddy_block_is_free(block)) {
- mark_allocated(mm, block);
- total_allocated += drm_buddy_block_size(mm, block);
- mm->avail -= drm_buddy_block_size(mm, block);
- if (drm_buddy_block_is_clear(block))
- mm->clear_avail -= drm_buddy_block_size(mm, block);
- list_add_tail(&block->link, &allocated);
- continue;
- } else if (!mm->clear_avail) {
- err = -ENOSPC;
- goto err_free;
- }
- }
-
- if (!drm_buddy_block_is_split(block)) {
- err = split_block(mm, block);
- if (unlikely(err))
- goto err_undo;
- }
-
- list_add(&block->right->tmp_link, dfs);
- list_add(&block->left->tmp_link, dfs);
- } while (1);
-
- if (total_allocated < size) {
- err = -ENOSPC;
- goto err_free;
- }
-
- list_splice_tail(&allocated, blocks);
-
- return 0;
-
-err_undo:
- /*
- * We really don't want to leave around a bunch of split blocks, since
- * bigger is better, so make sure we merge everything back before we
- * free the allocated blocks.
- */
- buddy = __get_buddy(block);
- if (buddy &&
- (drm_buddy_block_is_free(block) &&
- drm_buddy_block_is_free(buddy)))
- __drm_buddy_free(mm, block, false);
-
-err_free:
- if (err == -ENOSPC && total_allocated_on_err) {
- list_splice_tail(&allocated, blocks);
- *total_allocated_on_err = total_allocated;
- } else {
- drm_buddy_free_list_internal(mm, &allocated);
- }
-
- return err;
-}
-
-static int __drm_buddy_alloc_range(struct drm_buddy *mm,
- u64 start,
- u64 size,
- u64 *total_allocated_on_err,
- struct list_head *blocks)
-{
- LIST_HEAD(dfs);
- int i;
-
- for (i = 0; i < mm->n_roots; ++i)
- list_add_tail(&mm->roots[i]->tmp_link, &dfs);
-
- return __alloc_range(mm, &dfs, start, size,
- blocks, total_allocated_on_err);
-}
-
-static int __alloc_contig_try_harder(struct drm_buddy *mm,
- u64 size,
- u64 min_block_size,
- struct list_head *blocks)
-{
- u64 rhs_offset, lhs_offset, lhs_size, filled;
- struct drm_buddy_block *block;
- unsigned int tree, order;
- LIST_HEAD(blocks_lhs);
- unsigned long pages;
- u64 modify_size;
- int err;
-
- modify_size = rounddown_pow_of_two(size);
- pages = modify_size >> ilog2(mm->chunk_size);
- order = fls(pages) - 1;
- if (order == 0)
- return -ENOSPC;
-
- for_each_free_tree(tree) {
- struct rb_root *root;
- struct rb_node *iter;
-
- root = &mm->free_trees[tree][order];
- if (rbtree_is_empty(root))
- continue;
-
- iter = rb_last(root);
- while (iter) {
- block = rbtree_get_free_block(iter);
-
- /* Allocate blocks traversing RHS */
- rhs_offset = drm_buddy_block_offset(block);
- err = __drm_buddy_alloc_range(mm, rhs_offset, size,
- &filled, blocks);
- if (!err || err != -ENOSPC)
- return err;
-
- lhs_size = max((size - filled), min_block_size);
- if (!IS_ALIGNED(lhs_size, min_block_size))
- lhs_size = round_up(lhs_size, min_block_size);
-
- /* Allocate blocks traversing LHS */
- lhs_offset = drm_buddy_block_offset(block) - lhs_size;
- err = __drm_buddy_alloc_range(mm, lhs_offset, lhs_size,
- NULL, &blocks_lhs);
- if (!err) {
- list_splice(&blocks_lhs, blocks);
- return 0;
- } else if (err != -ENOSPC) {
- drm_buddy_free_list_internal(mm, blocks);
- return err;
- }
- /* Free blocks for the next iteration */
- drm_buddy_free_list_internal(mm, blocks);
-
- iter = rb_prev(iter);
- }
- }
-
- return -ENOSPC;
-}
-
-/**
- * drm_buddy_block_trim - free unused pages
- *
- * @mm: DRM buddy manager
- * @start: start address to begin the trimming.
- * @new_size: original size requested
- * @blocks: Input and output list of allocated blocks.
- * MUST contain single block as input to be trimmed.
- * On success will contain the newly allocated blocks
- * making up the @new_size. Blocks always appear in
- * ascending order
- *
- * For contiguous allocation, we round up the size to the nearest
- * power of two value, drivers consume *actual* size, so remaining
- * portions are unused and can be optionally freed with this function
- *
- * Returns:
- * 0 on success, error code on failure.
- */
-int drm_buddy_block_trim(struct drm_buddy *mm,
- u64 *start,
- u64 new_size,
- struct list_head *blocks)
-{
- struct drm_buddy_block *parent;
- struct drm_buddy_block *block;
- u64 block_start, block_end;
- LIST_HEAD(dfs);
- u64 new_start;
- int err;
-
- if (!list_is_singular(blocks))
- return -EINVAL;
-
- block = list_first_entry(blocks,
- struct drm_buddy_block,
- link);
-
- block_start = drm_buddy_block_offset(block);
- block_end = block_start + drm_buddy_block_size(mm, block);
-
- if (WARN_ON(!drm_buddy_block_is_allocated(block)))
- return -EINVAL;
-
- if (new_size > drm_buddy_block_size(mm, block))
- return -EINVAL;
-
- if (!new_size || !IS_ALIGNED(new_size, mm->chunk_size))
- return -EINVAL;
-
- if (new_size == drm_buddy_block_size(mm, block))
- return 0;
-
- new_start = block_start;
- if (start) {
- new_start = *start;
-
- if (new_start < block_start)
- return -EINVAL;
-
- if (!IS_ALIGNED(new_start, mm->chunk_size))
- return -EINVAL;
-
- if (range_overflows(new_start, new_size, block_end))
- return -EINVAL;
- }
-
- list_del(&block->link);
- mark_free(mm, block);
- mm->avail += drm_buddy_block_size(mm, block);
- if (drm_buddy_block_is_clear(block))
- mm->clear_avail += drm_buddy_block_size(mm, block);
-
- /* Prevent recursively freeing this node */
- parent = block->parent;
- block->parent = NULL;
-
- list_add(&block->tmp_link, &dfs);
- err = __alloc_range(mm, &dfs, new_start, new_size, blocks, NULL);
- if (err) {
- mark_allocated(mm, block);
- mm->avail -= drm_buddy_block_size(mm, block);
- if (drm_buddy_block_is_clear(block))
- mm->clear_avail -= drm_buddy_block_size(mm, block);
- list_add(&block->link, blocks);
- }
-
- block->parent = parent;
- return err;
-}
-EXPORT_SYMBOL(drm_buddy_block_trim);
-
-static struct drm_buddy_block *
-__drm_buddy_alloc_blocks(struct drm_buddy *mm,
- u64 start, u64 end,
- unsigned int order,
- unsigned long flags)
-{
- if (flags & DRM_BUDDY_RANGE_ALLOCATION)
- /* Allocate traversing within the range */
- return __drm_buddy_alloc_range_bias(mm, start, end,
- order, flags);
- else
- /* Allocate from freetree */
- return alloc_from_freetree(mm, order, flags);
-}
-
-/**
- * drm_buddy_alloc_blocks - allocate power-of-two blocks
- *
- * @mm: DRM buddy manager to allocate from
- * @start: start of the allowed range for this block
- * @end: end of the allowed range for this block
- * @size: size of the allocation in bytes
- * @min_block_size: alignment of the allocation
- * @blocks: output list head to add allocated blocks
- * @flags: DRM_BUDDY_*_ALLOCATION flags
- *
- * alloc_range_bias() called on range limitations, which traverses
- * the tree and returns the desired block.
- *
- * alloc_from_freetree() called when *no* range restrictions
- * are enforced, which picks the block from the freetree.
- *
- * Returns:
- * 0 on success, error code on failure.
- */
-int drm_buddy_alloc_blocks(struct drm_buddy *mm,
- u64 start, u64 end, u64 size,
- u64 min_block_size,
- struct list_head *blocks,
- unsigned long flags)
-{
- struct drm_buddy_block *block = NULL;
- u64 original_size, original_min_size;
- unsigned int min_order, order;
- LIST_HEAD(allocated);
- unsigned long pages;
- int err;
-
- if (size < mm->chunk_size)
- return -EINVAL;
-
- if (min_block_size < mm->chunk_size)
- return -EINVAL;
-
- if (!is_power_of_2(min_block_size))
- return -EINVAL;
-
- if (!IS_ALIGNED(start | end | size, mm->chunk_size))
- return -EINVAL;
-
- if (end > mm->size)
- return -EINVAL;
-
- if (range_overflows(start, size, mm->size))
- return -EINVAL;
-
- /* Actual range allocation */
- if (start + size == end) {
- if (!IS_ALIGNED(start | end, min_block_size))
- return -EINVAL;
-
- return __drm_buddy_alloc_range(mm, start, size, NULL, blocks);
- }
-
- original_size = size;
- original_min_size = min_block_size;
-
- /* Roundup the size to power of 2 */
- if (flags & DRM_BUDDY_CONTIGUOUS_ALLOCATION) {
- size = roundup_pow_of_two(size);
- min_block_size = size;
- /* Align size value to min_block_size */
- } else if (!IS_ALIGNED(size, min_block_size)) {
- size = round_up(size, min_block_size);
- }
-
- pages = size >> ilog2(mm->chunk_size);
- order = fls(pages) - 1;
- min_order = ilog2(min_block_size) - ilog2(mm->chunk_size);
-
- if (order > mm->max_order || size > mm->size) {
- if ((flags & DRM_BUDDY_CONTIGUOUS_ALLOCATION) &&
- !(flags & DRM_BUDDY_RANGE_ALLOCATION))
- return __alloc_contig_try_harder(mm, original_size,
- original_min_size, blocks);
-
- return -EINVAL;
- }
-
- do {
- order = min(order, (unsigned int)fls(pages) - 1);
- BUG_ON(order > mm->max_order);
- BUG_ON(order < min_order);
-
- do {
- block = __drm_buddy_alloc_blocks(mm, start,
- end,
- order,
- flags);
- if (!IS_ERR(block))
- break;
-
- if (order-- == min_order) {
- /* Try allocation through force merge method */
- if (mm->clear_avail &&
- !__force_merge(mm, start, end, min_order)) {
- block = __drm_buddy_alloc_blocks(mm, start,
- end,
- min_order,
- flags);
- if (!IS_ERR(block)) {
- order = min_order;
- break;
- }
- }
-
- /*
- * Try contiguous block allocation through
- * try harder method.
- */
- if (flags & DRM_BUDDY_CONTIGUOUS_ALLOCATION &&
- !(flags & DRM_BUDDY_RANGE_ALLOCATION))
- return __alloc_contig_try_harder(mm,
- original_size,
- original_min_size,
- blocks);
- err = -ENOSPC;
- goto err_free;
- }
- } while (1);
-
- mark_allocated(mm, block);
- mm->avail -= drm_buddy_block_size(mm, block);
- if (drm_buddy_block_is_clear(block))
- mm->clear_avail -= drm_buddy_block_size(mm, block);
- kmemleak_update_trace(block);
- list_add_tail(&block->link, &allocated);
-
- pages -= BIT(order);
-
- if (!pages)
- break;
- } while (1);
-
- /* Trim the allocated block to the required size */
- if (!(flags & DRM_BUDDY_TRIM_DISABLE) &&
- original_size != size) {
- struct list_head *trim_list;
- LIST_HEAD(temp);
- u64 trim_size;
-
- trim_list = &allocated;
- trim_size = original_size;
-
- if (!list_is_singular(&allocated)) {
- block = list_last_entry(&allocated, typeof(*block), link);
- list_move(&block->link, &temp);
- trim_list = &temp;
- trim_size = drm_buddy_block_size(mm, block) -
- (size - original_size);
- }
-
- drm_buddy_block_trim(mm,
- NULL,
- trim_size,
- trim_list);
-
- if (!list_empty(&temp))
- list_splice_tail(trim_list, &allocated);
- }
-
- list_splice_tail(&allocated, blocks);
- return 0;
-
-err_free:
- drm_buddy_free_list_internal(mm, &allocated);
- return err;
-}
-EXPORT_SYMBOL(drm_buddy_alloc_blocks);
+#include <drm/drm_print.h>
/**
* drm_buddy_block_print - print block information
@@ -1257,12 +21,12 @@ EXPORT_SYMBOL(drm_buddy_alloc_blocks);
* @block: DRM buddy block
* @p: DRM printer to use
*/
-void drm_buddy_block_print(struct drm_buddy *mm,
- struct drm_buddy_block *block,
+void drm_buddy_block_print(struct gpu_buddy *mm,
+ struct gpu_buddy_block *block,
struct drm_printer *p)
{
- u64 start = drm_buddy_block_offset(block);
- u64 size = drm_buddy_block_size(mm, block);
+ u64 start = gpu_buddy_block_offset(block);
+ u64 size = gpu_buddy_block_size(mm, block);
drm_printf(p, "%#018llx-%#018llx: %llu\n", start, start + size, size);
}
@@ -1274,7 +38,7 @@ EXPORT_SYMBOL(drm_buddy_block_print);
* @mm: DRM buddy manager
* @p: DRM printer to use
*/
-void drm_buddy_print(struct drm_buddy *mm, struct drm_printer *p)
+void drm_buddy_print(struct gpu_buddy *mm, struct drm_printer *p)
{
int order;
@@ -1282,7 +46,7 @@ void drm_buddy_print(struct drm_buddy *m
mm->chunk_size >> 10, mm->size >> 20, mm->avail >> 20, mm->clear_avail >> 20);
for (order = mm->max_order; order >= 0; order--) {
- struct drm_buddy_block *block, *tmp;
+ struct gpu_buddy_block *block, *tmp;
struct rb_root *root;
u64 count = 0, free;
unsigned int tree;
@@ -1291,7 +55,7 @@ void drm_buddy_print(struct drm_buddy *m
root = &mm->free_trees[tree][order];
rbtree_postorder_for_each_entry_safe(block, tmp, root, rb) {
- BUG_ON(!drm_buddy_block_is_free(block));
+ BUG_ON(!gpu_buddy_block_is_free(block));
count++;
}
}
@@ -1309,22 +73,5 @@ void drm_buddy_print(struct drm_buddy *m
}
EXPORT_SYMBOL(drm_buddy_print);
-static void drm_buddy_module_exit(void)
-{
- kmem_cache_destroy(slab_blocks);
-}
-
-static int __init drm_buddy_module_init(void)
-{
- slab_blocks = KMEM_CACHE(drm_buddy_block, 0);
- if (!slab_blocks)
- return -ENOMEM;
-
- return 0;
-}
-
-module_init(drm_buddy_module_init);
-module_exit(drm_buddy_module_exit);
-
-MODULE_DESCRIPTION("DRM Buddy Allocator");
+MODULE_DESCRIPTION("DRM-specific GPU Buddy Allocator Print Helpers");
MODULE_LICENSE("Dual MIT/GPL");
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -7,7 +7,7 @@
#include <drm/ttm/ttm_placement.h>
#include <drm/ttm/ttm_tt.h>
-#include <drm/drm_buddy.h>
+#include <linux/gpu_buddy.h>
#include "i915_drv.h"
#include "i915_ttm_buddy_manager.h"
--- a/drivers/gpu/drm/i915/i915_scatterlist.c
+++ b/drivers/gpu/drm/i915/i915_scatterlist.c
@@ -7,7 +7,7 @@
#include "i915_scatterlist.h"
#include "i915_ttm_buddy_manager.h"
-#include <drm/drm_buddy.h>
+#include <linux/gpu_buddy.h>
#include <drm/drm_mm.h>
#include <linux/slab.h>
@@ -167,9 +167,9 @@ struct i915_refct_sgt *i915_rsgt_from_bu
struct i915_ttm_buddy_resource *bman_res = to_ttm_buddy_resource(res);
const u64 size = res->size;
const u32 max_segment = round_down(UINT_MAX, page_alignment);
- struct drm_buddy *mm = bman_res->mm;
+ struct gpu_buddy *mm = bman_res->mm;
struct list_head *blocks = &bman_res->blocks;
- struct drm_buddy_block *block;
+ struct gpu_buddy_block *block;
struct i915_refct_sgt *rsgt;
struct scatterlist *sg;
struct sg_table *st;
@@ -202,8 +202,8 @@ struct i915_refct_sgt *i915_rsgt_from_bu
list_for_each_entry(block, blocks, link) {
u64 block_size, offset;
- block_size = min_t(u64, size, drm_buddy_block_size(mm, block));
- offset = drm_buddy_block_offset(block);
+ block_size = min_t(u64, size, gpu_buddy_block_size(mm, block));
+ offset = gpu_buddy_block_offset(block);
while (block_size) {
u64 len;
--- a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
+++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
@@ -8,6 +8,7 @@
#include <drm/ttm/ttm_placement.h>
#include <drm/ttm/ttm_bo.h>
+#include <linux/gpu_buddy.h>
#include <drm/drm_buddy.h>
#include "i915_ttm_buddy_manager.h"
@@ -16,7 +17,7 @@
struct i915_ttm_buddy_manager {
struct ttm_resource_manager manager;
- struct drm_buddy mm;
+ struct gpu_buddy mm;
struct list_head reserved;
struct mutex lock;
unsigned long visible_size;
@@ -38,7 +39,7 @@ static int i915_ttm_buddy_man_alloc(stru
{
struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
struct i915_ttm_buddy_resource *bman_res;
- struct drm_buddy *mm = &bman->mm;
+ struct gpu_buddy *mm = &bman->mm;
unsigned long n_pages, lpfn;
u64 min_page_size;
u64 size;
@@ -57,13 +58,13 @@ static int i915_ttm_buddy_man_alloc(stru
bman_res->mm = mm;
if (place->flags & TTM_PL_FLAG_TOPDOWN)
- bman_res->flags |= DRM_BUDDY_TOPDOWN_ALLOCATION;
+ bman_res->flags |= GPU_BUDDY_TOPDOWN_ALLOCATION;
if (place->flags & TTM_PL_FLAG_CONTIGUOUS)
- bman_res->flags |= DRM_BUDDY_CONTIGUOUS_ALLOCATION;
+ bman_res->flags |= GPU_BUDDY_CONTIGUOUS_ALLOCATION;
if (place->fpfn || lpfn != man->size)
- bman_res->flags |= DRM_BUDDY_RANGE_ALLOCATION;
+ bman_res->flags |= GPU_BUDDY_RANGE_ALLOCATION;
GEM_BUG_ON(!bman_res->base.size);
size = bman_res->base.size;
@@ -89,7 +90,7 @@ static int i915_ttm_buddy_man_alloc(stru
goto err_free_res;
}
- err = drm_buddy_alloc_blocks(mm, (u64)place->fpfn << PAGE_SHIFT,
+ err = gpu_buddy_alloc_blocks(mm, (u64)place->fpfn << PAGE_SHIFT,
(u64)lpfn << PAGE_SHIFT,
(u64)n_pages << PAGE_SHIFT,
min_page_size,
@@ -101,15 +102,15 @@ static int i915_ttm_buddy_man_alloc(stru
if (lpfn <= bman->visible_size) {
bman_res->used_visible_size = PFN_UP(bman_res->base.size);
} else {
- struct drm_buddy_block *block;
+ struct gpu_buddy_block *block;
list_for_each_entry(block, &bman_res->blocks, link) {
unsigned long start =
- drm_buddy_block_offset(block) >> PAGE_SHIFT;
+ gpu_buddy_block_offset(block) >> PAGE_SHIFT;
if (start < bman->visible_size) {
unsigned long end = start +
- (drm_buddy_block_size(mm, block) >> PAGE_SHIFT);
+ (gpu_buddy_block_size(mm, block) >> PAGE_SHIFT);
bman_res->used_visible_size +=
min(end, bman->visible_size) - start;
@@ -126,7 +127,7 @@ static int i915_ttm_buddy_man_alloc(stru
return 0;
err_free_blocks:
- drm_buddy_free_list(mm, &bman_res->blocks, 0);
+ gpu_buddy_free_list(mm, &bman_res->blocks, 0);
mutex_unlock(&bman->lock);
err_free_res:
ttm_resource_fini(man, &bman_res->base);
@@ -141,7 +142,7 @@ static void i915_ttm_buddy_man_free(stru
struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
mutex_lock(&bman->lock);
- drm_buddy_free_list(&bman->mm, &bman_res->blocks, 0);
+ gpu_buddy_free_list(&bman->mm, &bman_res->blocks, 0);
bman->visible_avail += bman_res->used_visible_size;
mutex_unlock(&bman->lock);
@@ -156,8 +157,8 @@ static bool i915_ttm_buddy_man_intersect
{
struct i915_ttm_buddy_resource *bman_res = to_ttm_buddy_resource(res);
struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
- struct drm_buddy *mm = &bman->mm;
- struct drm_buddy_block *block;
+ struct gpu_buddy *mm = &bman->mm;
+ struct gpu_buddy_block *block;
if (!place->fpfn && !place->lpfn)
return true;
@@ -176,9 +177,9 @@ static bool i915_ttm_buddy_man_intersect
/* Check each drm buddy block individually */
list_for_each_entry(block, &bman_res->blocks, link) {
unsigned long fpfn =
- drm_buddy_block_offset(block) >> PAGE_SHIFT;
+ gpu_buddy_block_offset(block) >> PAGE_SHIFT;
unsigned long lpfn = fpfn +
- (drm_buddy_block_size(mm, block) >> PAGE_SHIFT);
+ (gpu_buddy_block_size(mm, block) >> PAGE_SHIFT);
if (place->fpfn < lpfn && place->lpfn > fpfn)
return true;
@@ -194,8 +195,8 @@ static bool i915_ttm_buddy_man_compatibl
{
struct i915_ttm_buddy_resource *bman_res = to_ttm_buddy_resource(res);
struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
- struct drm_buddy *mm = &bman->mm;
- struct drm_buddy_block *block;
+ struct gpu_buddy *mm = &bman->mm;
+ struct gpu_buddy_block *block;
if (!place->fpfn && !place->lpfn)
return true;
@@ -209,9 +210,9 @@ static bool i915_ttm_buddy_man_compatibl
/* Check each drm buddy block individually */
list_for_each_entry(block, &bman_res->blocks, link) {
unsigned long fpfn =
- drm_buddy_block_offset(block) >> PAGE_SHIFT;
+ gpu_buddy_block_offset(block) >> PAGE_SHIFT;
unsigned long lpfn = fpfn +
- (drm_buddy_block_size(mm, block) >> PAGE_SHIFT);
+ (gpu_buddy_block_size(mm, block) >> PAGE_SHIFT);
if (fpfn < place->fpfn || lpfn > place->lpfn)
return false;
@@ -224,7 +225,7 @@ static void i915_ttm_buddy_man_debug(str
struct drm_printer *printer)
{
struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
- struct drm_buddy_block *block;
+ struct gpu_buddy_block *block;
mutex_lock(&bman->lock);
drm_printf(printer, "default_page_size: %lluKiB\n",
@@ -293,7 +294,7 @@ int i915_ttm_buddy_man_init(struct ttm_d
if (!bman)
return -ENOMEM;
- err = drm_buddy_init(&bman->mm, size, chunk_size);
+ err = gpu_buddy_init(&bman->mm, size, chunk_size);
if (err)
goto err_free_bman;
@@ -333,7 +334,7 @@ int i915_ttm_buddy_man_fini(struct ttm_d
{
struct ttm_resource_manager *man = ttm_manager_type(bdev, type);
struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
- struct drm_buddy *mm = &bman->mm;
+ struct gpu_buddy *mm = &bman->mm;
int ret;
ttm_resource_manager_set_used(man, false);
@@ -345,8 +346,8 @@ int i915_ttm_buddy_man_fini(struct ttm_d
ttm_set_driver_manager(bdev, type, NULL);
mutex_lock(&bman->lock);
- drm_buddy_free_list(mm, &bman->reserved, 0);
- drm_buddy_fini(mm);
+ gpu_buddy_free_list(mm, &bman->reserved, 0);
+ gpu_buddy_fini(mm);
bman->visible_avail += bman->visible_reserved;
WARN_ON_ONCE(bman->visible_avail != bman->visible_size);
mutex_unlock(&bman->lock);
@@ -371,15 +372,15 @@ int i915_ttm_buddy_man_reserve(struct tt
u64 start, u64 size)
{
struct i915_ttm_buddy_manager *bman = to_buddy_manager(man);
- struct drm_buddy *mm = &bman->mm;
+ struct gpu_buddy *mm = &bman->mm;
unsigned long fpfn = start >> PAGE_SHIFT;
unsigned long flags = 0;
int ret;
- flags |= DRM_BUDDY_RANGE_ALLOCATION;
+ flags |= GPU_BUDDY_RANGE_ALLOCATION;
mutex_lock(&bman->lock);
- ret = drm_buddy_alloc_blocks(mm, start,
+ ret = gpu_buddy_alloc_blocks(mm, start,
start + size,
size, mm->chunk_size,
&bman->reserved,
--- a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.h
+++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.h
@@ -13,7 +13,7 @@
struct ttm_device;
struct ttm_resource_manager;
-struct drm_buddy;
+struct gpu_buddy;
/**
* struct i915_ttm_buddy_resource
@@ -33,7 +33,7 @@ struct i915_ttm_buddy_resource {
struct list_head blocks;
unsigned long flags;
unsigned long used_visible_size;
- struct drm_buddy *mm;
+ struct gpu_buddy *mm;
};
/**
--- a/drivers/gpu/drm/i915/selftests/intel_memory_region.c
+++ b/drivers/gpu/drm/i915/selftests/intel_memory_region.c
@@ -6,7 +6,7 @@
#include <linux/prime_numbers.h>
#include <linux/sort.h>
-#include <drm/drm_buddy.h>
+#include <linux/gpu_buddy.h>
#include "../i915_selftest.h"
@@ -371,7 +371,7 @@ static int igt_mock_splintered_region(vo
struct drm_i915_private *i915 = mem->i915;
struct i915_ttm_buddy_resource *res;
struct drm_i915_gem_object *obj;
- struct drm_buddy *mm;
+ struct gpu_buddy *mm;
unsigned int expected_order;
LIST_HEAD(objects);
u64 size;
@@ -455,8 +455,8 @@ static int igt_mock_max_segment(void *ar
struct drm_i915_private *i915 = mem->i915;
struct i915_ttm_buddy_resource *res;
struct drm_i915_gem_object *obj;
- struct drm_buddy_block *block;
- struct drm_buddy *mm;
+ struct gpu_buddy_block *block;
+ struct gpu_buddy *mm;
struct list_head *blocks;
struct scatterlist *sg;
I915_RND_STATE(prng);
@@ -495,8 +495,8 @@ static int igt_mock_max_segment(void *ar
mm = res->mm;
size = 0;
list_for_each_entry(block, blocks, link) {
- if (drm_buddy_block_size(mm, block) > size)
- size = drm_buddy_block_size(mm, block);
+ if (gpu_buddy_block_size(mm, block) > size)
+ size = gpu_buddy_block_size(mm, block);
}
if (size < max_segment) {
pr_err("%s: Failed to create a huge contiguous block [> %u], largest block %lld\n",
@@ -535,14 +535,14 @@ static u64 igt_object_mappable_total(str
struct intel_memory_region *mr = obj->mm.region;
struct i915_ttm_buddy_resource *bman_res =
to_ttm_buddy_resource(obj->mm.res);
- struct drm_buddy *mm = bman_res->mm;
- struct drm_buddy_block *block;
+ struct gpu_buddy *mm = bman_res->mm;
+ struct gpu_buddy_block *block;
u64 total;
total = 0;
list_for_each_entry(block, &bman_res->blocks, link) {
- u64 start = drm_buddy_block_offset(block);
- u64 end = start + drm_buddy_block_size(mm, block);
+ u64 start = gpu_buddy_block_offset(block);
+ u64 end = start + gpu_buddy_block_size(mm, block);
if (start < resource_size(&mr->io))
total += min_t(u64, end, resource_size(&mr->io)) - start;
--- a/drivers/gpu/drm/lib/drm_random.c
+++ /dev/null
@@ -1,43 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/bitops.h>
-#include <linux/kernel.h>
-#include <linux/random.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-
-#include "drm_random.h"
-
-u32 drm_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state)
-{
- return upper_32_bits((u64)prandom_u32_state(state) * ep_ro);
-}
-EXPORT_SYMBOL(drm_prandom_u32_max_state);
-
-void drm_random_reorder(unsigned int *order, unsigned int count,
- struct rnd_state *state)
-{
- unsigned int i, j;
-
- for (i = 0; i < count; ++i) {
- BUILD_BUG_ON(sizeof(unsigned int) > sizeof(u32));
- j = drm_prandom_u32_max_state(count, state);
- swap(order[i], order[j]);
- }
-}
-EXPORT_SYMBOL(drm_random_reorder);
-
-unsigned int *drm_random_order(unsigned int count, struct rnd_state *state)
-{
- unsigned int *order, i;
-
- order = kmalloc_array(count, sizeof(*order), GFP_KERNEL);
- if (!order)
- return order;
-
- for (i = 0; i < count; i++)
- order[i] = i;
-
- drm_random_reorder(order, count, state);
- return order;
-}
-EXPORT_SYMBOL(drm_random_order);
--- a/drivers/gpu/drm/lib/drm_random.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __DRM_RANDOM_H__
-#define __DRM_RANDOM_H__
-
-/* This is a temporary home for a couple of utility functions that should
- * be transposed to lib/ at the earliest convenience.
- */
-
-#include <linux/random.h>
-
-#define DRM_RND_STATE_INITIALIZER(seed__) ({ \
- struct rnd_state state__; \
- prandom_seed_state(&state__, (seed__)); \
- state__; \
-})
-
-#define DRM_RND_STATE(name__, seed__) \
- struct rnd_state name__ = DRM_RND_STATE_INITIALIZER(seed__)
-
-unsigned int *drm_random_order(unsigned int count,
- struct rnd_state *state);
-void drm_random_reorder(unsigned int *order,
- unsigned int count,
- struct rnd_state *state);
-u32 drm_prandom_u32_max_state(u32 ep_ro,
- struct rnd_state *state);
-
-#endif /* !__DRM_RANDOM_H__ */
--- a/drivers/gpu/drm/tests/Makefile
+++ b/drivers/gpu/drm/tests/Makefile
@@ -4,7 +4,6 @@ obj-$(CONFIG_DRM_KUNIT_TEST_HELPERS) +=
drm_kunit_helpers.o
obj-$(CONFIG_DRM_KUNIT_TEST) += \
- drm_buddy_test.o \
drm_cmdline_parser_test.o \
drm_connector_test.o \
drm_damage_helper_test.o \
--- a/drivers/gpu/drm/tests/drm_buddy_test.c
+++ /dev/null
@@ -1,778 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Copyright © 2019 Intel Corporation
- * Copyright © 2022 Maíra Canal <mairacanal@riseup.net>
- */
-
-#include <kunit/test.h>
-
-#include <linux/prime_numbers.h>
-#include <linux/sched/signal.h>
-#include <linux/sizes.h>
-
-#include <drm/drm_buddy.h>
-
-#include "../lib/drm_random.h"
-
-static unsigned int random_seed;
-
-static inline u64 get_size(int order, u64 chunk_size)
-{
- return (1 << order) * chunk_size;
-}
-
-static void drm_test_buddy_alloc_range_bias(struct kunit *test)
-{
- u32 mm_size, size, ps, bias_size, bias_start, bias_end, bias_rem;
- DRM_RND_STATE(prng, random_seed);
- unsigned int i, count, *order;
- struct drm_buddy_block *block;
- unsigned long flags;
- struct drm_buddy mm;
- LIST_HEAD(allocated);
-
- bias_size = SZ_1M;
- ps = roundup_pow_of_two(prandom_u32_state(&prng) % bias_size);
- ps = max(SZ_4K, ps);
- mm_size = (SZ_8M-1) & ~(ps-1); /* Multiple roots */
-
- kunit_info(test, "mm_size=%u, ps=%u\n", mm_size, ps);
-
- KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, ps),
- "buddy_init failed\n");
-
- count = mm_size / bias_size;
- order = drm_random_order(count, &prng);
- KUNIT_EXPECT_TRUE(test, order);
-
- /*
- * Idea is to split the address space into uniform bias ranges, and then
- * in some random order allocate within each bias, using various
- * patterns within. This should detect if allocations leak out from a
- * given bias, for example.
- */
-
- for (i = 0; i < count; i++) {
- LIST_HEAD(tmp);
- u32 size;
-
- bias_start = order[i] * bias_size;
- bias_end = bias_start + bias_size;
- bias_rem = bias_size;
-
- /* internal round_up too big */
- KUNIT_ASSERT_TRUE_MSG(test,
- drm_buddy_alloc_blocks(&mm, bias_start,
- bias_end, bias_size + ps, bias_size,
- &allocated,
- DRM_BUDDY_RANGE_ALLOCATION),
- "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
- bias_start, bias_end, bias_size, bias_size);
-
- /* size too big */
- KUNIT_ASSERT_TRUE_MSG(test,
- drm_buddy_alloc_blocks(&mm, bias_start,
- bias_end, bias_size + ps, ps,
- &allocated,
- DRM_BUDDY_RANGE_ALLOCATION),
- "buddy_alloc didn't fail with bias(%x-%x), size=%u, ps=%u\n",
- bias_start, bias_end, bias_size + ps, ps);
-
- /* bias range too small for size */
- KUNIT_ASSERT_TRUE_MSG(test,
- drm_buddy_alloc_blocks(&mm, bias_start + ps,
- bias_end, bias_size, ps,
- &allocated,
- DRM_BUDDY_RANGE_ALLOCATION),
- "buddy_alloc didn't fail with bias(%x-%x), size=%u, ps=%u\n",
- bias_start + ps, bias_end, bias_size, ps);
-
- /* bias misaligned */
- KUNIT_ASSERT_TRUE_MSG(test,
- drm_buddy_alloc_blocks(&mm, bias_start + ps,
- bias_end - ps,
- bias_size >> 1, bias_size >> 1,
- &allocated,
- DRM_BUDDY_RANGE_ALLOCATION),
- "buddy_alloc h didn't fail with bias(%x-%x), size=%u, ps=%u\n",
- bias_start + ps, bias_end - ps, bias_size >> 1, bias_size >> 1);
-
- /* single big page */
- KUNIT_ASSERT_FALSE_MSG(test,
- drm_buddy_alloc_blocks(&mm, bias_start,
- bias_end, bias_size, bias_size,
- &tmp,
- DRM_BUDDY_RANGE_ALLOCATION),
- "buddy_alloc i failed with bias(%x-%x), size=%u, ps=%u\n",
- bias_start, bias_end, bias_size, bias_size);
- drm_buddy_free_list(&mm, &tmp, 0);
-
- /* single page with internal round_up */
- KUNIT_ASSERT_FALSE_MSG(test,
- drm_buddy_alloc_blocks(&mm, bias_start,
- bias_end, ps, bias_size,
- &tmp,
- DRM_BUDDY_RANGE_ALLOCATION),
- "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
- bias_start, bias_end, ps, bias_size);
- drm_buddy_free_list(&mm, &tmp, 0);
-
- /* random size within */
- size = max(round_up(prandom_u32_state(&prng) % bias_rem, ps), ps);
- if (size)
- KUNIT_ASSERT_FALSE_MSG(test,
- drm_buddy_alloc_blocks(&mm, bias_start,
- bias_end, size, ps,
- &tmp,
- DRM_BUDDY_RANGE_ALLOCATION),
- "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
- bias_start, bias_end, size, ps);
-
- bias_rem -= size;
- /* too big for current avail */
- KUNIT_ASSERT_TRUE_MSG(test,
- drm_buddy_alloc_blocks(&mm, bias_start,
- bias_end, bias_rem + ps, ps,
- &allocated,
- DRM_BUDDY_RANGE_ALLOCATION),
- "buddy_alloc didn't fail with bias(%x-%x), size=%u, ps=%u\n",
- bias_start, bias_end, bias_rem + ps, ps);
-
- if (bias_rem) {
- /* random fill of the remainder */
- size = max(round_up(prandom_u32_state(&prng) % bias_rem, ps), ps);
- size = max(size, ps);
-
- KUNIT_ASSERT_FALSE_MSG(test,
- drm_buddy_alloc_blocks(&mm, bias_start,
- bias_end, size, ps,
- &allocated,
- DRM_BUDDY_RANGE_ALLOCATION),
- "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
- bias_start, bias_end, size, ps);
- /*
- * Intentionally allow some space to be left
- * unallocated, and ideally not always on the bias
- * boundaries.
- */
- drm_buddy_free_list(&mm, &tmp, 0);
- } else {
- list_splice_tail(&tmp, &allocated);
- }
- }
-
- kfree(order);
- drm_buddy_free_list(&mm, &allocated, 0);
- drm_buddy_fini(&mm);
-
- /*
- * Something more free-form. Idea is to pick a random starting bias
- * range within the address space and then start filling it up. Also
- * randomly grow the bias range in both directions as we go along. This
- * should give us bias start/end which is not always uniform like above,
- * and in some cases will require the allocator to jump over already
- * allocated nodes in the middle of the address space.
- */
-
- KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, ps),
- "buddy_init failed\n");
-
- bias_start = round_up(prandom_u32_state(&prng) % (mm_size - ps), ps);
- bias_end = round_up(bias_start + prandom_u32_state(&prng) % (mm_size - bias_start), ps);
- bias_end = max(bias_end, bias_start + ps);
- bias_rem = bias_end - bias_start;
-
- do {
- u32 size = max(round_up(prandom_u32_state(&prng) % bias_rem, ps), ps);
-
- KUNIT_ASSERT_FALSE_MSG(test,
- drm_buddy_alloc_blocks(&mm, bias_start,
- bias_end, size, ps,
- &allocated,
- DRM_BUDDY_RANGE_ALLOCATION),
- "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
- bias_start, bias_end, size, ps);
- bias_rem -= size;
-
- /*
- * Try to randomly grow the bias range in both directions, or
- * only one, or perhaps don't grow at all.
- */
- do {
- u32 old_bias_start = bias_start;
- u32 old_bias_end = bias_end;
-
- if (bias_start)
- bias_start -= round_up(prandom_u32_state(&prng) % bias_start, ps);
- if (bias_end != mm_size)
- bias_end += round_up(prandom_u32_state(&prng) % (mm_size - bias_end), ps);
-
- bias_rem += old_bias_start - bias_start;
- bias_rem += bias_end - old_bias_end;
- } while (!bias_rem && (bias_start || bias_end != mm_size));
- } while (bias_rem);
-
- KUNIT_ASSERT_EQ(test, bias_start, 0);
- KUNIT_ASSERT_EQ(test, bias_end, mm_size);
- KUNIT_ASSERT_TRUE_MSG(test,
- drm_buddy_alloc_blocks(&mm, bias_start, bias_end,
- ps, ps,
- &allocated,
- DRM_BUDDY_RANGE_ALLOCATION),
- "buddy_alloc passed with bias(%x-%x), size=%u\n",
- bias_start, bias_end, ps);
-
- drm_buddy_free_list(&mm, &allocated, 0);
- drm_buddy_fini(&mm);
-
- /*
- * Allocate cleared blocks in the bias range when the DRM buddy's clear avail is
- * zero. This will validate the bias range allocation in scenarios like system boot
- * when no cleared blocks are available and exercise the fallback path too. The resulting
- * blocks should always be dirty.
- */
-
- KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, ps),
- "buddy_init failed\n");
-
- bias_start = round_up(prandom_u32_state(&prng) % (mm_size - ps), ps);
- bias_end = round_up(bias_start + prandom_u32_state(&prng) % (mm_size - bias_start), ps);
- bias_end = max(bias_end, bias_start + ps);
- bias_rem = bias_end - bias_start;
-
- flags = DRM_BUDDY_CLEAR_ALLOCATION | DRM_BUDDY_RANGE_ALLOCATION;
- size = max(round_up(prandom_u32_state(&prng) % bias_rem, ps), ps);
-
- KUNIT_ASSERT_FALSE_MSG(test,
- drm_buddy_alloc_blocks(&mm, bias_start,
- bias_end, size, ps,
- &allocated,
- flags),
- "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
- bias_start, bias_end, size, ps);
-
- list_for_each_entry(block, &allocated, link)
- KUNIT_EXPECT_EQ(test, drm_buddy_block_is_clear(block), false);
-
- drm_buddy_free_list(&mm, &allocated, 0);
- drm_buddy_fini(&mm);
-}
-
-static void drm_test_buddy_alloc_clear(struct kunit *test)
-{
- unsigned long n_pages, total, i = 0;
- DRM_RND_STATE(prng, random_seed);
- const unsigned long ps = SZ_4K;
- struct drm_buddy_block *block;
- const int max_order = 12;
- LIST_HEAD(allocated);
- struct drm_buddy mm;
- unsigned int order;
- u32 mm_size, size;
- LIST_HEAD(dirty);
- LIST_HEAD(clean);
-
- mm_size = SZ_4K << max_order;
- KUNIT_EXPECT_FALSE(test, drm_buddy_init(&mm, mm_size, ps));
-
- KUNIT_EXPECT_EQ(test, mm.max_order, max_order);
-
- /*
- * Idea is to allocate and free some random portion of the address space,
- * returning those pages as non-dirty and randomly alternate between
- * requesting dirty and non-dirty pages (not going over the limit
- * we freed as non-dirty), putting that into two separate lists.
- * Loop over both lists at the end checking that the dirty list
- * is indeed all dirty pages and vice versa. Free it all again,
- * keeping the dirty/clear status.
- */
- KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
- 5 * ps, ps, &allocated,
- DRM_BUDDY_TOPDOWN_ALLOCATION),
- "buddy_alloc hit an error size=%lu\n", 5 * ps);
- drm_buddy_free_list(&mm, &allocated, DRM_BUDDY_CLEARED);
-
- n_pages = 10;
- do {
- unsigned long flags;
- struct list_head *list;
- int slot = i % 2;
-
- if (slot == 0) {
- list = &dirty;
- flags = 0;
- } else {
- list = &clean;
- flags = DRM_BUDDY_CLEAR_ALLOCATION;
- }
-
- KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
- ps, ps, list,
- flags),
- "buddy_alloc hit an error size=%lu\n", ps);
- } while (++i < n_pages);
-
- list_for_each_entry(block, &clean, link)
- KUNIT_EXPECT_EQ(test, drm_buddy_block_is_clear(block), true);
-
- list_for_each_entry(block, &dirty, link)
- KUNIT_EXPECT_EQ(test, drm_buddy_block_is_clear(block), false);
-
- drm_buddy_free_list(&mm, &clean, DRM_BUDDY_CLEARED);
-
- /*
- * Trying to go over the clear limit for some allocation.
- * The allocation should never fail with reasonable page-size.
- */
- KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
- 10 * ps, ps, &clean,
- DRM_BUDDY_CLEAR_ALLOCATION),
- "buddy_alloc hit an error size=%lu\n", 10 * ps);
-
- drm_buddy_free_list(&mm, &clean, DRM_BUDDY_CLEARED);
- drm_buddy_free_list(&mm, &dirty, 0);
- drm_buddy_fini(&mm);
-
- KUNIT_EXPECT_FALSE(test, drm_buddy_init(&mm, mm_size, ps));
-
- /*
- * Create a new mm. Intentionally fragment the address space by creating
- * two alternating lists. Free both lists, one as dirty the other as clean.
- * Try to allocate double the previous size with matching min_page_size. The
- * allocation should never fail as it calls the force_merge. Also check that
- * the page is always dirty after force_merge. Free the page as dirty, then
- * repeat the whole thing, increment the order until we hit the max_order.
- */
-
- i = 0;
- n_pages = mm_size / ps;
- do {
- struct list_head *list;
- int slot = i % 2;
-
- if (slot == 0)
- list = &dirty;
- else
- list = &clean;
-
- KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
- ps, ps, list, 0),
- "buddy_alloc hit an error size=%lu\n", ps);
- } while (++i < n_pages);
-
- drm_buddy_free_list(&mm, &clean, DRM_BUDDY_CLEARED);
- drm_buddy_free_list(&mm, &dirty, 0);
-
- order = 1;
- do {
- size = SZ_4K << order;
-
- KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
- size, size, &allocated,
- DRM_BUDDY_CLEAR_ALLOCATION),
- "buddy_alloc hit an error size=%u\n", size);
- total = 0;
- list_for_each_entry(block, &allocated, link) {
- if (size != mm_size)
- KUNIT_EXPECT_EQ(test, drm_buddy_block_is_clear(block), false);
- total += drm_buddy_block_size(&mm, block);
- }
- KUNIT_EXPECT_EQ(test, total, size);
-
- drm_buddy_free_list(&mm, &allocated, 0);
- } while (++order <= max_order);
-
- drm_buddy_fini(&mm);
-
- /*
- * Create a new mm with a non power-of-two size. Allocate a random size, free as
- * cleared and then call fini. This will ensure the multi-root force merge during
- * fini.
- */
- mm_size = 12 * SZ_4K;
- size = max(round_up(prandom_u32_state(&prng) % mm_size, ps), ps);
- KUNIT_EXPECT_FALSE(test, drm_buddy_init(&mm, mm_size, ps));
- KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
- size, ps, &allocated,
- DRM_BUDDY_TOPDOWN_ALLOCATION),
- "buddy_alloc hit an error size=%u\n", size);
- drm_buddy_free_list(&mm, &allocated, DRM_BUDDY_CLEARED);
- drm_buddy_fini(&mm);
-}
-
-static void drm_test_buddy_alloc_contiguous(struct kunit *test)
-{
- const unsigned long ps = SZ_4K, mm_size = 16 * 3 * SZ_4K;
- unsigned long i, n_pages, total;
- struct drm_buddy_block *block;
- struct drm_buddy mm;
- LIST_HEAD(left);
- LIST_HEAD(middle);
- LIST_HEAD(right);
- LIST_HEAD(allocated);
-
- KUNIT_EXPECT_FALSE(test, drm_buddy_init(&mm, mm_size, ps));
-
- /*
- * Idea is to fragment the address space by alternating block
- * allocations between three different lists; one for left, middle and
- * right. We can then free a list to simulate fragmentation. In
- * particular we want to exercise the DRM_BUDDY_CONTIGUOUS_ALLOCATION,
- * including the try_harder path.
- */
-
- i = 0;
- n_pages = mm_size / ps;
- do {
- struct list_head *list;
- int slot = i % 3;
-
- if (slot == 0)
- list = &left;
- else if (slot == 1)
- list = &middle;
- else
- list = &right;
- KUNIT_ASSERT_FALSE_MSG(test,
- drm_buddy_alloc_blocks(&mm, 0, mm_size,
- ps, ps, list, 0),
- "buddy_alloc hit an error size=%lu\n",
- ps);
- } while (++i < n_pages);
-
- KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
- 3 * ps, ps, &allocated,
- DRM_BUDDY_CONTIGUOUS_ALLOCATION),
- "buddy_alloc didn't error size=%lu\n", 3 * ps);
-
- drm_buddy_free_list(&mm, &middle, 0);
- KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
- 3 * ps, ps, &allocated,
- DRM_BUDDY_CONTIGUOUS_ALLOCATION),
- "buddy_alloc didn't error size=%lu\n", 3 * ps);
- KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
- 2 * ps, ps, &allocated,
- DRM_BUDDY_CONTIGUOUS_ALLOCATION),
- "buddy_alloc didn't error size=%lu\n", 2 * ps);
-
- drm_buddy_free_list(&mm, &right, 0);
- KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
- 3 * ps, ps, &allocated,
- DRM_BUDDY_CONTIGUOUS_ALLOCATION),
- "buddy_alloc didn't error size=%lu\n", 3 * ps);
- /*
- * At this point we should have enough contiguous space for 2 blocks,
- * however they are never buddies (since we freed middle and right) so
- * will require the try_harder logic to find them.
- */
- KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
- 2 * ps, ps, &allocated,
- DRM_BUDDY_CONTIGUOUS_ALLOCATION),
- "buddy_alloc hit an error size=%lu\n", 2 * ps);
-
- drm_buddy_free_list(&mm, &left, 0);
- KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, 0, mm_size,
- 3 * ps, ps, &allocated,
- DRM_BUDDY_CONTIGUOUS_ALLOCATION),
- "buddy_alloc hit an error size=%lu\n", 3 * ps);
-
- total = 0;
- list_for_each_entry(block, &allocated, link)
- total += drm_buddy_block_size(&mm, block);
-
- KUNIT_ASSERT_EQ(test, total, ps * 2 + ps * 3);
-
- drm_buddy_free_list(&mm, &allocated, 0);
- drm_buddy_fini(&mm);
-}
-
-static void drm_test_buddy_alloc_pathological(struct kunit *test)
-{
- u64 mm_size, size, start = 0;
- struct drm_buddy_block *block;
- const int max_order = 3;
- unsigned long flags = 0;
- int order, top;
- struct drm_buddy mm;
- LIST_HEAD(blocks);
- LIST_HEAD(holes);
- LIST_HEAD(tmp);
-
- /*
- * Create a pot-sized mm, then allocate one of each possible
- * order within. This should leave the mm with exactly one
- * page left. Free the largest block, then whittle down again.
- * Eventually we will have a fully 50% fragmented mm.
- */
-
- mm_size = SZ_4K << max_order;
- KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, SZ_4K),
- "buddy_init failed\n");
-
- KUNIT_EXPECT_EQ(test, mm.max_order, max_order);
-
- for (top = max_order; top; top--) {
- /* Make room by freeing the largest allocated block */
- block = list_first_entry_or_null(&blocks, typeof(*block), link);
- if (block) {
- list_del(&block->link);
- drm_buddy_free_block(&mm, block);
- }
-
- for (order = top; order--;) {
- size = get_size(order, mm.chunk_size);
- KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start,
- mm_size, size, size,
- &tmp, flags),
- "buddy_alloc hit -ENOMEM with order=%d, top=%d\n",
- order, top);
-
- block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link);
- KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
-
- list_move_tail(&block->link, &blocks);
- }
-
- /* There should be one final page for this sub-allocation */
- size = get_size(0, mm.chunk_size);
- KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
- size, size, &tmp, flags),
- "buddy_alloc hit -ENOMEM for hole\n");
-
- block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link);
- KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
-
- list_move_tail(&block->link, &holes);
-
- size = get_size(top, mm.chunk_size);
- KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
- size, size, &tmp, flags),
- "buddy_alloc unexpectedly succeeded at top-order %d/%d, it should be full!",
- top, max_order);
- }
-
- drm_buddy_free_list(&mm, &holes, 0);
-
- /* Nothing larger than blocks of chunk_size now available */
- for (order = 1; order <= max_order; order++) {
- size = get_size(order, mm.chunk_size);
- KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
- size, size, &tmp, flags),
- "buddy_alloc unexpectedly succeeded at order %d, it should be full!",
- order);
- }
-
- list_splice_tail(&holes, &blocks);
- drm_buddy_free_list(&mm, &blocks, 0);
- drm_buddy_fini(&mm);
-}
-
-static void drm_test_buddy_alloc_pessimistic(struct kunit *test)
-{
- u64 mm_size, size, start = 0;
- struct drm_buddy_block *block, *bn;
- const unsigned int max_order = 16;
- unsigned long flags = 0;
- struct drm_buddy mm;
- unsigned int order;
- LIST_HEAD(blocks);
- LIST_HEAD(tmp);
-
- /*
- * Create a pot-sized mm, then allocate one of each possible
- * order within. This should leave the mm with exactly one
- * page left.
- */
-
- mm_size = SZ_4K << max_order;
- KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, SZ_4K),
- "buddy_init failed\n");
-
- KUNIT_EXPECT_EQ(test, mm.max_order, max_order);
-
- for (order = 0; order < max_order; order++) {
- size = get_size(order, mm.chunk_size);
- KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
- size, size, &tmp, flags),
- "buddy_alloc hit -ENOMEM with order=%d\n",
- order);
-
- block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link);
- KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
-
- list_move_tail(&block->link, &blocks);
- }
-
- /* And now the last remaining block available */
- size = get_size(0, mm.chunk_size);
- KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
- size, size, &tmp, flags),
- "buddy_alloc hit -ENOMEM on final alloc\n");
-
- block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link);
- KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
-
- list_move_tail(&block->link, &blocks);
-
- /* Should be completely full! */
- for (order = max_order; order--;) {
- size = get_size(order, mm.chunk_size);
- KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
- size, size, &tmp, flags),
- "buddy_alloc unexpectedly succeeded, it should be full!");
- }
-
- block = list_last_entry(&blocks, typeof(*block), link);
- list_del(&block->link);
- drm_buddy_free_block(&mm, block);
-
- /* As we free in increasing size, we make available larger blocks */
- order = 1;
- list_for_each_entry_safe(block, bn, &blocks, link) {
- list_del(&block->link);
- drm_buddy_free_block(&mm, block);
-
- size = get_size(order, mm.chunk_size);
- KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
- size, size, &tmp, flags),
- "buddy_alloc hit -ENOMEM with order=%d\n",
- order);
-
- block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link);
- KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
-
- list_del(&block->link);
- drm_buddy_free_block(&mm, block);
- order++;
- }
-
- /* To confirm, now the whole mm should be available */
- size = get_size(max_order, mm.chunk_size);
- KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
- size, size, &tmp, flags),
- "buddy_alloc (realloc) hit -ENOMEM with order=%d\n",
- max_order);
-
- block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link);
- KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
-
- list_del(&block->link);
- drm_buddy_free_block(&mm, block);
- drm_buddy_free_list(&mm, &blocks, 0);
- drm_buddy_fini(&mm);
-}
-
-static void drm_test_buddy_alloc_optimistic(struct kunit *test)
-{
- u64 mm_size, size, start = 0;
- struct drm_buddy_block *block;
- unsigned long flags = 0;
- const int max_order = 16;
- struct drm_buddy mm;
- LIST_HEAD(blocks);
- LIST_HEAD(tmp);
- int order;
-
- /*
- * Create a mm with one block of each order available, and
- * try to allocate them all.
- */
-
- mm_size = SZ_4K * ((1 << (max_order + 1)) - 1);
-
- KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_init(&mm, mm_size, SZ_4K),
- "buddy_init failed\n");
-
- KUNIT_EXPECT_EQ(test, mm.max_order, max_order);
-
- for (order = 0; order <= max_order; order++) {
- size = get_size(order, mm.chunk_size);
- KUNIT_ASSERT_FALSE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
- size, size, &tmp, flags),
- "buddy_alloc hit -ENOMEM with order=%d\n",
- order);
-
- block = list_first_entry_or_null(&tmp, struct drm_buddy_block, link);
- KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
-
- list_move_tail(&block->link, &blocks);
- }
-
- /* Should be completely full! */
- size = get_size(0, mm.chunk_size);
- KUNIT_ASSERT_TRUE_MSG(test, drm_buddy_alloc_blocks(&mm, start, mm_size,
- size, size, &tmp, flags),
- "buddy_alloc unexpectedly succeeded, it should be full!");
-
- drm_buddy_free_list(&mm, &blocks, 0);
- drm_buddy_fini(&mm);
-}
-
-static void drm_test_buddy_alloc_limit(struct kunit *test)
-{
- u64 size = U64_MAX, start = 0;
- struct drm_buddy_block *block;
- unsigned long flags = 0;
- LIST_HEAD(allocated);
- struct drm_buddy mm;
-
- KUNIT_EXPECT_FALSE(test, drm_buddy_init(&mm, size, SZ_4K));
-
- KUNIT_EXPECT_EQ_MSG(test, mm.max_order, DRM_BUDDY_MAX_ORDER,
- "mm.max_order(%d) != %d\n", mm.max_order,
- DRM_BUDDY_MAX_ORDER);
-
- size = mm.chunk_size << mm.max_order;
- KUNIT_EXPECT_FALSE(test, drm_buddy_alloc_blocks(&mm, start, size, size,
- mm.chunk_size, &allocated, flags));
-
- block = list_first_entry_or_null(&allocated, struct drm_buddy_block, link);
- KUNIT_EXPECT_TRUE(test, block);
-
- KUNIT_EXPECT_EQ_MSG(test, drm_buddy_block_order(block), mm.max_order,
- "block order(%d) != %d\n",
- drm_buddy_block_order(block), mm.max_order);
-
- KUNIT_EXPECT_EQ_MSG(test, drm_buddy_block_size(&mm, block),
- BIT_ULL(mm.max_order) * mm.chunk_size,
- "block size(%llu) != %llu\n",
- drm_buddy_block_size(&mm, block),
- BIT_ULL(mm.max_order) * mm.chunk_size);
-
- drm_buddy_free_list(&mm, &allocated, 0);
- drm_buddy_fini(&mm);
-}
-
-static int drm_buddy_suite_init(struct kunit_suite *suite)
-{
- while (!random_seed)
- random_seed = get_random_u32();
-
- kunit_info(suite, "Testing DRM buddy manager, with random_seed=0x%x\n",
- random_seed);
-
- return 0;
-}
-
-static struct kunit_case drm_buddy_tests[] = {
- KUNIT_CASE(drm_test_buddy_alloc_limit),
- KUNIT_CASE(drm_test_buddy_alloc_optimistic),
- KUNIT_CASE(drm_test_buddy_alloc_pessimistic),
- KUNIT_CASE(drm_test_buddy_alloc_pathological),
- KUNIT_CASE(drm_test_buddy_alloc_contiguous),
- KUNIT_CASE(drm_test_buddy_alloc_clear),
- KUNIT_CASE(drm_test_buddy_alloc_range_bias),
- {}
-};
-
-static struct kunit_suite drm_buddy_test_suite = {
- .name = "drm_buddy",
- .suite_init = drm_buddy_suite_init,
- .test_cases = drm_buddy_tests,
-};
-
-kunit_test_suite(drm_buddy_test_suite);
-
-MODULE_AUTHOR("Intel Corporation");
-MODULE_DESCRIPTION("Kunit test for drm_buddy functions");
-MODULE_LICENSE("GPL");
--- a/drivers/gpu/drm/tests/drm_exec_test.c
+++ b/drivers/gpu/drm/tests/drm_exec_test.c
@@ -16,8 +16,6 @@
#include <drm/drm_gem.h>
#include <drm/drm_kunit_helpers.h>
-#include "../lib/drm_random.h"
-
struct drm_exec_priv {
struct device *dev;
struct drm_device *drm;
--- a/drivers/gpu/drm/tests/drm_mm_test.c
+++ b/drivers/gpu/drm/tests/drm_mm_test.c
@@ -15,8 +15,6 @@
#include <drm/drm_mm.h>
-#include "../lib/drm_random.h"
-
enum {
BEST,
BOTTOMUP,
--- a/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c
@@ -251,7 +251,7 @@ static void ttm_bo_validate_basic(struct
NULL, &dummy_ttm_bo_destroy);
KUNIT_EXPECT_EQ(test, err, 0);
- snd_place = ttm_place_kunit_init(test, snd_mem, DRM_BUDDY_TOPDOWN_ALLOCATION);
+ snd_place = ttm_place_kunit_init(test, snd_mem, GPU_BUDDY_TOPDOWN_ALLOCATION);
snd_placement = ttm_placement_kunit_init(test, snd_place, 1);
err = ttm_bo_validate(bo, snd_placement, &ctx_val);
@@ -263,7 +263,7 @@ static void ttm_bo_validate_basic(struct
KUNIT_EXPECT_TRUE(test, ttm_tt_is_populated(bo->ttm));
KUNIT_EXPECT_EQ(test, bo->resource->mem_type, snd_mem);
KUNIT_EXPECT_EQ(test, bo->resource->placement,
- DRM_BUDDY_TOPDOWN_ALLOCATION);
+ GPU_BUDDY_TOPDOWN_ALLOCATION);
ttm_bo_put(bo);
ttm_mock_manager_fini(priv->ttm_dev, snd_mem);
--- a/drivers/gpu/drm/ttm/tests/ttm_mock_manager.c
+++ b/drivers/gpu/drm/ttm/tests/ttm_mock_manager.c
@@ -27,7 +27,7 @@ static int ttm_mock_manager_alloc(struct
{
struct ttm_mock_manager *manager = to_mock_mgr(man);
struct ttm_mock_resource *mock_res;
- struct drm_buddy *mm = &manager->mm;
+ struct gpu_buddy *mm = &manager->mm;
u64 lpfn, fpfn, alloc_size;
int err;
@@ -43,14 +43,14 @@ static int ttm_mock_manager_alloc(struct
INIT_LIST_HEAD(&mock_res->blocks);
if (place->flags & TTM_PL_FLAG_TOPDOWN)
- mock_res->flags |= DRM_BUDDY_TOPDOWN_ALLOCATION;
+ mock_res->flags |= GPU_BUDDY_TOPDOWN_ALLOCATION;
if (place->flags & TTM_PL_FLAG_CONTIGUOUS)
- mock_res->flags |= DRM_BUDDY_CONTIGUOUS_ALLOCATION;
+ mock_res->flags |= GPU_BUDDY_CONTIGUOUS_ALLOCATION;
alloc_size = (uint64_t)mock_res->base.size;
mutex_lock(&manager->lock);
- err = drm_buddy_alloc_blocks(mm, fpfn, lpfn, alloc_size,
+ err = gpu_buddy_alloc_blocks(mm, fpfn, lpfn, alloc_size,
manager->default_page_size,
&mock_res->blocks,
mock_res->flags);
@@ -63,7 +63,7 @@ static int ttm_mock_manager_alloc(struct
return 0;
error_free_blocks:
- drm_buddy_free_list(mm, &mock_res->blocks, 0);
+ gpu_buddy_free_list(mm, &mock_res->blocks, 0);
ttm_resource_fini(man, &mock_res->base);
mutex_unlock(&manager->lock);
@@ -75,10 +75,10 @@ static void ttm_mock_manager_free(struct
{
struct ttm_mock_manager *manager = to_mock_mgr(man);
struct ttm_mock_resource *mock_res = to_mock_mgr_resource(res);
- struct drm_buddy *mm = &manager->mm;
+ struct gpu_buddy *mm = &manager->mm;
mutex_lock(&manager->lock);
- drm_buddy_free_list(mm, &mock_res->blocks, 0);
+ gpu_buddy_free_list(mm, &mock_res->blocks, 0);
mutex_unlock(&manager->lock);
ttm_resource_fini(man, res);
@@ -102,7 +102,7 @@ int ttm_mock_manager_init(struct ttm_dev
mutex_init(&manager->lock);
- err = drm_buddy_init(&manager->mm, size, PAGE_SIZE);
+ err = gpu_buddy_init(&manager->mm, size, PAGE_SIZE);
if (err) {
kfree(manager);
@@ -138,7 +138,7 @@ void ttm_mock_manager_fini(struct ttm_de
ttm_resource_manager_set_used(man, false);
mutex_lock(&mock_man->lock);
- drm_buddy_fini(&mock_man->mm);
+ gpu_buddy_fini(&mock_man->mm);
mutex_unlock(&mock_man->lock);
ttm_set_driver_manager(bdev, mem_type, NULL);
--- a/drivers/gpu/drm/ttm/tests/ttm_mock_manager.h
+++ b/drivers/gpu/drm/ttm/tests/ttm_mock_manager.h
@@ -5,11 +5,11 @@
#ifndef TTM_MOCK_MANAGER_H
#define TTM_MOCK_MANAGER_H
-#include <drm/drm_buddy.h>
+#include <linux/gpu_buddy.h>
struct ttm_mock_manager {
struct ttm_resource_manager man;
- struct drm_buddy mm;
+ struct gpu_buddy mm;
u64 default_page_size;
/* protects allocations of mock buffer objects */
struct mutex lock;
--- a/drivers/gpu/drm/xe/xe_res_cursor.h
+++ b/drivers/gpu/drm/xe/xe_res_cursor.h
@@ -44,10 +44,10 @@ struct xe_res_cursor {
void *node;
u32 mem_type;
struct scatterlist *sgl;
- struct drm_buddy *mm;
+ struct gpu_buddy *mm;
};
-static struct drm_buddy *xe_res_get_buddy(struct ttm_resource *res)
+static struct gpu_buddy *xe_res_get_buddy(struct ttm_resource *res)
{
struct ttm_resource_manager *mgr;
@@ -81,30 +81,30 @@ static inline void xe_res_first(struct t
case XE_PL_STOLEN:
case XE_PL_VRAM0:
case XE_PL_VRAM1: {
- struct drm_buddy_block *block;
+ struct gpu_buddy_block *block;
struct list_head *head, *next;
- struct drm_buddy *mm = xe_res_get_buddy(res);
+ struct gpu_buddy *mm = xe_res_get_buddy(res);
head = &to_xe_ttm_vram_mgr_resource(res)->blocks;
block = list_first_entry_or_null(head,
- struct drm_buddy_block,
+ struct gpu_buddy_block,
link);
if (!block)
goto fallback;
- while (start >= drm_buddy_block_size(mm, block)) {
- start -= drm_buddy_block_size(mm, block);
+ while (start >= gpu_buddy_block_size(mm, block)) {
+ start -= gpu_buddy_block_size(mm, block);
next = block->link.next;
if (next != head)
- block = list_entry(next, struct drm_buddy_block,
+ block = list_entry(next, struct gpu_buddy_block,
link);
}
cur->mm = mm;
- cur->start = drm_buddy_block_offset(block) + start;
- cur->size = min(drm_buddy_block_size(mm, block) - start,
+ cur->start = gpu_buddy_block_offset(block) + start;
+ cur->size = min(gpu_buddy_block_size(mm, block) - start,
size);
cur->remaining = size;
cur->node = block;
@@ -175,7 +175,7 @@ static inline void xe_res_first_sg(const
*/
static inline void xe_res_next(struct xe_res_cursor *cur, u64 size)
{
- struct drm_buddy_block *block;
+ struct gpu_buddy_block *block;
struct list_head *next;
u64 start;
@@ -205,18 +205,18 @@ static inline void xe_res_next(struct xe
block = cur->node;
next = block->link.next;
- block = list_entry(next, struct drm_buddy_block, link);
+ block = list_entry(next, struct gpu_buddy_block, link);
- while (start >= drm_buddy_block_size(cur->mm, block)) {
- start -= drm_buddy_block_size(cur->mm, block);
+ while (start >= gpu_buddy_block_size(cur->mm, block)) {
+ start -= gpu_buddy_block_size(cur->mm, block);
next = block->link.next;
- block = list_entry(next, struct drm_buddy_block, link);
+ block = list_entry(next, struct gpu_buddy_block, link);
}
- cur->start = drm_buddy_block_offset(block) + start;
- cur->size = min(drm_buddy_block_size(cur->mm, block) - start,
+ cur->start = gpu_buddy_block_offset(block) + start;
+ cur->size = min(gpu_buddy_block_size(cur->mm, block) - start,
cur->remaining);
cur->node = block;
break;
--- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
+++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr.c
@@ -5,6 +5,7 @@
*/
#include <drm/drm_managed.h>
+#include <drm/drm_buddy.h>
#include <drm/ttm/ttm_placement.h>
#include <drm/ttm/ttm_range_manager.h>
@@ -15,16 +16,16 @@
#include "xe_res_cursor.h"
#include "xe_ttm_vram_mgr.h"
-static inline struct drm_buddy_block *
+static inline struct gpu_buddy_block *
xe_ttm_vram_mgr_first_block(struct list_head *list)
{
- return list_first_entry_or_null(list, struct drm_buddy_block, link);
+ return list_first_entry_or_null(list, struct gpu_buddy_block, link);
}
-static inline bool xe_is_vram_mgr_blocks_contiguous(struct drm_buddy *mm,
+static inline bool xe_is_vram_mgr_blocks_contiguous(struct gpu_buddy *mm,
struct list_head *head)
{
- struct drm_buddy_block *block;
+ struct gpu_buddy_block *block;
u64 start, size;
block = xe_ttm_vram_mgr_first_block(head);
@@ -32,12 +33,12 @@ static inline bool xe_is_vram_mgr_blocks
return false;
while (head != block->link.next) {
- start = drm_buddy_block_offset(block);
- size = drm_buddy_block_size(mm, block);
+ start = gpu_buddy_block_offset(block);
+ size = gpu_buddy_block_size(mm, block);
- block = list_entry(block->link.next, struct drm_buddy_block,
+ block = list_entry(block->link.next, struct gpu_buddy_block,
link);
- if (start + size != drm_buddy_block_offset(block))
+ if (start + size != gpu_buddy_block_offset(block))
return false;
}
@@ -51,7 +52,7 @@ static int xe_ttm_vram_mgr_new(struct tt
{
struct xe_ttm_vram_mgr *mgr = to_xe_ttm_vram_mgr(man);
struct xe_ttm_vram_mgr_resource *vres;
- struct drm_buddy *mm = &mgr->mm;
+ struct gpu_buddy *mm = &mgr->mm;
u64 size, remaining_size, min_page_size;
unsigned long lpfn;
int err;
@@ -78,10 +79,10 @@ static int xe_ttm_vram_mgr_new(struct tt
INIT_LIST_HEAD(&vres->blocks);
if (place->flags & TTM_PL_FLAG_TOPDOWN)
- vres->flags |= DRM_BUDDY_TOPDOWN_ALLOCATION;
+ vres->flags |= GPU_BUDDY_TOPDOWN_ALLOCATION;
if (place->fpfn || lpfn != man->size >> PAGE_SHIFT)
- vres->flags |= DRM_BUDDY_RANGE_ALLOCATION;
+ vres->flags |= GPU_BUDDY_RANGE_ALLOCATION;
if (WARN_ON(!vres->base.size)) {
err = -EINVAL;
@@ -137,7 +138,7 @@ static int xe_ttm_vram_mgr_new(struct tt
*/
u64 alloc_size = min_t(u64, remaining_size, SZ_2G);
- err = drm_buddy_alloc_blocks(mm, (u64)place->fpfn << PAGE_SHIFT,
+ err = gpu_buddy_alloc_blocks(mm, (u64)place->fpfn << PAGE_SHIFT,
(u64)lpfn << PAGE_SHIFT,
alloc_size,
min_page_size,
@@ -150,20 +151,20 @@ static int xe_ttm_vram_mgr_new(struct tt
} while (remaining_size);
if (place->flags & TTM_PL_FLAG_CONTIGUOUS) {
- if (!drm_buddy_block_trim(mm, NULL, vres->base.size, &vres->blocks))
+ if (!gpu_buddy_block_trim(mm, NULL, vres->base.size, &vres->blocks))
size = vres->base.size;
}
if (lpfn <= mgr->visible_size >> PAGE_SHIFT) {
vres->used_visible_size = size;
} else {
- struct drm_buddy_block *block;
+ struct gpu_buddy_block *block;
list_for_each_entry(block, &vres->blocks, link) {
- u64 start = drm_buddy_block_offset(block);
+ u64 start = gpu_buddy_block_offset(block);
if (start < mgr->visible_size) {
- u64 end = start + drm_buddy_block_size(mm, block);
+ u64 end = start + gpu_buddy_block_size(mm, block);
vres->used_visible_size +=
min(end, mgr->visible_size) - start;
@@ -183,11 +184,11 @@ static int xe_ttm_vram_mgr_new(struct tt
* the object.
*/
if (vres->base.placement & TTM_PL_FLAG_CONTIGUOUS) {
- struct drm_buddy_block *block = list_first_entry(&vres->blocks,
+ struct gpu_buddy_block *block = list_first_entry(&vres->blocks,
typeof(*block),
link);
- vres->base.start = drm_buddy_block_offset(block) >> PAGE_SHIFT;
+ vres->base.start = gpu_buddy_block_offset(block) >> PAGE_SHIFT;
} else {
vres->base.start = XE_BO_INVALID_OFFSET;
}
@@ -196,7 +197,7 @@ static int xe_ttm_vram_mgr_new(struct tt
return 0;
error_free_blocks:
- drm_buddy_free_list(mm, &vres->blocks, 0);
+ gpu_buddy_free_list(mm, &vres->blocks, 0);
mutex_unlock(&mgr->lock);
error_fini:
ttm_resource_fini(man, &vres->base);
@@ -211,10 +212,10 @@ static void xe_ttm_vram_mgr_del(struct t
struct xe_ttm_vram_mgr_resource *vres =
to_xe_ttm_vram_mgr_resource(res);
struct xe_ttm_vram_mgr *mgr = to_xe_ttm_vram_mgr(man);
- struct drm_buddy *mm = &mgr->mm;
+ struct gpu_buddy *mm = &mgr->mm;
mutex_lock(&mgr->lock);
- drm_buddy_free_list(mm, &vres->blocks, 0);
+ gpu_buddy_free_list(mm, &vres->blocks, 0);
mgr->visible_avail += vres->used_visible_size;
mutex_unlock(&mgr->lock);
@@ -227,7 +228,7 @@ static void xe_ttm_vram_mgr_debug(struct
struct drm_printer *printer)
{
struct xe_ttm_vram_mgr *mgr = to_xe_ttm_vram_mgr(man);
- struct drm_buddy *mm = &mgr->mm;
+ struct gpu_buddy *mm = &mgr->mm;
mutex_lock(&mgr->lock);
drm_printf(printer, "default_page_size: %lluKiB\n",
@@ -250,8 +251,8 @@ static bool xe_ttm_vram_mgr_intersects(s
struct xe_ttm_vram_mgr *mgr = to_xe_ttm_vram_mgr(man);
struct xe_ttm_vram_mgr_resource *vres =
to_xe_ttm_vram_mgr_resource(res);
- struct drm_buddy *mm = &mgr->mm;
- struct drm_buddy_block *block;
+ struct gpu_buddy *mm = &mgr->mm;
+ struct gpu_buddy_block *block;
if (!place->fpfn && !place->lpfn)
return true;
@@ -261,9 +262,9 @@ static bool xe_ttm_vram_mgr_intersects(s
list_for_each_entry(block, &vres->blocks, link) {
unsigned long fpfn =
- drm_buddy_block_offset(block) >> PAGE_SHIFT;
+ gpu_buddy_block_offset(block) >> PAGE_SHIFT;
unsigned long lpfn = fpfn +
- (drm_buddy_block_size(mm, block) >> PAGE_SHIFT);
+ (gpu_buddy_block_size(mm, block) >> PAGE_SHIFT);
if (place->fpfn < lpfn && place->lpfn > fpfn)
return true;
@@ -280,8 +281,8 @@ static bool xe_ttm_vram_mgr_compatible(s
struct xe_ttm_vram_mgr *mgr = to_xe_ttm_vram_mgr(man);
struct xe_ttm_vram_mgr_resource *vres =
to_xe_ttm_vram_mgr_resource(res);
- struct drm_buddy *mm = &mgr->mm;
- struct drm_buddy_block *block;
+ struct gpu_buddy *mm = &mgr->mm;
+ struct gpu_buddy_block *block;
if (!place->fpfn && !place->lpfn)
return true;
@@ -291,9 +292,9 @@ static bool xe_ttm_vram_mgr_compatible(s
list_for_each_entry(block, &vres->blocks, link) {
unsigned long fpfn =
- drm_buddy_block_offset(block) >> PAGE_SHIFT;
+ gpu_buddy_block_offset(block) >> PAGE_SHIFT;
unsigned long lpfn = fpfn +
- (drm_buddy_block_size(mm, block) >> PAGE_SHIFT);
+ (gpu_buddy_block_size(mm, block) >> PAGE_SHIFT);
if (fpfn < place->fpfn || lpfn > place->lpfn)
return false;
@@ -323,7 +324,7 @@ static void ttm_vram_mgr_fini(struct drm
WARN_ON_ONCE(mgr->visible_avail != mgr->visible_size);
- drm_buddy_fini(&mgr->mm);
+ gpu_buddy_fini(&mgr->mm);
ttm_resource_manager_cleanup(&mgr->manager);
@@ -347,7 +348,7 @@ int __xe_ttm_vram_mgr_init(struct xe_dev
mgr->visible_avail = io_size;
ttm_resource_manager_init(man, &xe->ttm, size);
- err = drm_buddy_init(&mgr->mm, man->size, default_page_size);
+ err = gpu_buddy_init(&mgr->mm, man->size, default_page_size);
if (err)
return err;
@@ -389,7 +390,7 @@ int xe_ttm_vram_mgr_alloc_sgt(struct xe_
if (!*sgt)
return -ENOMEM;
- /* Determine the number of DRM_BUDDY blocks to export */
+ /* Determine the number of GPU_BUDDY blocks to export */
xe_res_first(res, offset, length, &cursor);
while (cursor.remaining) {
num_entries++;
@@ -405,10 +406,10 @@ int xe_ttm_vram_mgr_alloc_sgt(struct xe_
sg->length = 0;
/*
- * Walk down DRM_BUDDY blocks to populate scatterlist nodes
- * @note: Use iterator api to get first the DRM_BUDDY block
+ * Walk down GPU_BUDDY blocks to populate scatterlist nodes
+ * @note: Use iterator api to get first the GPU_BUDDY block
* and the number of bytes from it. Access the following
- * DRM_BUDDY block(s) if more buffer needs to exported
+ * GPU_BUDDY block(s) if more buffer needs to exported
*/
xe_res_first(res, offset, length, &cursor);
for_each_sgtable_sg((*sgt), sg, i) {
--- a/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h
+++ b/drivers/gpu/drm/xe/xe_ttm_vram_mgr_types.h
@@ -6,7 +6,7 @@
#ifndef _XE_TTM_VRAM_MGR_TYPES_H_
#define _XE_TTM_VRAM_MGR_TYPES_H_
-#include <drm/drm_buddy.h>
+#include <linux/gpu_buddy.h>
#include <drm/ttm/ttm_device.h>
struct xe_mem_region;
@@ -20,7 +20,7 @@ struct xe_ttm_vram_mgr {
/** @manager: Base TTM resource manager */
struct ttm_resource_manager manager;
/** @mm: DRM buddy allocator which manages the VRAM */
- struct drm_buddy mm;
+ struct gpu_buddy mm;
/** @vram: ptr to details of associated VRAM region */
struct xe_mem_region *vram;
/** @visible_size: Proped size of the CPU visible portion */
--- /dev/null
+++ b/drivers/gpu/tests/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+
+gpu_buddy_tests-y = gpu_buddy_test.o gpu_random.o
+obj-$(CONFIG_GPU_BUDDY_KUNIT_TEST) += gpu_buddy_tests.o
--- /dev/null
+++ b/drivers/gpu/tests/gpu_buddy_test.c
@@ -0,0 +1,778 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2019 Intel Corporation
+ * Copyright © 2022 Maíra Canal <mairacanal@riseup.net>
+ */
+
+#include <kunit/test.h>
+
+#include <linux/prime_numbers.h>
+#include <linux/sched/signal.h>
+#include <linux/sizes.h>
+
+#include <linux/gpu_buddy.h>
+
+#include "gpu_random.h"
+
+static unsigned int random_seed;
+
+static inline u64 get_size(int order, u64 chunk_size)
+{
+ return (1 << order) * chunk_size;
+}
+
+static void drm_test_buddy_alloc_range_bias(struct kunit *test)
+{
+ u32 mm_size, size, ps, bias_size, bias_start, bias_end, bias_rem;
+ GPU_RND_STATE(prng, random_seed);
+ unsigned int i, count, *order;
+ struct gpu_buddy_block *block;
+ unsigned long flags;
+ struct gpu_buddy mm;
+ LIST_HEAD(allocated);
+
+ bias_size = SZ_1M;
+ ps = roundup_pow_of_two(prandom_u32_state(&prng) % bias_size);
+ ps = max(SZ_4K, ps);
+ mm_size = (SZ_8M-1) & ~(ps-1); /* Multiple roots */
+
+ kunit_info(test, "mm_size=%u, ps=%u\n", mm_size, ps);
+
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, ps),
+ "buddy_init failed\n");
+
+ count = mm_size / bias_size;
+ order = gpu_random_order(count, &prng);
+ KUNIT_EXPECT_TRUE(test, order);
+
+ /*
+ * Idea is to split the address space into uniform bias ranges, and then
+ * in some random order allocate within each bias, using various
+ * patterns within. This should detect if allocations leak out from a
+ * given bias, for example.
+ */
+
+ for (i = 0; i < count; i++) {
+ LIST_HEAD(tmp);
+ u32 size;
+
+ bias_start = order[i] * bias_size;
+ bias_end = bias_start + bias_size;
+ bias_rem = bias_size;
+
+ /* internal round_up too big */
+ KUNIT_ASSERT_TRUE_MSG(test,
+ gpu_buddy_alloc_blocks(&mm, bias_start,
+ bias_end, bias_size + ps, bias_size,
+ &allocated,
+ GPU_BUDDY_RANGE_ALLOCATION),
+ "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
+ bias_start, bias_end, bias_size, bias_size);
+
+ /* size too big */
+ KUNIT_ASSERT_TRUE_MSG(test,
+ gpu_buddy_alloc_blocks(&mm, bias_start,
+ bias_end, bias_size + ps, ps,
+ &allocated,
+ GPU_BUDDY_RANGE_ALLOCATION),
+ "buddy_alloc didn't fail with bias(%x-%x), size=%u, ps=%u\n",
+ bias_start, bias_end, bias_size + ps, ps);
+
+ /* bias range too small for size */
+ KUNIT_ASSERT_TRUE_MSG(test,
+ gpu_buddy_alloc_blocks(&mm, bias_start + ps,
+ bias_end, bias_size, ps,
+ &allocated,
+ GPU_BUDDY_RANGE_ALLOCATION),
+ "buddy_alloc didn't fail with bias(%x-%x), size=%u, ps=%u\n",
+ bias_start + ps, bias_end, bias_size, ps);
+
+ /* bias misaligned */
+ KUNIT_ASSERT_TRUE_MSG(test,
+ gpu_buddy_alloc_blocks(&mm, bias_start + ps,
+ bias_end - ps,
+ bias_size >> 1, bias_size >> 1,
+ &allocated,
+ GPU_BUDDY_RANGE_ALLOCATION),
+ "buddy_alloc h didn't fail with bias(%x-%x), size=%u, ps=%u\n",
+ bias_start + ps, bias_end - ps, bias_size >> 1, bias_size >> 1);
+
+ /* single big page */
+ KUNIT_ASSERT_FALSE_MSG(test,
+ gpu_buddy_alloc_blocks(&mm, bias_start,
+ bias_end, bias_size, bias_size,
+ &tmp,
+ GPU_BUDDY_RANGE_ALLOCATION),
+ "buddy_alloc i failed with bias(%x-%x), size=%u, ps=%u\n",
+ bias_start, bias_end, bias_size, bias_size);
+ gpu_buddy_free_list(&mm, &tmp, 0);
+
+ /* single page with internal round_up */
+ KUNIT_ASSERT_FALSE_MSG(test,
+ gpu_buddy_alloc_blocks(&mm, bias_start,
+ bias_end, ps, bias_size,
+ &tmp,
+ GPU_BUDDY_RANGE_ALLOCATION),
+ "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
+ bias_start, bias_end, ps, bias_size);
+ gpu_buddy_free_list(&mm, &tmp, 0);
+
+ /* random size within */
+ size = max(round_up(prandom_u32_state(&prng) % bias_rem, ps), ps);
+ if (size)
+ KUNIT_ASSERT_FALSE_MSG(test,
+ gpu_buddy_alloc_blocks(&mm, bias_start,
+ bias_end, size, ps,
+ &tmp,
+ GPU_BUDDY_RANGE_ALLOCATION),
+ "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
+ bias_start, bias_end, size, ps);
+
+ bias_rem -= size;
+ /* too big for current avail */
+ KUNIT_ASSERT_TRUE_MSG(test,
+ gpu_buddy_alloc_blocks(&mm, bias_start,
+ bias_end, bias_rem + ps, ps,
+ &allocated,
+ GPU_BUDDY_RANGE_ALLOCATION),
+ "buddy_alloc didn't fail with bias(%x-%x), size=%u, ps=%u\n",
+ bias_start, bias_end, bias_rem + ps, ps);
+
+ if (bias_rem) {
+ /* random fill of the remainder */
+ size = max(round_up(prandom_u32_state(&prng) % bias_rem, ps), ps);
+ size = max(size, ps);
+
+ KUNIT_ASSERT_FALSE_MSG(test,
+ gpu_buddy_alloc_blocks(&mm, bias_start,
+ bias_end, size, ps,
+ &allocated,
+ GPU_BUDDY_RANGE_ALLOCATION),
+ "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
+ bias_start, bias_end, size, ps);
+ /*
+ * Intentionally allow some space to be left
+ * unallocated, and ideally not always on the bias
+ * boundaries.
+ */
+ gpu_buddy_free_list(&mm, &tmp, 0);
+ } else {
+ list_splice_tail(&tmp, &allocated);
+ }
+ }
+
+ kfree(order);
+ gpu_buddy_free_list(&mm, &allocated, 0);
+ gpu_buddy_fini(&mm);
+
+ /*
+ * Something more free-form. Idea is to pick a random starting bias
+ * range within the address space and then start filling it up. Also
+ * randomly grow the bias range in both directions as we go along. This
+ * should give us bias start/end which is not always uniform like above,
+ * and in some cases will require the allocator to jump over already
+ * allocated nodes in the middle of the address space.
+ */
+
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, ps),
+ "buddy_init failed\n");
+
+ bias_start = round_up(prandom_u32_state(&prng) % (mm_size - ps), ps);
+ bias_end = round_up(bias_start + prandom_u32_state(&prng) % (mm_size - bias_start), ps);
+ bias_end = max(bias_end, bias_start + ps);
+ bias_rem = bias_end - bias_start;
+
+ do {
+ u32 size = max(round_up(prandom_u32_state(&prng) % bias_rem, ps), ps);
+
+ KUNIT_ASSERT_FALSE_MSG(test,
+ gpu_buddy_alloc_blocks(&mm, bias_start,
+ bias_end, size, ps,
+ &allocated,
+ GPU_BUDDY_RANGE_ALLOCATION),
+ "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
+ bias_start, bias_end, size, ps);
+ bias_rem -= size;
+
+ /*
+ * Try to randomly grow the bias range in both directions, or
+ * only one, or perhaps don't grow at all.
+ */
+ do {
+ u32 old_bias_start = bias_start;
+ u32 old_bias_end = bias_end;
+
+ if (bias_start)
+ bias_start -= round_up(prandom_u32_state(&prng) % bias_start, ps);
+ if (bias_end != mm_size)
+ bias_end += round_up(prandom_u32_state(&prng) % (mm_size - bias_end), ps);
+
+ bias_rem += old_bias_start - bias_start;
+ bias_rem += bias_end - old_bias_end;
+ } while (!bias_rem && (bias_start || bias_end != mm_size));
+ } while (bias_rem);
+
+ KUNIT_ASSERT_EQ(test, bias_start, 0);
+ KUNIT_ASSERT_EQ(test, bias_end, mm_size);
+ KUNIT_ASSERT_TRUE_MSG(test,
+ gpu_buddy_alloc_blocks(&mm, bias_start, bias_end,
+ ps, ps,
+ &allocated,
+ GPU_BUDDY_RANGE_ALLOCATION),
+ "buddy_alloc passed with bias(%x-%x), size=%u\n",
+ bias_start, bias_end, ps);
+
+ gpu_buddy_free_list(&mm, &allocated, 0);
+ gpu_buddy_fini(&mm);
+
+ /*
+ * Allocate cleared blocks in the bias range when the DRM buddy's clear avail is
+ * zero. This will validate the bias range allocation in scenarios like system boot
+ * when no cleared blocks are available and exercise the fallback path too. The resulting
+ * blocks should always be dirty.
+ */
+
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, ps),
+ "buddy_init failed\n");
+
+ bias_start = round_up(prandom_u32_state(&prng) % (mm_size - ps), ps);
+ bias_end = round_up(bias_start + prandom_u32_state(&prng) % (mm_size - bias_start), ps);
+ bias_end = max(bias_end, bias_start + ps);
+ bias_rem = bias_end - bias_start;
+
+ flags = GPU_BUDDY_CLEAR_ALLOCATION | GPU_BUDDY_RANGE_ALLOCATION;
+ size = max(round_up(prandom_u32_state(&prng) % bias_rem, ps), ps);
+
+ KUNIT_ASSERT_FALSE_MSG(test,
+ gpu_buddy_alloc_blocks(&mm, bias_start,
+ bias_end, size, ps,
+ &allocated,
+ flags),
+ "buddy_alloc failed with bias(%x-%x), size=%u, ps=%u\n",
+ bias_start, bias_end, size, ps);
+
+ list_for_each_entry(block, &allocated, link)
+ KUNIT_EXPECT_EQ(test, gpu_buddy_block_is_clear(block), false);
+
+ gpu_buddy_free_list(&mm, &allocated, 0);
+ gpu_buddy_fini(&mm);
+}
+
+static void drm_test_buddy_alloc_clear(struct kunit *test)
+{
+ unsigned long n_pages, total, i = 0;
+ GPU_RND_STATE(prng, random_seed);
+ const unsigned long ps = SZ_4K;
+ struct gpu_buddy_block *block;
+ const int max_order = 12;
+ LIST_HEAD(allocated);
+ struct gpu_buddy mm;
+ unsigned int order;
+ u32 mm_size, size;
+ LIST_HEAD(dirty);
+ LIST_HEAD(clean);
+
+ mm_size = SZ_4K << max_order;
+ KUNIT_EXPECT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
+
+ KUNIT_EXPECT_EQ(test, mm.max_order, max_order);
+
+ /*
+ * Idea is to allocate and free some random portion of the address space,
+ * returning those pages as non-dirty and randomly alternate between
+ * requesting dirty and non-dirty pages (not going over the limit
+ * we freed as non-dirty), putting that into two separate lists.
+ * Loop over both lists at the end checking that the dirty list
+ * is indeed all dirty pages and vice versa. Free it all again,
+ * keeping the dirty/clear status.
+ */
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+ 5 * ps, ps, &allocated,
+ GPU_BUDDY_TOPDOWN_ALLOCATION),
+ "buddy_alloc hit an error size=%lu\n", 5 * ps);
+ gpu_buddy_free_list(&mm, &allocated, GPU_BUDDY_CLEARED);
+
+ n_pages = 10;
+ do {
+ unsigned long flags;
+ struct list_head *list;
+ int slot = i % 2;
+
+ if (slot == 0) {
+ list = &dirty;
+ flags = 0;
+ } else {
+ list = &clean;
+ flags = GPU_BUDDY_CLEAR_ALLOCATION;
+ }
+
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+ ps, ps, list,
+ flags),
+ "buddy_alloc hit an error size=%lu\n", ps);
+ } while (++i < n_pages);
+
+ list_for_each_entry(block, &clean, link)
+ KUNIT_EXPECT_EQ(test, gpu_buddy_block_is_clear(block), true);
+
+ list_for_each_entry(block, &dirty, link)
+ KUNIT_EXPECT_EQ(test, gpu_buddy_block_is_clear(block), false);
+
+ gpu_buddy_free_list(&mm, &clean, GPU_BUDDY_CLEARED);
+
+ /*
+ * Trying to go over the clear limit for some allocation.
+ * The allocation should never fail with reasonable page-size.
+ */
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+ 10 * ps, ps, &clean,
+ GPU_BUDDY_CLEAR_ALLOCATION),
+ "buddy_alloc hit an error size=%lu\n", 10 * ps);
+
+ gpu_buddy_free_list(&mm, &clean, GPU_BUDDY_CLEARED);
+ gpu_buddy_free_list(&mm, &dirty, 0);
+ gpu_buddy_fini(&mm);
+
+ KUNIT_EXPECT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
+
+ /*
+ * Create a new mm. Intentionally fragment the address space by creating
+ * two alternating lists. Free both lists, one as dirty the other as clean.
+ * Try to allocate double the previous size with matching min_page_size. The
+ * allocation should never fail as it calls the force_merge. Also check that
+ * the page is always dirty after force_merge. Free the page as dirty, then
+ * repeat the whole thing, increment the order until we hit the max_order.
+ */
+
+ i = 0;
+ n_pages = mm_size / ps;
+ do {
+ struct list_head *list;
+ int slot = i % 2;
+
+ if (slot == 0)
+ list = &dirty;
+ else
+ list = &clean;
+
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+ ps, ps, list, 0),
+ "buddy_alloc hit an error size=%lu\n", ps);
+ } while (++i < n_pages);
+
+ gpu_buddy_free_list(&mm, &clean, GPU_BUDDY_CLEARED);
+ gpu_buddy_free_list(&mm, &dirty, 0);
+
+ order = 1;
+ do {
+ size = SZ_4K << order;
+
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+ size, size, &allocated,
+ GPU_BUDDY_CLEAR_ALLOCATION),
+ "buddy_alloc hit an error size=%u\n", size);
+ total = 0;
+ list_for_each_entry(block, &allocated, link) {
+ if (size != mm_size)
+ KUNIT_EXPECT_EQ(test, gpu_buddy_block_is_clear(block), false);
+ total += gpu_buddy_block_size(&mm, block);
+ }
+ KUNIT_EXPECT_EQ(test, total, size);
+
+ gpu_buddy_free_list(&mm, &allocated, 0);
+ } while (++order <= max_order);
+
+ gpu_buddy_fini(&mm);
+
+ /*
+ * Create a new mm with a non power-of-two size. Allocate a random size, free as
+ * cleared and then call fini. This will ensure the multi-root force merge during
+ * fini.
+ */
+ mm_size = 12 * SZ_4K;
+ size = max(round_up(prandom_u32_state(&prng) % mm_size, ps), ps);
+ KUNIT_EXPECT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+ size, ps, &allocated,
+ GPU_BUDDY_TOPDOWN_ALLOCATION),
+ "buddy_alloc hit an error size=%u\n", size);
+ gpu_buddy_free_list(&mm, &allocated, GPU_BUDDY_CLEARED);
+ gpu_buddy_fini(&mm);
+}
+
+static void drm_test_buddy_alloc_contiguous(struct kunit *test)
+{
+ const unsigned long ps = SZ_4K, mm_size = 16 * 3 * SZ_4K;
+ unsigned long i, n_pages, total;
+ struct gpu_buddy_block *block;
+ struct gpu_buddy mm;
+ LIST_HEAD(left);
+ LIST_HEAD(middle);
+ LIST_HEAD(right);
+ LIST_HEAD(allocated);
+
+ KUNIT_EXPECT_FALSE(test, gpu_buddy_init(&mm, mm_size, ps));
+
+ /*
+ * Idea is to fragment the address space by alternating block
+ * allocations between three different lists; one for left, middle and
+ * right. We can then free a list to simulate fragmentation. In
+ * particular we want to exercise the GPU_BUDDY_CONTIGUOUS_ALLOCATION,
+ * including the try_harder path.
+ */
+
+ i = 0;
+ n_pages = mm_size / ps;
+ do {
+ struct list_head *list;
+ int slot = i % 3;
+
+ if (slot == 0)
+ list = &left;
+ else if (slot == 1)
+ list = &middle;
+ else
+ list = &right;
+ KUNIT_ASSERT_FALSE_MSG(test,
+ gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+ ps, ps, list, 0),
+ "buddy_alloc hit an error size=%lu\n",
+ ps);
+ } while (++i < n_pages);
+
+ KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+ 3 * ps, ps, &allocated,
+ GPU_BUDDY_CONTIGUOUS_ALLOCATION),
+ "buddy_alloc didn't error size=%lu\n", 3 * ps);
+
+ gpu_buddy_free_list(&mm, &middle, 0);
+ KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+ 3 * ps, ps, &allocated,
+ GPU_BUDDY_CONTIGUOUS_ALLOCATION),
+ "buddy_alloc didn't error size=%lu\n", 3 * ps);
+ KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+ 2 * ps, ps, &allocated,
+ GPU_BUDDY_CONTIGUOUS_ALLOCATION),
+ "buddy_alloc didn't error size=%lu\n", 2 * ps);
+
+ gpu_buddy_free_list(&mm, &right, 0);
+ KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+ 3 * ps, ps, &allocated,
+ GPU_BUDDY_CONTIGUOUS_ALLOCATION),
+ "buddy_alloc didn't error size=%lu\n", 3 * ps);
+ /*
+ * At this point we should have enough contiguous space for 2 blocks,
+ * however they are never buddies (since we freed middle and right) so
+ * will require the try_harder logic to find them.
+ */
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+ 2 * ps, ps, &allocated,
+ GPU_BUDDY_CONTIGUOUS_ALLOCATION),
+ "buddy_alloc hit an error size=%lu\n", 2 * ps);
+
+ gpu_buddy_free_list(&mm, &left, 0);
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, 0, mm_size,
+ 3 * ps, ps, &allocated,
+ GPU_BUDDY_CONTIGUOUS_ALLOCATION),
+ "buddy_alloc hit an error size=%lu\n", 3 * ps);
+
+ total = 0;
+ list_for_each_entry(block, &allocated, link)
+ total += gpu_buddy_block_size(&mm, block);
+
+ KUNIT_ASSERT_EQ(test, total, ps * 2 + ps * 3);
+
+ gpu_buddy_free_list(&mm, &allocated, 0);
+ gpu_buddy_fini(&mm);
+}
+
+static void drm_test_buddy_alloc_pathological(struct kunit *test)
+{
+ u64 mm_size, size, start = 0;
+ struct gpu_buddy_block *block;
+ const int max_order = 3;
+ unsigned long flags = 0;
+ int order, top;
+ struct gpu_buddy mm;
+ LIST_HEAD(blocks);
+ LIST_HEAD(holes);
+ LIST_HEAD(tmp);
+
+ /*
+ * Create a pot-sized mm, then allocate one of each possible
+ * order within. This should leave the mm with exactly one
+ * page left. Free the largest block, then whittle down again.
+ * Eventually we will have a fully 50% fragmented mm.
+ */
+
+ mm_size = SZ_4K << max_order;
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, SZ_4K),
+ "buddy_init failed\n");
+
+ KUNIT_EXPECT_EQ(test, mm.max_order, max_order);
+
+ for (top = max_order; top; top--) {
+ /* Make room by freeing the largest allocated block */
+ block = list_first_entry_or_null(&blocks, typeof(*block), link);
+ if (block) {
+ list_del(&block->link);
+ gpu_buddy_free_block(&mm, block);
+ }
+
+ for (order = top; order--;) {
+ size = get_size(order, mm.chunk_size);
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, start,
+ mm_size, size, size,
+ &tmp, flags),
+ "buddy_alloc hit -ENOMEM with order=%d, top=%d\n",
+ order, top);
+
+ block = list_first_entry_or_null(&tmp, struct gpu_buddy_block, link);
+ KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
+
+ list_move_tail(&block->link, &blocks);
+ }
+
+ /* There should be one final page for this sub-allocation */
+ size = get_size(0, mm.chunk_size);
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size,
+ size, size, &tmp, flags),
+ "buddy_alloc hit -ENOMEM for hole\n");
+
+ block = list_first_entry_or_null(&tmp, struct gpu_buddy_block, link);
+ KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
+
+ list_move_tail(&block->link, &holes);
+
+ size = get_size(top, mm.chunk_size);
+ KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size,
+ size, size, &tmp, flags),
+ "buddy_alloc unexpectedly succeeded at top-order %d/%d, it should be full!",
+ top, max_order);
+ }
+
+ gpu_buddy_free_list(&mm, &holes, 0);
+
+ /* Nothing larger than blocks of chunk_size now available */
+ for (order = 1; order <= max_order; order++) {
+ size = get_size(order, mm.chunk_size);
+ KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size,
+ size, size, &tmp, flags),
+ "buddy_alloc unexpectedly succeeded at order %d, it should be full!",
+ order);
+ }
+
+ list_splice_tail(&holes, &blocks);
+ gpu_buddy_free_list(&mm, &blocks, 0);
+ gpu_buddy_fini(&mm);
+}
+
+static void drm_test_buddy_alloc_pessimistic(struct kunit *test)
+{
+ u64 mm_size, size, start = 0;
+ struct gpu_buddy_block *block, *bn;
+ const unsigned int max_order = 16;
+ unsigned long flags = 0;
+ struct gpu_buddy mm;
+ unsigned int order;
+ LIST_HEAD(blocks);
+ LIST_HEAD(tmp);
+
+ /*
+ * Create a pot-sized mm, then allocate one of each possible
+ * order within. This should leave the mm with exactly one
+ * page left.
+ */
+
+ mm_size = SZ_4K << max_order;
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, SZ_4K),
+ "buddy_init failed\n");
+
+ KUNIT_EXPECT_EQ(test, mm.max_order, max_order);
+
+ for (order = 0; order < max_order; order++) {
+ size = get_size(order, mm.chunk_size);
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size,
+ size, size, &tmp, flags),
+ "buddy_alloc hit -ENOMEM with order=%d\n",
+ order);
+
+ block = list_first_entry_or_null(&tmp, struct gpu_buddy_block, link);
+ KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
+
+ list_move_tail(&block->link, &blocks);
+ }
+
+ /* And now the last remaining block available */
+ size = get_size(0, mm.chunk_size);
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size,
+ size, size, &tmp, flags),
+ "buddy_alloc hit -ENOMEM on final alloc\n");
+
+ block = list_first_entry_or_null(&tmp, struct gpu_buddy_block, link);
+ KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
+
+ list_move_tail(&block->link, &blocks);
+
+ /* Should be completely full! */
+ for (order = max_order; order--;) {
+ size = get_size(order, mm.chunk_size);
+ KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size,
+ size, size, &tmp, flags),
+ "buddy_alloc unexpectedly succeeded, it should be full!");
+ }
+
+ block = list_last_entry(&blocks, typeof(*block), link);
+ list_del(&block->link);
+ gpu_buddy_free_block(&mm, block);
+
+ /* As we free in increasing size, we make available larger blocks */
+ order = 1;
+ list_for_each_entry_safe(block, bn, &blocks, link) {
+ list_del(&block->link);
+ gpu_buddy_free_block(&mm, block);
+
+ size = get_size(order, mm.chunk_size);
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size,
+ size, size, &tmp, flags),
+ "buddy_alloc hit -ENOMEM with order=%d\n",
+ order);
+
+ block = list_first_entry_or_null(&tmp, struct gpu_buddy_block, link);
+ KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
+
+ list_del(&block->link);
+ gpu_buddy_free_block(&mm, block);
+ order++;
+ }
+
+ /* To confirm, now the whole mm should be available */
+ size = get_size(max_order, mm.chunk_size);
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size,
+ size, size, &tmp, flags),
+ "buddy_alloc (realloc) hit -ENOMEM with order=%d\n",
+ max_order);
+
+ block = list_first_entry_or_null(&tmp, struct gpu_buddy_block, link);
+ KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
+
+ list_del(&block->link);
+ gpu_buddy_free_block(&mm, block);
+ gpu_buddy_free_list(&mm, &blocks, 0);
+ gpu_buddy_fini(&mm);
+}
+
+static void drm_test_buddy_alloc_optimistic(struct kunit *test)
+{
+ u64 mm_size, size, start = 0;
+ struct gpu_buddy_block *block;
+ unsigned long flags = 0;
+ const int max_order = 16;
+ struct gpu_buddy mm;
+ LIST_HEAD(blocks);
+ LIST_HEAD(tmp);
+ int order;
+
+ /*
+ * Create a mm with one block of each order available, and
+ * try to allocate them all.
+ */
+
+ mm_size = SZ_4K * ((1 << (max_order + 1)) - 1);
+
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_init(&mm, mm_size, SZ_4K),
+ "buddy_init failed\n");
+
+ KUNIT_EXPECT_EQ(test, mm.max_order, max_order);
+
+ for (order = 0; order <= max_order; order++) {
+ size = get_size(order, mm.chunk_size);
+ KUNIT_ASSERT_FALSE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size,
+ size, size, &tmp, flags),
+ "buddy_alloc hit -ENOMEM with order=%d\n",
+ order);
+
+ block = list_first_entry_or_null(&tmp, struct gpu_buddy_block, link);
+ KUNIT_ASSERT_TRUE_MSG(test, block, "alloc_blocks has no blocks\n");
+
+ list_move_tail(&block->link, &blocks);
+ }
+
+ /* Should be completely full! */
+ size = get_size(0, mm.chunk_size);
+ KUNIT_ASSERT_TRUE_MSG(test, gpu_buddy_alloc_blocks(&mm, start, mm_size,
+ size, size, &tmp, flags),
+ "buddy_alloc unexpectedly succeeded, it should be full!");
+
+ gpu_buddy_free_list(&mm, &blocks, 0);
+ gpu_buddy_fini(&mm);
+}
+
+static void drm_test_buddy_alloc_limit(struct kunit *test)
+{
+ u64 size = U64_MAX, start = 0;
+ struct gpu_buddy_block *block;
+ unsigned long flags = 0;
+ LIST_HEAD(allocated);
+ struct gpu_buddy mm;
+
+ KUNIT_EXPECT_FALSE(test, gpu_buddy_init(&mm, size, SZ_4K));
+
+ KUNIT_EXPECT_EQ_MSG(test, mm.max_order, GPU_BUDDY_MAX_ORDER,
+ "mm.max_order(%d) != %d\n", mm.max_order,
+ GPU_BUDDY_MAX_ORDER);
+
+ size = mm.chunk_size << mm.max_order;
+ KUNIT_EXPECT_FALSE(test, gpu_buddy_alloc_blocks(&mm, start, size, size,
+ mm.chunk_size, &allocated, flags));
+
+ block = list_first_entry_or_null(&allocated, struct gpu_buddy_block, link);
+ KUNIT_EXPECT_TRUE(test, block);
+
+ KUNIT_EXPECT_EQ_MSG(test, gpu_buddy_block_order(block), mm.max_order,
+ "block order(%d) != %d\n",
+ gpu_buddy_block_order(block), mm.max_order);
+
+ KUNIT_EXPECT_EQ_MSG(test, gpu_buddy_block_size(&mm, block),
+ BIT_ULL(mm.max_order) * mm.chunk_size,
+ "block size(%llu) != %llu\n",
+ gpu_buddy_block_size(&mm, block),
+ BIT_ULL(mm.max_order) * mm.chunk_size);
+
+ gpu_buddy_free_list(&mm, &allocated, 0);
+ gpu_buddy_fini(&mm);
+}
+
+static int gpu_buddy_suite_init(struct kunit_suite *suite)
+{
+ while (!random_seed)
+ random_seed = get_random_u32();
+
+ kunit_info(suite, "Testing DRM buddy manager, with random_seed=0x%x\n",
+ random_seed);
+
+ return 0;
+}
+
+static struct kunit_case gpu_buddy_tests[] = {
+ KUNIT_CASE(drm_test_buddy_alloc_limit),
+ KUNIT_CASE(drm_test_buddy_alloc_optimistic),
+ KUNIT_CASE(drm_test_buddy_alloc_pessimistic),
+ KUNIT_CASE(drm_test_buddy_alloc_pathological),
+ KUNIT_CASE(drm_test_buddy_alloc_contiguous),
+ KUNIT_CASE(drm_test_buddy_alloc_clear),
+ KUNIT_CASE(drm_test_buddy_alloc_range_bias),
+ {}
+};
+
+static struct kunit_suite gpu_buddy_test_suite = {
+ .name = "gpu_buddy",
+ .suite_init = gpu_buddy_suite_init,
+ .test_cases = gpu_buddy_tests,
+};
+
+kunit_test_suite(gpu_buddy_test_suite);
+
+MODULE_AUTHOR("Intel Corporation");
+MODULE_DESCRIPTION("Kunit test for gpu_buddy functions");
+MODULE_LICENSE("GPL");
--- /dev/null
+++ b/drivers/gpu/tests/gpu_random.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/bitops.h>
+#include <linux/kernel.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "gpu_random.h"
+
+u32 gpu_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state)
+{
+ return upper_32_bits((u64)prandom_u32_state(state) * ep_ro);
+}
+EXPORT_SYMBOL(gpu_prandom_u32_max_state);
+
+void gpu_random_reorder(unsigned int *order, unsigned int count,
+ struct rnd_state *state)
+{
+ unsigned int i, j;
+
+ for (i = 0; i < count; ++i) {
+ BUILD_BUG_ON(sizeof(unsigned int) > sizeof(u32));
+ j = gpu_prandom_u32_max_state(count, state);
+ swap(order[i], order[j]);
+ }
+}
+EXPORT_SYMBOL(gpu_random_reorder);
+
+unsigned int *gpu_random_order(unsigned int count, struct rnd_state *state)
+{
+ unsigned int *order, i;
+
+ order = kmalloc_array(count, sizeof(*order), GFP_KERNEL);
+ if (!order)
+ return order;
+
+ for (i = 0; i < count; i++)
+ order[i] = i;
+
+ gpu_random_reorder(order, count, state);
+ return order;
+}
+EXPORT_SYMBOL(gpu_random_order);
--- /dev/null
+++ b/drivers/gpu/tests/gpu_random.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __GPU_RANDOM_H__
+#define __GPU_RANDOM_H__
+
+/* This is a temporary home for a couple of utility functions that should
+ * be transposed to lib/ at the earliest convenience.
+ */
+
+#include <linux/random.h>
+
+#define GPU_RND_STATE_INITIALIZER(seed__) ({ \
+ struct rnd_state state__; \
+ prandom_seed_state(&state__, (seed__)); \
+ state__; \
+})
+
+#define GPU_RND_STATE(name__, seed__) \
+ struct rnd_state name__ = GPU_RND_STATE_INITIALIZER(seed__)
+
+unsigned int *gpu_random_order(unsigned int count,
+ struct rnd_state *state);
+void gpu_random_reorder(unsigned int *order,
+ unsigned int count,
+ struct rnd_state *state);
+u32 gpu_prandom_u32_max_state(u32 ep_ro,
+ struct rnd_state *state);
+
+#endif /* !__GPU_RANDOM_H__ */
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -37,6 +37,7 @@ source "drivers/char/agp/Kconfig"
source "drivers/gpu/vga/Kconfig"
+source "drivers/gpu/Kconfig"
source "drivers/gpu/host1x/Kconfig"
source "drivers/gpu/ipu-v3/Kconfig"
--- a/include/drm/drm_buddy.h
+++ b/include/drm/drm_buddy.h
@@ -6,175 +6,13 @@
#ifndef __DRM_BUDDY_H__
#define __DRM_BUDDY_H__
-#include <linux/bitops.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/sched.h>
-#include <linux/rbtree.h>
+#include <linux/gpu_buddy.h>
-#include <drm/drm_print.h>
+struct drm_printer;
-#define range_overflows(start, size, max) ({ \
- typeof(start) start__ = (start); \
- typeof(size) size__ = (size); \
- typeof(max) max__ = (max); \
- (void)(&start__ == &size__); \
- (void)(&start__ == &max__); \
- start__ >= max__ || size__ > max__ - start__; \
-})
-
-#define DRM_BUDDY_RANGE_ALLOCATION BIT(0)
-#define DRM_BUDDY_TOPDOWN_ALLOCATION BIT(1)
-#define DRM_BUDDY_CONTIGUOUS_ALLOCATION BIT(2)
-#define DRM_BUDDY_CLEAR_ALLOCATION BIT(3)
-#define DRM_BUDDY_CLEARED BIT(4)
-#define DRM_BUDDY_TRIM_DISABLE BIT(5)
-
-struct drm_buddy_block {
-#define DRM_BUDDY_HEADER_OFFSET GENMASK_ULL(63, 12)
-#define DRM_BUDDY_HEADER_STATE GENMASK_ULL(11, 10)
-#define DRM_BUDDY_ALLOCATED (1 << 10)
-#define DRM_BUDDY_FREE (2 << 10)
-#define DRM_BUDDY_SPLIT (3 << 10)
-#define DRM_BUDDY_HEADER_CLEAR GENMASK_ULL(9, 9)
-/* Free to be used, if needed in the future */
-#define DRM_BUDDY_HEADER_UNUSED GENMASK_ULL(8, 6)
-#define DRM_BUDDY_HEADER_ORDER GENMASK_ULL(5, 0)
- u64 header;
-
- struct drm_buddy_block *left;
- struct drm_buddy_block *right;
- struct drm_buddy_block *parent;
-
- void *private; /* owned by creator */
-
- /*
- * While the block is allocated by the user through drm_buddy_alloc*,
- * the user has ownership of the link, for example to maintain within
- * a list, if so desired. As soon as the block is freed with
- * drm_buddy_free* ownership is given back to the mm.
- */
- union {
- struct rb_node rb;
- struct list_head link;
- };
-
- struct list_head tmp_link;
-};
-
-/* Order-zero must be at least SZ_4K */
-#define DRM_BUDDY_MAX_ORDER (63 - 12)
-
-/*
- * Binary Buddy System.
- *
- * Locking should be handled by the user, a simple mutex around
- * drm_buddy_alloc* and drm_buddy_free* should suffice.
- */
-struct drm_buddy {
- /* Maintain a free list for each order. */
- struct rb_root **free_trees;
-
- /*
- * Maintain explicit binary tree(s) to track the allocation of the
- * address space. This gives us a simple way of finding a buddy block
- * and performing the potentially recursive merge step when freeing a
- * block. Nodes are either allocated or free, in which case they will
- * also exist on the respective free list.
- */
- struct drm_buddy_block **roots;
-
- /*
- * Anything from here is public, and remains static for the lifetime of
- * the mm. Everything above is considered do-not-touch.
- */
- unsigned int n_roots;
- unsigned int max_order;
-
- /* Must be at least SZ_4K */
- u64 chunk_size;
- u64 size;
- u64 avail;
- u64 clear_avail;
-};
-
-static inline u64
-drm_buddy_block_offset(const struct drm_buddy_block *block)
-{
- return block->header & DRM_BUDDY_HEADER_OFFSET;
-}
-
-static inline unsigned int
-drm_buddy_block_order(struct drm_buddy_block *block)
-{
- return block->header & DRM_BUDDY_HEADER_ORDER;
-}
-
-static inline unsigned int
-drm_buddy_block_state(struct drm_buddy_block *block)
-{
- return block->header & DRM_BUDDY_HEADER_STATE;
-}
-
-static inline bool
-drm_buddy_block_is_allocated(struct drm_buddy_block *block)
-{
- return drm_buddy_block_state(block) == DRM_BUDDY_ALLOCATED;
-}
-
-static inline bool
-drm_buddy_block_is_clear(struct drm_buddy_block *block)
-{
- return block->header & DRM_BUDDY_HEADER_CLEAR;
-}
-
-static inline bool
-drm_buddy_block_is_free(struct drm_buddy_block *block)
-{
- return drm_buddy_block_state(block) == DRM_BUDDY_FREE;
-}
-
-static inline bool
-drm_buddy_block_is_split(struct drm_buddy_block *block)
-{
- return drm_buddy_block_state(block) == DRM_BUDDY_SPLIT;
-}
-
-static inline u64
-drm_buddy_block_size(struct drm_buddy *mm,
- struct drm_buddy_block *block)
-{
- return mm->chunk_size << drm_buddy_block_order(block);
-}
-
-int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size);
-
-void drm_buddy_fini(struct drm_buddy *mm);
-
-struct drm_buddy_block *
-drm_get_buddy(struct drm_buddy_block *block);
-
-int drm_buddy_alloc_blocks(struct drm_buddy *mm,
- u64 start, u64 end, u64 size,
- u64 min_page_size,
- struct list_head *blocks,
- unsigned long flags);
-
-int drm_buddy_block_trim(struct drm_buddy *mm,
- u64 *start,
- u64 new_size,
- struct list_head *blocks);
-
-void drm_buddy_reset_clear(struct drm_buddy *mm, bool is_clear);
-
-void drm_buddy_free_block(struct drm_buddy *mm, struct drm_buddy_block *block);
-
-void drm_buddy_free_list(struct drm_buddy *mm,
- struct list_head *objects,
- unsigned int flags);
-
-void drm_buddy_print(struct drm_buddy *mm, struct drm_printer *p);
-void drm_buddy_block_print(struct drm_buddy *mm,
- struct drm_buddy_block *block,
+/* DRM-specific GPU Buddy Allocator print helpers */
+void drm_buddy_print(struct gpu_buddy *mm, struct drm_printer *p);
+void drm_buddy_block_print(struct gpu_buddy *mm,
+ struct gpu_buddy_block *block,
struct drm_printer *p);
#endif
--- /dev/null
+++ b/include/linux/gpu_buddy.h
@@ -0,0 +1,188 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2021 Intel Corporation
+ */
+
+#ifndef __GPU_BUDDY_H__
+#define __GPU_BUDDY_H__
+
+#include <linux/bitops.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/rbtree.h>
+
+#include <drm/drm_print.h>
+
+#define range_overflows(start, size, max) ({ \
+ typeof(start) start__ = (start); \
+ typeof(size) size__ = (size); \
+ typeof(max) max__ = (max); \
+ (void)(&start__ == &size__); \
+ (void)(&start__ == &max__); \
+ start__ >= max__ || size__ > max__ - start__; \
+})
+
+#define GPU_BUDDY_RANGE_ALLOCATION BIT(0)
+#define GPU_BUDDY_TOPDOWN_ALLOCATION BIT(1)
+#define GPU_BUDDY_CONTIGUOUS_ALLOCATION BIT(2)
+#define GPU_BUDDY_CLEAR_ALLOCATION BIT(3)
+#define GPU_BUDDY_CLEARED BIT(4)
+#define GPU_BUDDY_TRIM_DISABLE BIT(5)
+
+enum gpu_buddy_free_tree {
+ GPU_BUDDY_CLEAR_TREE = 0,
+ GPU_BUDDY_DIRTY_TREE,
+ GPU_BUDDY_MAX_FREE_TREES,
+};
+
+#define for_each_free_tree(tree) \
+ for ((tree) = 0; (tree) < GPU_BUDDY_MAX_FREE_TREES; (tree)++)
+
+struct gpu_buddy_block {
+#define GPU_BUDDY_HEADER_OFFSET GENMASK_ULL(63, 12)
+#define GPU_BUDDY_HEADER_STATE GENMASK_ULL(11, 10)
+#define GPU_BUDDY_ALLOCATED (1 << 10)
+#define GPU_BUDDY_FREE (2 << 10)
+#define GPU_BUDDY_SPLIT (3 << 10)
+#define GPU_BUDDY_HEADER_CLEAR GENMASK_ULL(9, 9)
+/* Free to be used, if needed in the future */
+#define GPU_BUDDY_HEADER_UNUSED GENMASK_ULL(8, 6)
+#define GPU_BUDDY_HEADER_ORDER GENMASK_ULL(5, 0)
+ u64 header;
+
+ struct gpu_buddy_block *left;
+ struct gpu_buddy_block *right;
+ struct gpu_buddy_block *parent;
+
+ void *private; /* owned by creator */
+
+ /*
+ * While the block is allocated by the user through gpu_buddy_alloc*,
+ * the user has ownership of the link, for example to maintain within
+ * a list, if so desired. As soon as the block is freed with
+ * gpu_buddy_free* ownership is given back to the mm.
+ */
+ union {
+ struct rb_node rb;
+ struct list_head link;
+ };
+
+ struct list_head tmp_link;
+};
+
+/* Order-zero must be at least SZ_4K */
+#define GPU_BUDDY_MAX_ORDER (63 - 12)
+
+/*
+ * Binary Buddy System.
+ *
+ * Locking should be handled by the user, a simple mutex around
+ * gpu_buddy_alloc* and gpu_buddy_free* should suffice.
+ */
+struct gpu_buddy {
+ /* Maintain a free list for each order. */
+ struct rb_root **free_trees;
+
+ /*
+ * Maintain explicit binary tree(s) to track the allocation of the
+ * address space. This gives us a simple way of finding a buddy block
+ * and performing the potentially recursive merge step when freeing a
+ * block. Nodes are either allocated or free, in which case they will
+ * also exist on the respective free list.
+ */
+ struct gpu_buddy_block **roots;
+
+ /*
+ * Anything from here is public, and remains static for the lifetime of
+ * the mm. Everything above is considered do-not-touch.
+ */
+ unsigned int n_roots;
+ unsigned int max_order;
+
+ /* Must be at least SZ_4K */
+ u64 chunk_size;
+ u64 size;
+ u64 avail;
+ u64 clear_avail;
+};
+
+static inline u64
+gpu_buddy_block_offset(const struct gpu_buddy_block *block)
+{
+ return block->header & GPU_BUDDY_HEADER_OFFSET;
+}
+
+static inline unsigned int
+gpu_buddy_block_order(struct gpu_buddy_block *block)
+{
+ return block->header & GPU_BUDDY_HEADER_ORDER;
+}
+
+static inline unsigned int
+gpu_buddy_block_state(struct gpu_buddy_block *block)
+{
+ return block->header & GPU_BUDDY_HEADER_STATE;
+}
+
+static inline bool
+gpu_buddy_block_is_allocated(struct gpu_buddy_block *block)
+{
+ return gpu_buddy_block_state(block) == GPU_BUDDY_ALLOCATED;
+}
+
+static inline bool
+gpu_buddy_block_is_clear(struct gpu_buddy_block *block)
+{
+ return block->header & GPU_BUDDY_HEADER_CLEAR;
+}
+
+static inline bool
+gpu_buddy_block_is_free(struct gpu_buddy_block *block)
+{
+ return gpu_buddy_block_state(block) == GPU_BUDDY_FREE;
+}
+
+static inline bool
+gpu_buddy_block_is_split(struct gpu_buddy_block *block)
+{
+ return gpu_buddy_block_state(block) == GPU_BUDDY_SPLIT;
+}
+
+static inline u64
+gpu_buddy_block_size(struct gpu_buddy *mm,
+ struct gpu_buddy_block *block)
+{
+ return mm->chunk_size << gpu_buddy_block_order(block);
+}
+
+int gpu_buddy_init(struct gpu_buddy *mm, u64 size, u64 chunk_size);
+
+void gpu_buddy_fini(struct gpu_buddy *mm);
+
+struct gpu_buddy_block *
+gpu_get_buddy(struct gpu_buddy_block *block);
+
+int gpu_buddy_alloc_blocks(struct gpu_buddy *mm,
+ u64 start, u64 end, u64 size,
+ u64 min_page_size,
+ struct list_head *blocks,
+ unsigned long flags);
+
+int gpu_buddy_block_trim(struct gpu_buddy *mm,
+ u64 *start,
+ u64 new_size,
+ struct list_head *blocks);
+
+void gpu_buddy_reset_clear(struct gpu_buddy *mm, bool is_clear);
+
+void gpu_buddy_free_block(struct gpu_buddy *mm, struct gpu_buddy_block *block);
+
+void gpu_buddy_free_list(struct gpu_buddy *mm,
+ struct list_head *objects,
+ unsigned int flags);
+
+void gpu_buddy_print(struct gpu_buddy *mm);
+void gpu_buddy_block_print(struct gpu_buddy *mm,
+ struct gpu_buddy_block *block);
+#endif
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 511/602] gpu/buddy: bail out of try_harder when alignment cannot be honoured
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (509 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 510/602] gpu: Move DRM buddy allocator one level up (part two) Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 512/602] NFSD: pass nfsd_file to nfsd_iter_read() Greg Kroah-Hartman
` (94 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Christian König, Matthew Auld,
Timur Kristóf, John Olender, Arunpravin Paneer Selvam,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com>
[ Upstream commit 56bc6384314fb9ae98975fb2af8b143097ede3dc ]
The try_harder contiguous fallback could return a range whose start
offset did not match the caller's min_block_size. When a candidate's
start is misaligned, realign it: free the misaligned run and reallocate
exactly @size at the next lower min_block_size boundary. This keeps the
returned size unchanged with no surplus to trim, and rejects the request
only when no aligned candidate fits.
v2: align misaligned candidates down to min_block_size instead of
bailing out, for both the RHS and LHS paths (Matthew).
Fixes: 0a1844bf0b53 ("drm/buddy: Improve contiguous memory allocation")
Suggested-by: Christian König <christian.koenig@amd.com>
Cc: Matthew Auld <matthew.auld@intel.com>
Cc: Christian König <christian.koenig@amd.com>
Cc: Timur Kristóf <timur.kristof@gmail.com>
Cc: stable@vger.kernel.org
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
Tested-by: John Olender <john.olender@gmail.com>
Signed-off-by: Arunpravin Paneer Selvam <Arunpravin.PaneerSelvam@amd.com>
Link: https://patch.msgid.link/20260709131050.1022759-1-Arunpravin.PaneerSelvam@amd.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/buddy.c | 65 ++++++++++++++++++++++++++++++++++++----------------
1 file changed, 45 insertions(+), 20 deletions(-)
--- a/drivers/gpu/buddy.c
+++ b/drivers/gpu/buddy.c
@@ -901,22 +901,30 @@ static int __gpu_buddy_alloc_range(struc
blocks, total_allocated_on_err);
}
+static int __alloc_contig_aligned_retry(struct gpu_buddy *mm,
+ u64 unaligned_offset,
+ u64 size,
+ u64 min_block_size,
+ struct list_head *blocks)
+{
+ u64 aligned_offset = round_down(unaligned_offset, min_block_size);
+
+ return __gpu_buddy_alloc_range(mm, aligned_offset, size, NULL, blocks);
+}
+
static int __alloc_contig_try_harder(struct gpu_buddy *mm,
u64 size,
u64 min_block_size,
struct list_head *blocks)
{
- u64 rhs_offset, lhs_offset, lhs_size, filled;
+ u64 rhs_offset, lhs_offset, filled;
struct gpu_buddy_block *block;
unsigned int tree, order;
- LIST_HEAD(blocks_lhs);
- unsigned long pages;
u64 modify_size;
int err;
modify_size = rounddown_pow_of_two(size);
- pages = modify_size >> ilog2(mm->chunk_size);
- order = fls(pages) - 1;
+ order = ilog2(modify_size) - ilog2(mm->chunk_size);
if (order == 0)
return -ENOSPC;
@@ -932,31 +940,48 @@ static int __alloc_contig_try_harder(str
while (iter) {
block = rbtree_get_free_block(iter);
- /* Allocate blocks traversing RHS */
rhs_offset = gpu_buddy_block_offset(block);
+
+ /* Allocate blocks traversing RHS */
err = __gpu_buddy_alloc_range(mm, rhs_offset, size,
&filled, blocks);
- if (!err || err != -ENOSPC)
+ if (err && err != -ENOSPC)
return err;
-
- lhs_size = max((size - filled), min_block_size);
- if (!IS_ALIGNED(lhs_size, min_block_size))
- lhs_size = round_up(lhs_size, min_block_size);
-
- /* Allocate blocks traversing LHS */
- lhs_offset = gpu_buddy_block_offset(block) - lhs_size;
- err = __gpu_buddy_alloc_range(mm, lhs_offset, lhs_size,
- NULL, &blocks_lhs);
+ if (!err && IS_ALIGNED(rhs_offset, min_block_size))
+ return 0;
if (!err) {
- list_splice(&blocks_lhs, blocks);
+ /* Allocate the unaligned RHS offset using round_down */
+ gpu_buddy_free_list_internal(mm, blocks);
+ err = __alloc_contig_aligned_retry(mm, rhs_offset,
+ size,
+ min_block_size,
+ blocks);
+ if (!err)
+ return 0;
+ if (err != -ENOSPC) {
+ gpu_buddy_free_list_internal(mm, blocks);
+ return err;
+ }
+ goto next;
+ }
+
+ if (size - filled > rhs_offset)
+ goto next;
+
+ lhs_offset = rhs_offset - (size - filled);
+
+ /* Allocate the unaligned LHS offset using round_down */
+ gpu_buddy_free_list_internal(mm, blocks);
+ err = __alloc_contig_aligned_retry(mm, lhs_offset, size,
+ min_block_size, blocks);
+ if (!err)
return 0;
- } else if (err != -ENOSPC) {
+ if (err != -ENOSPC) {
gpu_buddy_free_list_internal(mm, blocks);
return err;
}
- /* Free blocks for the next iteration */
+next:
gpu_buddy_free_list_internal(mm, blocks);
-
iter = rb_prev(iter);
}
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 512/602] NFSD: pass nfsd_file to nfsd_iter_read()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (510 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 511/602] gpu/buddy: bail out of try_harder when alignment cannot be honoured Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 513/602] sunrpc: allocate a separate bvec array for socket sends Greg Kroah-Hartman
` (93 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Mike Snitzer, Jeff Layton, NeilBrown,
Christoph Hellwig, Chuck Lever, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mike Snitzer <snitzer@kernel.org>
[ Upstream commit 803bc849f0039291f546ba0e2237faebeb5c073e ]
Prepare for nfsd_iter_read() to use the DIO alignment stored in
nfsd_file by passing the nfsd_file to nfsd_iter_read() rather than
just the file which is associaed with the nfsd_file.
This means nfsd4_encode_readv() now also needs the nfsd_file rather
than the file. Instead of changing the file arg to be the nfsd_file,
we discard the file arg as the nfsd_file (and indeed the file) is
already available via the "read" argument.
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: NeilBrown <neil@brown.name>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Stable-dep-of: 18c1cc698861 ("SUNRPC: Return an error from xdr_buf_to_bvec() on overflow")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/nfsd/nfs4xdr.c | 8 ++++----
fs/nfsd/vfs.c | 7 ++++---
fs/nfsd/vfs.h | 2 +-
3 files changed, 9 insertions(+), 8 deletions(-)
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -4384,7 +4384,7 @@ out_err:
static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp,
struct nfsd4_read *read,
- struct file *file, unsigned long maxcount)
+ unsigned long maxcount)
{
struct xdr_stream *xdr = resp->xdr;
unsigned int base = xdr->buf->page_len & ~PAGE_MASK;
@@ -4395,7 +4395,7 @@ static __be32 nfsd4_encode_readv(struct
if (xdr_reserve_space_vec(xdr, maxcount) < 0)
return nfserr_resource;
- nfserr = nfsd_iter_read(resp->rqstp, read->rd_fhp, file,
+ nfserr = nfsd_iter_read(resp->rqstp, read->rd_fhp, read->rd_nf,
read->rd_offset, &maxcount, base,
&read->rd_eof);
read->rd_length = maxcount;
@@ -4444,7 +4444,7 @@ nfsd4_encode_read(struct nfsd4_compoundr
if (file->f_op->splice_read && splice_ok)
nfserr = nfsd4_encode_splice_read(resp, read, file, maxcount);
else
- nfserr = nfsd4_encode_readv(resp, read, file, maxcount);
+ nfserr = nfsd4_encode_readv(resp, read, maxcount);
if (nfserr) {
xdr_truncate_encode(xdr, starting_len);
return nfserr;
@@ -5311,7 +5311,7 @@ nfsd4_encode_read_plus_data(struct nfsd4
if (file->f_op->splice_read && splice_ok)
nfserr = nfsd4_encode_splice_read(resp, read, file, maxcount);
else
- nfserr = nfsd4_encode_readv(resp, read, file, maxcount);
+ nfserr = nfsd4_encode_readv(resp, read, maxcount);
if (nfserr)
return nfserr;
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1067,7 +1067,7 @@ __be32 nfsd_splice_read(struct svc_rqst
* nfsd_iter_read - Perform a VFS read using an iterator
* @rqstp: RPC transaction context
* @fhp: file handle of file to be read
- * @file: opened struct file of file to be read
+ * @nf: opened struct nfsd_file of file to be read
* @offset: starting byte offset
* @count: IN: requested number of bytes; OUT: number of bytes read
* @base: offset in first page of read buffer
@@ -1080,9 +1080,10 @@ __be32 nfsd_splice_read(struct svc_rqst
* returned.
*/
__be32 nfsd_iter_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
- struct file *file, loff_t offset, unsigned long *count,
+ struct nfsd_file *nf, loff_t offset, unsigned long *count,
unsigned int base, u32 *eof)
{
+ struct file *file = nf->nf_file;
unsigned long v, total;
struct iov_iter iter;
loff_t ppos = offset;
@@ -1283,7 +1284,7 @@ __be32 nfsd_read(struct svc_rqst *rqstp,
if (file->f_op->splice_read && nfsd_read_splice_ok(rqstp))
err = nfsd_splice_read(rqstp, fhp, file, offset, count, eof);
else
- err = nfsd_iter_read(rqstp, fhp, file, offset, count, 0, eof);
+ err = nfsd_iter_read(rqstp, fhp, nf, offset, count, 0, eof);
nfsd_file_put(nf);
trace_nfsd_read_done(rqstp, fhp, offset, *count);
--- a/fs/nfsd/vfs.h
+++ b/fs/nfsd/vfs.h
@@ -122,7 +122,7 @@ __be32 nfsd_splice_read(struct svc_rqst
unsigned long *count,
u32 *eof);
__be32 nfsd_iter_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
- struct file *file, loff_t offset,
+ struct nfsd_file *nf, loff_t offset,
unsigned long *count, unsigned int base,
u32 *eof);
bool nfsd_read_splice_ok(struct svc_rqst *rqstp);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 513/602] sunrpc: allocate a separate bvec array for socket sends
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (511 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 512/602] NFSD: pass nfsd_file to nfsd_iter_read() Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 514/602] SUNRPC: Add helpers to convert xdr_buf byte ranges to scatterlists Greg Kroah-Hartman
` (92 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jeff Layton, NeilBrown, Chuck Lever,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Layton <jlayton@kernel.org>
[ Upstream commit 6b3b697d65d46a0f640216a3f6c72856c159c567 ]
svc_tcp_sendmsg() calls xdr_buf_to_bvec() with the second slot of
rq_bvec as the start, but doesn't reduce the array length by one, which
could lead to an array overrun. Also, rq_bvec is always rq_maxpages in
length, which can be too short in some cases, since the TCP record
marker consumes a slot.
Fix both problems by adding a separate bvec array to the svc_sock that
is specifically for sending. For TCP, make this array one slot longer
than rq_maxpages, to account for the record marker. For UDP, only
allocate as large an array as we need since it's limited to 64k of
payload.
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: NeilBrown <neil@brown.name>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Stable-dep-of: 18c1cc698861 ("SUNRPC: Return an error from xdr_buf_to_bvec() on overflow")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/sunrpc/svcsock.h | 3 +++
net/sunrpc/svcsock.c | 37 ++++++++++++++++++++++++++++---------
2 files changed, 31 insertions(+), 9 deletions(-)
--- a/include/linux/sunrpc/svcsock.h
+++ b/include/linux/sunrpc/svcsock.h
@@ -26,6 +26,9 @@ struct svc_sock {
void (*sk_odata)(struct sock *);
void (*sk_owspace)(struct sock *);
+ /* For sends (protected by xpt_mutex) */
+ struct bio_vec *sk_bvec;
+
/* private TCP part */
/* On-the-wire fragment header: */
__be32 sk_marker;
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -68,6 +68,17 @@
#define RPCDBG_FACILITY RPCDBG_SVCXPRT
+/*
+ * For UDP:
+ * 1 for header page
+ * enough pages for RPCSVC_MAXPAYLOAD_UDP
+ * 1 in case payload is not aligned
+ * 1 for tail page
+ */
+enum {
+ SUNRPC_MAX_UDP_SENDPAGES = 1 + RPCSVC_MAXPAYLOAD_UDP / PAGE_SIZE + 1 + 1
+};
+
/* To-do: to avoid tying up an nfsd thread while waiting for a
* handshake request, the request could instead be deferred.
*/
@@ -750,15 +761,14 @@ static int svc_udp_sendto(struct svc_rqs
if (svc_xprt_is_dead(xprt))
goto out_notconn;
- count = xdr_buf_to_bvec(rqstp->rq_bvec,
- ARRAY_SIZE(rqstp->rq_bvec), xdr);
+ count = xdr_buf_to_bvec(svsk->sk_bvec, SUNRPC_MAX_UDP_SENDPAGES, xdr);
- iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, rqstp->rq_bvec,
+ iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, svsk->sk_bvec,
count, rqstp->rq_res.len);
err = sock_sendmsg(svsk->sk_sock, &msg);
if (err == -ECONNREFUSED) {
/* ICMP error on earlier request. */
- iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, rqstp->rq_bvec,
+ iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, svsk->sk_bvec,
count, rqstp->rq_res.len);
err = sock_sendmsg(svsk->sk_sock, &msg);
}
@@ -1248,19 +1258,19 @@ static int svc_tcp_sendmsg(struct svc_so
*sentp = 0;
/* The stream record marker is copied into a temporary page
- * fragment buffer so that it can be included in rq_bvec.
+ * fragment buffer so that it can be included in sk_bvec.
*/
buf = page_frag_alloc(&svsk->sk_frag_cache, sizeof(marker),
GFP_KERNEL);
if (!buf)
return -ENOMEM;
memcpy(buf, &marker, sizeof(marker));
- bvec_set_virt(rqstp->rq_bvec, buf, sizeof(marker));
+ bvec_set_virt(svsk->sk_bvec, buf, sizeof(marker));
- count = xdr_buf_to_bvec(rqstp->rq_bvec + 1,
- ARRAY_SIZE(rqstp->rq_bvec) - 1, &rqstp->rq_res);
+ count = xdr_buf_to_bvec(svsk->sk_bvec + 1, RPCSVC_MAXPAGES,
+ &rqstp->rq_res);
- iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, rqstp->rq_bvec,
+ iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, svsk->sk_bvec,
1 + count, sizeof(marker) + rqstp->rq_res.len);
ret = sock_sendmsg(svsk->sk_sock, &msg);
page_frag_free(buf);
@@ -1423,6 +1433,13 @@ static struct svc_sock *svc_setup_socket
if (!svsk)
return ERR_PTR(-ENOMEM);
+ svsk->sk_bvec = kcalloc(RPCSVC_MAXPAGES + 1, sizeof(*svsk->sk_bvec),
+ GFP_KERNEL);
+ if (!svsk->sk_bvec) {
+ kfree(svsk);
+ return ERR_PTR(-ENOMEM);
+ }
+
inet = sock->sk;
if (pmap_register) {
@@ -1432,6 +1449,7 @@ static struct svc_sock *svc_setup_socket
inet->sk_protocol,
ntohs(inet_sk(inet)->inet_sport));
if (err < 0) {
+ kfree(svsk->sk_bvec);
kfree(svsk);
return ERR_PTR(err);
}
@@ -1651,5 +1669,6 @@ static void svc_sock_free(struct svc_xpr
if (pfc->va)
__page_frag_cache_drain(virt_to_head_page(pfc->va),
pfc->pagecnt_bias);
+ kfree(svsk->sk_bvec);
kfree(svsk);
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 514/602] SUNRPC: Add helpers to convert xdr_buf byte ranges to scatterlists
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (512 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 513/602] sunrpc: allocate a separate bvec array for socket sends Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 515/602] SUNRPC: Return an error from xdr_buf_to_bvec() on overflow Greg Kroah-Hartman
` (91 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jeff Layton, Anna Schumaker,
Chuck Lever, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <chuck.lever@oracle.com>
[ Upstream commit e9be933959b581effd426f93b86654f5fbf0c574 ]
The crypto/krb5 library accepts data in scatterlist form, but
the GSS-API layer presents RPC payloads as struct xdr_buf.
Bridge that gap with a pair of helper functions:
xdr_buf_to_sg() - populate a caller-supplied scatterlist
array from a byte range
xdr_buf_to_sg_alloc() - populate a caller-supplied inline
scatterlist, chaining to a heap-
allocated overflow for large payloads
The inline array (typically stack-allocated at eight entries)
covers the common case of small RPCs with no heap allocation
on the encrypt/decrypt path. Only buffers spanning many pages
incur a kmalloc for the chained extension.
The segment-walking logic follows the same head, page array,
tail traversal as xdr_process_buf(), but populates a
scatterlist directly rather than invoking a per-segment
callback. sg_next() traversal makes the walker safe for
chained scatterlists. Once subsequent patches reroute all
per-message crypto operations through crypto/krb5,
xdr_process_buf() loses its last callers and is removed.
Assisted-by: Claude:claude-opus-4-6
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Acked-by: Anna Schumaker <anna.schumaker@hammerspace.com>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Stable-dep-of: 18c1cc698861 ("SUNRPC: Return an error from xdr_buf_to_bvec() on overflow")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/sunrpc/xdr.h | 15 +++
net/sunrpc/xdr.c | 199 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 214 insertions(+)
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -141,6 +141,21 @@ int xdr_alloc_bvec(struct xdr_buf *buf,
void xdr_free_bvec(struct xdr_buf *buf);
unsigned int xdr_buf_to_bvec(struct bio_vec *bvec, unsigned int bvec_size,
const struct xdr_buf *xdr);
+int xdr_buf_to_sg(const struct xdr_buf *buf, unsigned int offset,
+ unsigned int len, struct scatterlist *sg, unsigned int nsg);
+int xdr_buf_to_sg_alloc(const struct xdr_buf *buf, unsigned int offset,
+ unsigned int len, struct scatterlist *sg_head,
+ unsigned int sg_head_nents,
+ struct scatterlist **sg_overflow, gfp_t gfp);
+
+/*
+ * Inline scatterlist entries for xdr_buf_to_sg_alloc(). Sized to cover the
+ * head kvec, tail kvec, and a few page fragments without any heap allocation.
+ */
+enum {
+ XDR_BUF_TO_SG_NENTS = 8,
+};
+
static inline __be32 *xdr_encode_array(__be32 *p, const void *s, unsigned int len)
{
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -219,6 +219,205 @@ bvec_overflow:
}
/**
+ * xdr_buf_to_sg - Populate a scatterlist from an xdr_buf range
+ * @buf: xdr_buf to map
+ * @offset: starting byte offset within @buf
+ * @len: number of bytes to cover
+ * @sg: scatterlist array initialized with sg_init_table()
+ * @nsg: number of entries available in @sg
+ *
+ * @sg is traversed with sg_next(), so callers may pass a list
+ * assembled with sg_chain().
+ *
+ * Return: on success, the number of scatterlist entries used; the
+ * last used entry is marked with sg_mark_end(). On failure, a
+ * negative errno.
+ */
+int xdr_buf_to_sg(const struct xdr_buf *buf, unsigned int offset,
+ unsigned int len, struct scatterlist *sg, unsigned int nsg)
+{
+ unsigned int page_len, thislen, page_offset;
+ struct scatterlist *cur = sg, *prev = NULL;
+ int nents = 0;
+ int i;
+
+ if (len == 0)
+ return 0;
+
+ if (offset >= buf->head[0].iov_len) {
+ offset -= buf->head[0].iov_len;
+ } else {
+ thislen = min_t(unsigned int,
+ buf->head[0].iov_len - offset, len);
+ if (nents >= nsg)
+ return -ENOSPC;
+ sg_set_buf(cur, buf->head[0].iov_base + offset,
+ thislen);
+ prev = cur;
+ cur = sg_next(cur);
+ nents++;
+ len -= thislen;
+ offset = 0;
+ }
+ if (len == 0)
+ goto done;
+
+ if (offset >= buf->page_len) {
+ offset -= buf->page_len;
+ } else {
+ page_len = min(buf->page_len - offset, len);
+ len -= page_len;
+ page_offset = (offset + buf->page_base) & (PAGE_SIZE - 1);
+ i = (offset + buf->page_base) >> PAGE_SHIFT;
+ thislen = PAGE_SIZE - page_offset;
+ do {
+ if (thislen > page_len)
+ thislen = page_len;
+ if (nents >= nsg)
+ return -ENOSPC;
+ sg_set_page(cur, buf->pages[i],
+ thislen, page_offset);
+ prev = cur;
+ cur = sg_next(cur);
+ nents++;
+ page_len -= thislen;
+ i++;
+ page_offset = 0;
+ thislen = PAGE_SIZE;
+ } while (page_len != 0);
+ offset = 0;
+ }
+ if (len == 0)
+ goto done;
+
+ if (offset < buf->tail[0].iov_len) {
+ thislen = min_t(unsigned int,
+ buf->tail[0].iov_len - offset, len);
+ if (nents >= nsg)
+ return -ENOSPC;
+ sg_set_buf(cur, buf->tail[0].iov_base + offset,
+ thislen);
+ prev = cur;
+ nents++;
+ len -= thislen;
+ }
+ if (len != 0)
+ return -EINVAL;
+
+done:
+ if (prev)
+ sg_mark_end(prev);
+ return nents;
+}
+EXPORT_SYMBOL_GPL(xdr_buf_to_sg);
+
+/*
+ * Count the scatterlist entries needed to cover [offset, offset + len)
+ * within @buf. Mirrors the walk in xdr_buf_to_sg() so the caller can
+ * size an allocation that matches the requested sub-range rather than
+ * the full xdr_buf.
+ */
+static unsigned int xdr_buf_sg_nents(const struct xdr_buf *buf,
+ unsigned int offset, unsigned int len)
+{
+ unsigned int nsg = 0, thislen, page_offset;
+
+ if (len == 0)
+ return 0;
+
+ if (offset < buf->head[0].iov_len) {
+ thislen = min_t(unsigned int,
+ buf->head[0].iov_len - offset, len);
+ nsg++;
+ len -= thislen;
+ offset = 0;
+ } else {
+ offset -= buf->head[0].iov_len;
+ }
+ if (len == 0)
+ return nsg;
+
+ if (offset < buf->page_len) {
+ thislen = min(buf->page_len - offset, len);
+ page_offset = (offset + buf->page_base) & (PAGE_SIZE - 1);
+ nsg += DIV_ROUND_UP(page_offset + thislen, PAGE_SIZE);
+ len -= thislen;
+ offset = 0;
+ } else {
+ offset -= buf->page_len;
+ }
+ if (len == 0)
+ return nsg;
+
+ if (offset < buf->tail[0].iov_len)
+ nsg++;
+ return nsg;
+}
+
+/**
+ * xdr_buf_to_sg_alloc - Populate a scatterlist for an xdr_buf range
+ * @buf: xdr_buf to map
+ * @offset: starting byte offset within @buf
+ * @len: number of bytes to cover
+ * @sg_head: caller-provided scatterlist array (typically stack-allocated)
+ * @sg_head_nents: number of entries in @sg_head
+ * @sg_overflow: OUT: chained extension, or NULL when @sg_head sufficed
+ * @gfp: memory allocation flags for overflow
+ *
+ * Populates @sg_head directly when the xdr_buf fits. When more
+ * entries are needed, an overflow scatterlist is allocated and
+ * chained from @sg_head so that the result is traversable with
+ * sg_next().
+ *
+ * Return: on success, the number of populated scatterlist entries
+ * (counting only data entries, not chain entries). @sg_head is
+ * the head of the resulting list. Caller must kfree @sg_overflow
+ * when done. On failure, a negative errno.
+ */
+int xdr_buf_to_sg_alloc(const struct xdr_buf *buf, unsigned int offset,
+ unsigned int len, struct scatterlist *sg_head,
+ unsigned int sg_head_nents,
+ struct scatterlist **sg_overflow, gfp_t gfp)
+{
+ unsigned int nsg;
+ int ret;
+
+ *sg_overflow = NULL;
+ if (len == 0)
+ return 0;
+
+ nsg = xdr_buf_sg_nents(buf, offset, len);
+ if (nsg == 0)
+ return -EINVAL;
+
+ if (nsg <= sg_head_nents) {
+ sg_init_table(sg_head, nsg);
+ } else {
+ /* +1 replaces the slot sg_chain() consumes as the link. */
+ unsigned int overflow_nents = nsg - sg_head_nents + 1;
+ struct scatterlist *overflow;
+
+ overflow = kmalloc_array(overflow_nents, sizeof(*overflow),
+ gfp);
+ if (!overflow)
+ return -ENOMEM;
+
+ sg_init_table(sg_head, sg_head_nents);
+ sg_init_table(overflow, overflow_nents);
+ sg_chain(sg_head, sg_head_nents, overflow);
+ *sg_overflow = overflow;
+ }
+
+ ret = xdr_buf_to_sg(buf, offset, len, sg_head, nsg);
+ if (ret < 0) {
+ kfree(*sg_overflow);
+ *sg_overflow = NULL;
+ }
+ return ret;
+}
+EXPORT_SYMBOL_GPL(xdr_buf_to_sg_alloc);
+
+/**
* xdr_inline_pages - Prepare receive buffer for a large reply
* @xdr: xdr_buf into which reply will be placed
* @offset: expected offset where data payload will start, in bytes
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 515/602] SUNRPC: Return an error from xdr_buf_to_bvec() on overflow
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (513 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 514/602] SUNRPC: Add helpers to convert xdr_buf byte ranges to scatterlists Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 516/602] remoteproc: xlnx: Check remote core state Greg Kroah-Hartman
` (90 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Chris Mason, Jeff Layton,
Chuck Lever, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <chuck.lever@oracle.com>
[ Upstream commit 18c1cc69886192e33536498289d26dba6894e3d5 ]
xdr_buf_to_bvec() returns a slot count even when the caller's bvec
budget is exhausted partway through the xdr_buf. Callers feed that
count into iov_iter_bvec() and continue as if the conversion had
succeeded, silently sending or writing fewer bytes than the data
length declares. For an NFS WRITE the server reports the truncated
transfer to the client as full success.
The overflow represents an internal invariant violation: a higher
layer reserved a bvec budget too small for the xdr_buf it then
asked the encoder to convert. That is a server-side fault, not a
media I/O failure and not a malformed client argument.
Change xdr_buf_to_bvec() to return a signed int and have the
overflow label return -ESERVERFAULT. Update the three callers to
detect the negative return and fail the request: nfsd_vfs_write()
folds the error into host_err, which nfserrno() translates to
nfserr_serverfault for the WRITE reply; svc_udp_sendto() and
svc_tcp_sendmsg() propagate the error out of the send path.
Reported-by: Chris Mason <clm@meta.com>
Fixes: 2eb2b9358181 ("SUNRPC: Convert svc_tcp_sendmsg to use bio_vecs directly")
Cc: stable@vger.kernel.org
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/sunrpc/xdr.h | 4 ++--
net/sunrpc/svcsock.c | 14 ++++++++++++--
net/sunrpc/xdr.c | 11 ++++++-----
3 files changed, 20 insertions(+), 9 deletions(-)
--- a/include/linux/sunrpc/xdr.h
+++ b/include/linux/sunrpc/xdr.h
@@ -139,8 +139,8 @@ void xdr_terminate_string(const struct x
size_t xdr_buf_pagecount(const struct xdr_buf *buf);
int xdr_alloc_bvec(struct xdr_buf *buf, gfp_t gfp);
void xdr_free_bvec(struct xdr_buf *buf);
-unsigned int xdr_buf_to_bvec(struct bio_vec *bvec, unsigned int bvec_size,
- const struct xdr_buf *xdr);
+int xdr_buf_to_bvec(struct bio_vec *bvec, unsigned int bvec_size,
+ const struct xdr_buf *xdr);
int xdr_buf_to_sg(const struct xdr_buf *buf, unsigned int offset,
unsigned int len, struct scatterlist *sg, unsigned int nsg);
int xdr_buf_to_sg_alloc(const struct xdr_buf *buf, unsigned int offset,
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -748,7 +748,7 @@ static int svc_udp_sendto(struct svc_rqs
.msg_flags = MSG_SPLICE_PAGES,
.msg_controllen = sizeof(buffer),
};
- unsigned int count;
+ int count;
int err;
svc_udp_release_ctxt(xprt, rqstp->rq_xprt_ctxt);
@@ -762,6 +762,10 @@ static int svc_udp_sendto(struct svc_rqs
goto out_notconn;
count = xdr_buf_to_bvec(svsk->sk_bvec, SUNRPC_MAX_UDP_SENDPAGES, xdr);
+ if (count < 0) {
+ err = count;
+ goto out_trace;
+ }
iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, svsk->sk_bvec,
count, rqstp->rq_res.len);
@@ -773,6 +777,7 @@ static int svc_udp_sendto(struct svc_rqs
err = sock_sendmsg(svsk->sk_sock, &msg);
}
+out_trace:
trace_svcsock_udp_send(xprt, err);
mutex_unlock(&xprt->xpt_mutex);
@@ -1251,7 +1256,7 @@ static int svc_tcp_sendmsg(struct svc_so
struct msghdr msg = {
.msg_flags = MSG_SPLICE_PAGES,
};
- unsigned int count;
+ int count;
void *buf;
int ret;
@@ -1269,10 +1274,15 @@ static int svc_tcp_sendmsg(struct svc_so
count = xdr_buf_to_bvec(svsk->sk_bvec + 1, RPCSVC_MAXPAGES,
&rqstp->rq_res);
+ if (count < 0) {
+ ret = count;
+ goto out;
+ }
iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, svsk->sk_bvec,
1 + count, sizeof(marker) + rqstp->rq_res.len);
ret = sock_sendmsg(svsk->sk_sock, &msg);
+out:
page_frag_free(buf);
if (ret < 0)
return ret;
--- a/net/sunrpc/xdr.c
+++ b/net/sunrpc/xdr.c
@@ -167,13 +167,14 @@ xdr_free_bvec(struct xdr_buf *buf)
/**
* xdr_buf_to_bvec - Copy components of an xdr_buf into a bio_vec array
* @bvec: bio_vec array to populate
- * @bvec_size: element count of @bio_vec
+ * @bvec_size: element count of @bvec
* @xdr: xdr_buf to be copied
*
- * Returns the number of entries consumed in @bvec.
+ * Returns the number of entries consumed in @bvec on success, or
+ * -ESERVERFAULT when @xdr does not fit within @bvec_size entries.
*/
-unsigned int xdr_buf_to_bvec(struct bio_vec *bvec, unsigned int bvec_size,
- const struct xdr_buf *xdr)
+int xdr_buf_to_bvec(struct bio_vec *bvec, unsigned int bvec_size,
+ const struct xdr_buf *xdr)
{
const struct kvec *head = xdr->head;
const struct kvec *tail = xdr->tail;
@@ -215,7 +216,7 @@ unsigned int xdr_buf_to_bvec(struct bio_
bvec_overflow:
pr_warn_once("%s: bio_vec array overflow\n", __func__);
- return count;
+ return -ESERVERFAULT;
}
/**
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 516/602] remoteproc: xlnx: Check remote core state
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (514 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 515/602] SUNRPC: Return an error from xdr_buf_to_bvec() on overflow Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 517/602] mm/hugetlb: fix hugetlb cgroup rsvd charge/uncharge mismatch Greg Kroah-Hartman
` (89 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Tanmay Shah, Beleswar Padhi,
Michal Simek, Mathieu Poirier, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tanmay Shah <tanmay.shah@amd.com>
[ Upstream commit a48df51d23138388900995add2854cda4aa68e55 ]
The remote state is set to RPROC_DETACHED if the resource table is found
in the memory. However, this can be wrong if the remote is not started,
but firmware is still loaded in the memory. Use PM_GET_NODE_STATUS call
to the firmware to request the state of the RPU node. If the RPU is
actually out of reset and running, only then move the remote state to
RPROC_DETACHED, otherwise keep the remote state to RPROC_OFFLINE.
Signed-off-by: Tanmay Shah <tanmay.shah@amd.com>
Fixes: bca4b02ef92e ("remoteproc: xlnx: Add attach detach support")
Reviewed-by: Beleswar Padhi <b-padhi@ti.com>
Acked-by: Michal Simek <michal.simek@amd.com>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20260428221855.313752-1-tanmay.shah@amd.com
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
[ replaced the unavailable zynqmp_pm_get_node_status() helper with a direct zynqmp_pm_invoke_fn() call and exported it for modular builds. ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/firmware/xilinx/zynqmp.c | 1
drivers/remoteproc/xlnx_r5_remoteproc.c | 50 +++++++++++++++++++++++++-------
include/linux/firmware/xlnx-zynqmp.h | 13 ++++++++
3 files changed, 54 insertions(+), 10 deletions(-)
--- a/drivers/firmware/xilinx/zynqmp.c
+++ b/drivers/firmware/xilinx/zynqmp.c
@@ -386,6 +386,7 @@ int zynqmp_pm_invoke_fn(u32 pm_api_id, u
return do_fw_call(ret_payload, 8, smc_arg[0], smc_arg[1], smc_arg[2], smc_arg[3],
smc_arg[4], smc_arg[5], smc_arg[6], smc_arg[7]);
}
+EXPORT_SYMBOL_GPL(zynqmp_pm_invoke_fn);
static u32 pm_api_version;
static u32 pm_tz_version;
--- a/drivers/remoteproc/xlnx_r5_remoteproc.c
+++ b/drivers/remoteproc/xlnx_r5_remoteproc.c
@@ -927,16 +927,6 @@ static struct zynqmp_r5_core *zynqmp_r5_
goto free_rproc;
}
- /*
- * If firmware is already available in the memory then move rproc state
- * to DETACHED. Firmware can be preloaded via debugger or by any other
- * agent (processors) in the system.
- * If firmware isn't available in the memory and resource table isn't
- * found, then rproc state remains OFFLINE.
- */
- if (!zynqmp_r5_get_rsc_table_va(r5_core))
- r5_rproc->state = RPROC_DETACHED;
-
r5_core->rproc = r5_rproc;
return r5_core;
@@ -1189,6 +1179,7 @@ static int zynqmp_r5_core_init(struct zy
{
struct device *dev = cluster->dev;
struct zynqmp_r5_core *r5_core;
+ u32 payload[PAYLOAD_ARG_CNT];
int ret = -EINVAL, i;
r5_core = cluster->r5_cores[0];
@@ -1234,6 +1225,45 @@ static int zynqmp_r5_core_init(struct zy
ret = zynqmp_r5_get_sram_banks(r5_core);
if (ret)
return ret;
+
+ /*
+ * It is possible that firmware is loaded into the memory, but
+ * RPU (remote) is not running. In such case, RPU state will be
+ * moved to RPROC_DETACHED wrongfully. To avoid it first make
+ * sure RPU is power-on and out of reset before parsing for the
+ * resource table.
+ */
+ ret = zynqmp_pm_feature(PM_GET_NODE_STATUS);
+ if (ret < PM_API_VERSION_2)
+ ret = -EOPNOTSUPP;
+ else
+ ret = zynqmp_pm_invoke_fn(PM_GET_NODE_STATUS, payload, 1,
+ r5_core->pm_domain_id);
+ if (ret) {
+ dev_warn(r5_core->dev,
+ "failed to get rpu node status, err %d\n", ret);
+ continue;
+ }
+
+ /*
+ * If RPU state is power on and out of reset i.e. running, then
+ * assign RPROC_DETACHED state. If the RPU is not out of reset
+ * then do not attempt to attach to the remote processor.
+ */
+ if (payload[1] == PM_NODE_RUNNING) {
+ /*
+ * Not all the firmware that is running on the remote
+ * core is expected to have the resource table. The
+ * firmware might not use RPMsg at all, and in that case
+ * resource table becomes irrelevant. However, we still
+ * need to make sure that running core is not reported
+ * as offline. so do not decide remote core state based
+ * on the resource table availability
+ */
+ if (zynqmp_r5_get_rsc_table_va(r5_core))
+ dev_dbg(r5_core->dev, "rsc tbl not found\n");
+ r5_core->rproc->state = RPROC_DETACHED;
+ }
}
return 0;
--- a/include/linux/firmware/xlnx-zynqmp.h
+++ b/include/linux/firmware/xlnx-zynqmp.h
@@ -143,6 +143,7 @@ enum pm_api_cb_id {
enum pm_api_id {
PM_API_FEATURES = 0,
PM_GET_API_VERSION = 1,
+ PM_GET_NODE_STATUS = 3,
PM_REGISTER_NOTIFIER = 5,
PM_FORCE_POWERDOWN = 8,
PM_REQUEST_WAKEUP = 10,
@@ -519,6 +520,18 @@ enum pm_gem_config_type {
};
/**
+ * enum pm_node_status - Device node status provided by xilpm fw
+ * @PM_NODE_UNUSED: Device is not used
+ * @PM_NODE_RUNNING: Device is power-on and out of reset
+ * @PM_NODE_HALT: Device is power-on but in the reset state
+ */
+enum pm_node_status {
+ PM_NODE_UNUSED = 0,
+ PM_NODE_RUNNING = 1,
+ PM_NODE_HALT = 12,
+};
+
+/**
* struct zynqmp_pm_query_data - PM query data
* @qid: query ID
* @arg1: Argument 1 of query data
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 517/602] mm/hugetlb: fix hugetlb cgroup rsvd charge/uncharge mismatch
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (515 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 516/602] remoteproc: xlnx: Check remote core state Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 518/602] mm/sparse-vmemmap: fix vmemmap accounting underflow Greg Kroah-Hartman
` (88 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, syzbot+226c1f947186f8fef796,
Deepanshu Kartikey, Muchun Song, David Hildenbrand,
Oscar Salvador, Mina Almasry, Andrew Morton, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Deepanshu Kartikey <kartikey406@gmail.com>
[ Upstream commit 15807d0ddde37407af72859426b654f3d1972b00 ]
In alloc_hugetlb_folio(), a single h_cg pointer is used for both the rsvd
and non-rsvd hugetlb cgroup charges. When map_chg is set,
hugetlb_cgroup_charge_cgroup_rsvd() stores the charged cgroup in h_cg, but
the immediately following hugetlb_cgroup_charge_cgroup() overwrites h_cg
with the non-rsvd cgroup pointer.
As a result, hugetlb_cgroup_commit_charge_rsvd() stores the wrong
(non-rsvd) cgroup pointer into the folio's rsvd slot.
When the folio is later freed, free_huge_folio() unconditionally calls
both hugetlb_cgroup_uncharge_folio() and
hugetlb_cgroup_uncharge_folio_rsvd(). The rsvd uncharge reads back the
wrong cgroup from the folio and decrements a counter that was never
charged for that cgroup, causing a page_counter underflow:
page_counter underflow: -512 nr_pages=512
WARNING: mm/page_counter.c:61 at page_counter_cancel
Fix this by introducing a separate h_cg_rsvd pointer exclusively for the
rsvd charge path, keeping the rsvd and non-rsvd charges fully independent
through their charge, commit, and error uncharge paths.
Link: https://lore.kernel.org/20260328065534.346053-1-kartikey406@gmail.com
Fixes: 08cf9faf7558 ("hugetlb_cgroup: support noreserve mappings")
Reported-by: syzbot+226c1f947186f8fef796@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=226c1f947186f8fef796
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
Reviewed-by: Muchun Song <muchun.song@linux.dev>
Cc: David Hildenbrand <david@kernel.org>
Cc: Oscar Salvador <osalvador@suse.de>
Cc: Mina Almasry <almasrymina@google.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
mm/hugetlb.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -2976,6 +2976,7 @@ struct folio *alloc_hugetlb_folio(struct
long gbl_chg;
int memcg_charge_ret, ret, idx;
struct hugetlb_cgroup *h_cg = NULL;
+ struct hugetlb_cgroup *h_cg_rsvd = NULL;
struct mem_cgroup *memcg;
bool deferred_reserve;
gfp_t gfp = htlb_alloc_mask(h) | __GFP_RETRY_MAYFAIL;
@@ -3019,7 +3020,7 @@ struct folio *alloc_hugetlb_folio(struct
deferred_reserve = map_chg || avoid_reserve;
if (deferred_reserve) {
ret = hugetlb_cgroup_charge_cgroup_rsvd(
- idx, pages_per_huge_page(h), &h_cg);
+ idx, pages_per_huge_page(h), &h_cg_rsvd);
if (ret)
goto out_subpool_put;
}
@@ -3056,7 +3057,7 @@ struct folio *alloc_hugetlb_folio(struct
*/
if (deferred_reserve) {
hugetlb_cgroup_commit_charge_rsvd(idx, pages_per_huge_page(h),
- h_cg, folio);
+ h_cg_rsvd, folio);
}
spin_unlock_irq(&hugetlb_lock);
@@ -3097,7 +3098,7 @@ out_uncharge_cgroup:
out_uncharge_cgroup_reservation:
if (deferred_reserve)
hugetlb_cgroup_uncharge_cgroup_rsvd(idx, pages_per_huge_page(h),
- h_cg);
+ h_cg_rsvd);
out_subpool_put:
if (map_chg || avoid_reserve)
hugepage_subpool_put_pages(spool, 1);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 518/602] mm/sparse-vmemmap: fix vmemmap accounting underflow
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (516 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 517/602] mm/hugetlb: fix hugetlb cgroup rsvd charge/uncharge mismatch Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 519/602] landlock: Prepare to use credential instead of domain for fowner Greg Kroah-Hartman
` (87 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Muchun Song,
Mike Rapoport (Microsoft), Oscar Salvador,
David Hildenbrand (Arm), Liam R. Howlett, Aneesh Kumar K.V,
Joao Martins, Lorenzo Stoakes, Madhavan Srinivasan,
Michael Ellerman, Michal Hocko, Nicholas Piggin,
Suren Baghdasaryan, Vlastimil Babka, Andrew Morton, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Muchun Song <songmuchun@bytedance.com>
[ Upstream commit c373f7f98e6ad591c85d40548cf8b6443be69311 ]
Patch series "mm: Fix vmemmap optimization accounting and initialization",
v8.
The series fixes several bugs in vmemmap optimization, mainly around
incorrect page accounting and memmap initialization in DAX and memory
hotplug paths. It also fixes pageblock migratetype initialization and
struct page initialization for ZONE_DEVICE compound pages.
Patches 1-4 fix vmemmap accounting issues. Patch 1 fixes an accounting
underflow in the section activation failure path by moving vmemmap page
accounting into the lower-level allocation and freeing helpers. Patch 2
fixes incorrect altmap passing in the memory hotplug error path. Patch 3
passes pgmap through memory deactivation paths so the teardown side can
determine whether vmemmap optimization was in effect. Patch 4 uses that
information to account the optimized DAX vmemmap size correctly.
Patches 5-6 fix initialization issues in mm/mm_init. One makes sure all
pageblocks in ZONE_DEVICE compound pages get their migratetype
initialized. The other fixes a case where DAX memory hotplug reuses an
unoptimized early-section memmap while compound_nr_pages() still assumes
vmemmap optimization, leaving tail struct pages uninitialized.
This patch (of 6):
In section_activate(), if populate_section_memmap() fails, the error
handling path calls section_deactivate() to roll back the state. This
causes a vmemmap accounting imbalance.
Since commit c3576889d87b ("mm: fix accounting of memmap pages"), memmap
pages are accounted for only after populate_section_memmap() succeeds.
However, the failure path unconditionally calls section_deactivate(),
which decreases the vmemmap count. Consequently, a failure in
populate_section_memmap() leads to an accounting underflow, incorrectly
reducing the system's tracked vmemmap usage.
Fix this more thoroughly by moving all accounting calls into the lower
level functions that actually perform the vmemmap allocation and freeing:
- populate_section_memmap() accounts for newly allocated vmemmap pages -
depopulate_section_memmap() unaccounts when vmemmap is freed
This ensures proper accounting in all code paths, including error handling
and early section cases.
Link: https://lore.kernel.org/20260428081855.1249045-1-songmuchun@bytedance.com
Link: https://lore.kernel.org/20260428081855.1249045-2-songmuchun@bytedance.com
Fixes: c3576889d87b ("mm: fix accounting of memmap pages")
Signed-off-by: Muchun Song <songmuchun@bytedance.com>
Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Acked-by: Oscar Salvador <osalvador@suse.de>
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
Acked-by: Liam R. Howlett <liam@infradead.org>
Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com>
Cc: Joao Martins <joao.m.martins@oracle.com>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
mm/sparse.c | 32 ++++++++++++++++++++++----------
1 file changed, 22 insertions(+), 10 deletions(-)
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -633,7 +633,12 @@ static struct page * __meminit populate_
unsigned long nr_pages, int nid, struct vmem_altmap *altmap,
struct dev_pagemap *pgmap)
{
- return __populate_section_memmap(pfn, nr_pages, nid, altmap, pgmap);
+ struct page *page = __populate_section_memmap(pfn, nr_pages, nid, altmap,
+ pgmap);
+
+ memmap_pages_add(DIV_ROUND_UP(nr_pages * sizeof(struct page), PAGE_SIZE));
+
+ return page;
}
static void depopulate_section_memmap(unsigned long pfn, unsigned long nr_pages,
@@ -642,13 +647,17 @@ static void depopulate_section_memmap(un
unsigned long start = (unsigned long) pfn_to_page(pfn);
unsigned long end = start + nr_pages * sizeof(struct page);
+ memmap_pages_add(-1L * (DIV_ROUND_UP(nr_pages * sizeof(struct page), PAGE_SIZE)));
vmemmap_free(start, end, altmap);
}
+
static void free_map_bootmem(struct page *memmap)
{
unsigned long start = (unsigned long)memmap;
unsigned long end = (unsigned long)(memmap + PAGES_PER_SECTION);
+ memmap_boot_pages_add(-1L * (DIV_ROUND_UP(PAGES_PER_SECTION * sizeof(struct page),
+ PAGE_SIZE)));
vmemmap_free(start, end, NULL);
}
@@ -705,13 +714,18 @@ static struct page * __meminit populate_
unsigned long nr_pages, int nid, struct vmem_altmap *altmap,
struct dev_pagemap *pgmap)
{
- return kvmalloc_node(array_size(sizeof(struct page),
- PAGES_PER_SECTION), GFP_KERNEL, nid);
+ struct page *page = kvmalloc_node(array_size(sizeof(struct page),
+ PAGES_PER_SECTION), GFP_KERNEL, nid);
+
+ memmap_pages_add(DIV_ROUND_UP(nr_pages * sizeof(struct page), PAGE_SIZE));
+
+ return page;
}
static void depopulate_section_memmap(unsigned long pfn, unsigned long nr_pages,
struct vmem_altmap *altmap)
{
+ memmap_pages_add(-1L * (DIV_ROUND_UP(nr_pages * sizeof(struct page), PAGE_SIZE)));
kvfree(pfn_to_page(pfn));
}
@@ -724,6 +738,9 @@ static void free_map_bootmem(struct page
nr_pages = PAGE_ALIGN(PAGES_PER_SECTION * sizeof(struct page))
>> PAGE_SHIFT;
+ memmap_boot_pages_add(-1L * (DIV_ROUND_UP(PAGES_PER_SECTION * sizeof(struct page),
+ PAGE_SIZE)));
+
for (i = 0; i < nr_pages; i++, page++) {
magic = page->index;
@@ -817,14 +834,10 @@ static void section_deactivate(unsigned
* The memmap of early sections is always fully populated. See
* section_activate() and pfn_valid() .
*/
- if (!section_is_early) {
- memmap_pages_add(-1L * (DIV_ROUND_UP(nr_pages * sizeof(struct page), PAGE_SIZE)));
+ if (!section_is_early)
depopulate_section_memmap(pfn, nr_pages, altmap);
- } else if (memmap) {
- memmap_boot_pages_add(-1L * (DIV_ROUND_UP(nr_pages * sizeof(struct page),
- PAGE_SIZE)));
+ else if (memmap)
free_map_bootmem(memmap);
- }
if (empty)
ms->section_mem_map = (unsigned long)NULL;
@@ -869,7 +882,6 @@ static struct page * __meminit section_a
section_deactivate(pfn, nr_pages, altmap);
return ERR_PTR(-ENOMEM);
}
- memmap_pages_add(DIV_ROUND_UP(nr_pages * sizeof(struct page), PAGE_SIZE));
return memmap;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 519/602] landlock: Prepare to use credential instead of domain for fowner
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (517 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 518/602] mm/sparse-vmemmap: fix vmemmap accounting underflow Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 520/602] landlock: Fix LANDLOCK_SCOPE_SIGNAL bypass on the SIGIO path Greg Kroah-Hartman
` (86 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Günther Noack,
Mickaël Salaün, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mickaël Salaün <mic@digikod.net>
[ Upstream commit 79625f1b3a3df63d3289a0781fdf121bc42966f7 ]
This cosmetic change is needed for audit support, specifically to be
able to filter according to cross-execution boundaries.
struct landlock_file_security's size stay the same for now but it will
increase with struct landlock_cred_security's size.
Only save Landlock domain in hook_file_set_fowner() if the current
domain has LANDLOCK_SCOPE_SIGNAL, which was previously done for each
hook_file_send_sigiotask() calls. This should improve a bit
performance.
Replace hardcoded LANDLOCK_SCOPE_SIGNAL with the signal_scope.scope
variable.
Use scoped guards for RCU read-side critical sections.
Cc: Günther Noack <gnoack@google.com>
Link: https://lore.kernel.org/r/20250320190717.2287696-8-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>
Stable-dep-of: 4b80320ca7ed ("landlock: Fix LANDLOCK_SCOPE_SIGNAL bypass on the SIGIO path")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
security/landlock/fs.c | 37 +++++++++++++++++++++++++++++++------
security/landlock/fs.h | 23 +++++++++++++++++------
security/landlock/task.c | 25 ++++++++++++++++---------
3 files changed, 64 insertions(+), 21 deletions(-)
--- a/security/landlock/fs.c
+++ b/security/landlock/fs.c
@@ -1680,15 +1680,40 @@ static bool control_current_fowner(struc
static void hook_file_set_fowner(struct file *file)
{
struct landlock_ruleset *prev_dom;
- struct landlock_ruleset *new_dom = NULL;
+ struct landlock_cred_security fown_subject = {};
+ size_t fown_layer = 0;
+
+ /*
+ * Keep this local to match the layout expected by follow-up changes
+ * shared with audit-enabled kernels.
+ */
+ (void)fown_layer;
if (control_current_fowner(file_f_owner(file))) {
- new_dom = landlock_get_current_domain();
- landlock_get_ruleset(new_dom);
+ static const struct access_masks signal_scope = {
+ .scope = LANDLOCK_SCOPE_SIGNAL,
+ };
+ struct landlock_ruleset *const current_domain =
+ landlock_get_current_domain();
+ const struct landlock_cred_security applicable_subject = {
+ .domain = current_domain,
+ };
+ const struct landlock_cred_security *new_subject = NULL;
+
+ if (landlock_get_applicable_domain(current_domain, signal_scope))
+ new_subject = &applicable_subject;
+
+ if (new_subject) {
+ landlock_get_ruleset(new_subject->domain);
+ fown_subject = *new_subject;
+ }
}
- prev_dom = landlock_file(file)->fown_domain;
- landlock_file(file)->fown_domain = new_dom;
+ prev_dom = landlock_file(file)->fown_subject.domain;
+ landlock_file(file)->fown_subject = fown_subject;
+#ifdef CONFIG_AUDIT
+ landlock_file(file)->fown_layer = fown_layer;
+#endif /* CONFIG_AUDIT*/
/* May be called in an RCU read-side critical section. */
landlock_put_ruleset_deferred(prev_dom);
@@ -1696,7 +1721,7 @@ static void hook_file_set_fowner(struct
static void hook_file_free_security(struct file *file)
{
- landlock_put_ruleset_deferred(landlock_file(file)->fown_domain);
+ landlock_put_ruleset_deferred(landlock_file(file)->fown_subject.domain);
}
static struct security_hook_list landlock_hooks[] __ro_after_init = {
--- a/security/landlock/fs.h
+++ b/security/landlock/fs.h
@@ -1,9 +1,10 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * Landlock LSM - Filesystem management and hooks
+ * Landlock - Filesystem management and hooks
*
* Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net>
* Copyright © 2018-2020 ANSSI
+ * Copyright © 2024-2025 Microsoft Corporation
*/
#ifndef _SECURITY_LANDLOCK_FS_H
@@ -13,6 +14,7 @@
#include <linux/init.h>
#include <linux/rcupdate.h>
+#include "cred.h"
#include "ruleset.h"
#include "setup.h"
@@ -52,13 +54,22 @@ struct landlock_file_security {
* needed to authorize later operations on the open file.
*/
access_mask_t allowed_access;
+
+#ifdef CONFIG_AUDIT
+ /**
+ * @fown_layer: Compatibility storage for follow-up fowner changes.
+ */
+ u8 fown_layer;
+#endif /* CONFIG_AUDIT */
+
/**
- * @fown_domain: Domain of the task that set the PID that may receive a
- * signal e.g., SIGURG when writing MSG_OOB to the related socket.
- * This pointer is protected by the related file->f_owner->lock, as for
- * fown_struct's members: pid, uid, and euid.
+ * @fown_subject: Landlock credential of the task that set the PID that
+ * may receive a signal e.g., SIGURG when writing MSG_OOB to the
+ * related socket. This pointer is protected by the related
+ * file->f_owner->lock, as for fown_struct's members: pid, uid, and
+ * euid.
*/
- struct landlock_ruleset *fown_domain;
+ struct landlock_cred_security fown_subject;
};
/**
--- a/security/landlock/task.c
+++ b/security/landlock/task.c
@@ -297,22 +297,29 @@ static int hook_task_kill(struct task_st
static int hook_file_send_sigiotask(struct task_struct *tsk,
struct fown_struct *fown, int signum)
{
- const struct landlock_ruleset *dom;
+ const struct landlock_cred_security *subject;
bool is_scoped = false;
/* Lock already held by send_sigio() and send_sigurg(). */
lockdep_assert_held(&fown->lock);
- dom = landlock_get_applicable_domain(
- landlock_file(fown->file)->fown_domain, signal_scope);
+ subject = &landlock_file(fown->file)->fown_subject;
- /* Quick return for unowned socket. */
- if (!dom)
+ /*
+ * Quick return for unowned socket.
+ *
+ * subject->domain has already been filtered when saved by
+ * hook_file_set_fowner(), so there is no need to call
+ * landlock_get_applicable_subject() here.
+ */
+ if (!subject->domain)
return 0;
- rcu_read_lock();
- is_scoped = domain_is_scoped(dom, landlock_get_task_domain(tsk),
- LANDLOCK_SCOPE_SIGNAL);
- rcu_read_unlock();
+ scoped_guard(rcu)
+ {
+ is_scoped = domain_is_scoped(subject->domain,
+ landlock_get_task_domain(tsk),
+ signal_scope.scope);
+ }
if (is_scoped)
return -EPERM;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 520/602] landlock: Fix LANDLOCK_SCOPE_SIGNAL bypass on the SIGIO path
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (518 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 519/602] landlock: Prepare to use credential instead of domain for fowner Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 521/602] mm/mm_init: fix pageblock migratetype for ZONE_DEVICE compound pages Greg Kroah-Hartman
` (85 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Bryam Vargas, Günther Noack,
Mickaël Salaün, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <hexlabsecurity@proton.me>
[ Upstream commit 4b80320ca7ed03d6e683f95b6066565dc97b9f92 ]
LANDLOCK_SCOPE_SIGNAL must prevent a sandboxed process from signaling
processes outside its Landlock domain. It can be bypassed through the
asynchronous SIGIO delivery path.
A sandboxed process that owns any file or socket can arm it with
fcntl(fd, F_SETOWN, -pgid), fcntl(fd, F_SETSIG, SIGKILL) and O_ASYNC, so
that an I/O event makes the kernel deliver the chosen signal to the
whole process group. As the head of its process group's task list (the
default position right after fork()) that group can also hold the
non-sandboxed process that launched it, e.g. a supervisor or a security
monitor. The sandbox can thus kill or signal the processes
LANDLOCK_SCOPE_SIGNAL is meant to protect from it.
The scope is enforced in hook_file_send_sigiotask() against the Landlock
domain recorded at F_SETOWN time, not the live domain of the sender.
control_current_fowner() decides whether to record that domain and skips
recording it when the fowner target is in the caller's thread group,
which is safe only for a single-task target (PIDTYPE_PID, PIDTYPE_TGID).
For a process group (PIDTYPE_PGID) pid_task() returns only one member;
recording is skipped whenever that member shares the caller's thread
group, and hook_file_send_sigiotask() then lets the signal fan out to
the whole group unchecked.
Record the domain for every non single-process target so the scope is
enforced against each group member at delivery time.
That recording is necessary but not sufficient on its own: the kernel
signals a process group through its members' thread-group leaders, and
the leader of the registrant's own process can carry a different
Landlock domain than the sibling thread that armed the owner.
domain_is_scoped() would then deny that leader, even though commit
18eb75f3af40 ("landlock: Always allow signals between threads of the
same process") requires same-process delivery to be allowed.
hook_task_kill() avoids this by evaluating same_thread_group() live, per
recipient; the SIGIO path instead delegates the whole decision to a
single registration-time check, which a process-group fan-out cannot
honor.
So also record the registrant's thread group next to its domain and
exempt it at delivery: hook_file_send_sigiotask() allows the signal
whenever the recipient belongs to the registrant's own process,
restoring the same-process guarantee while keeping out-of-domain group
members blocked. The direct kill() path (hook_task_kill) already
evaluates the live domain and is unaffected.
Fixes: 18eb75f3af40 ("landlock: Always allow signals between threads of the same process")
Cc: stable@vger.kernel.org
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
Reviewed-by: Günther Noack <gnoack3000@gmail.com>
Link: https://patch.msgid.link/56bffc24f3d0d08b45a686a48e99766b0a0821fa.1780614610.git.hexlabsecurity@proton.me
[mic: Check pid_type earlier and improve comment, fix commit message,
fix comment formatting]
Signed-off-by: Mickaël Salaün <mic@digikod.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
security/landlock/fs.c | 14 ++++++++++++++
security/landlock/fs.h | 10 ++++++++++
security/landlock/task.c | 11 +++++++++++
3 files changed, 35 insertions(+)
--- a/security/landlock/fs.c
+++ b/security/landlock/fs.c
@@ -1666,6 +1666,14 @@ static bool control_current_fowner(struc
lockdep_assert_held(&fown->lock);
/*
+ * A process-group or session owner (PIDTYPE_PGID/PIDTYPE_SID) fans the
+ * signal out to every member at delivery time, so record the domain and
+ * let hook_file_send_sigiotask() check the live scope per recipient.
+ */
+ if (fown->pid_type != PIDTYPE_PID && fown->pid_type != PIDTYPE_TGID)
+ return true;
+
+ /*
* Some callers (e.g. fcntl_dirnotify) may not be in an RCU read-side
* critical section.
*/
@@ -1681,6 +1689,7 @@ static void hook_file_set_fowner(struct
{
struct landlock_ruleset *prev_dom;
struct landlock_cred_security fown_subject = {};
+ struct pid *prev_tg, *fown_tg = NULL;
size_t fown_layer = 0;
/*
@@ -1706,21 +1715,26 @@ static void hook_file_set_fowner(struct
if (new_subject) {
landlock_get_ruleset(new_subject->domain);
fown_subject = *new_subject;
+ fown_tg = get_pid(task_tgid(current));
}
}
prev_dom = landlock_file(file)->fown_subject.domain;
+ prev_tg = landlock_file(file)->fown_tg;
landlock_file(file)->fown_subject = fown_subject;
+ landlock_file(file)->fown_tg = fown_tg;
#ifdef CONFIG_AUDIT
landlock_file(file)->fown_layer = fown_layer;
#endif /* CONFIG_AUDIT*/
/* May be called in an RCU read-side critical section. */
landlock_put_ruleset_deferred(prev_dom);
+ put_pid(prev_tg);
}
static void hook_file_free_security(struct file *file)
{
+ put_pid(landlock_file(file)->fown_tg);
landlock_put_ruleset_deferred(landlock_file(file)->fown_subject.domain);
}
--- a/security/landlock/fs.h
+++ b/security/landlock/fs.h
@@ -70,6 +70,16 @@ struct landlock_file_security {
* euid.
*/
struct landlock_cred_security fown_subject;
+ /**
+ * @fown_tg: Thread group of the task that set the file owner, pinned
+ * while @fown_subject holds a domain. It lets
+ * hook_file_send_sigiotask() always allow a SIGIO delivered to the
+ * owner's own process -- e.g. the thread-group leader reached through a
+ * process-group owner -- matching the same-process exemption of
+ * hook_task_kill(). NULL when no domain is recorded. Protected by
+ * file->f_owner->lock, like @fown_subject.
+ */
+ struct pid *fown_tg;
};
/**
--- a/security/landlock/task.c
+++ b/security/landlock/task.c
@@ -314,6 +314,17 @@ static int hook_file_send_sigiotask(stru
if (!subject->domain)
return 0;
+ /*
+ * Always allow delivery to the file owner's own process, including a
+ * thread-group leader reached through a process-group owner. This
+ * mirrors hook_task_kill()'s same-process exemption and preserves the
+ * guarantee of commit 18eb75f3af40 ("landlock: Always allow signals
+ * between threads of the same process"), which the registration-time
+ * check cannot honor for a process-group target.
+ */
+ if (task_tgid(tsk) == landlock_file(fown->file)->fown_tg)
+ return 0;
+
scoped_guard(rcu)
{
is_scoped = domain_is_scoped(subject->domain,
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 521/602] mm/mm_init: fix pageblock migratetype for ZONE_DEVICE compound pages
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (519 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 520/602] landlock: Fix LANDLOCK_SCOPE_SIGNAL bypass on the SIGIO path Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 522/602] mtd: maps: vmu-flash: fix fault in unaligned fixup Greg Kroah-Hartman
` (84 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Muchun Song,
Mike Rapoport (Microsoft), Oscar Salvador,
David Hildenbrand (Arm), Liam R. Howlett, Aneesh Kumar K.V,
Joao Martins, Lorenzo Stoakes, Madhavan Srinivasan,
Michael Ellerman, Michal Hocko, Nicholas Piggin,
Suren Baghdasaryan, Vlastimil Babka, Andrew Morton, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Muchun Song <songmuchun@bytedance.com>
[ Upstream commit 94405c6136839f7c462249c8b4b957bcb9527a9d ]
The memmap_init_zone_device() function only initializes the migratetype of
the first pageblock of a compound page. If the compound page size exceeds
pageblock_nr_pages (e.g., 1GB hugepages with 2MB pageblocks), subsequent
pageblocks in the compound page remain uninitialized.
Move the migratetype initialization out of __init_zone_device_page() and
into a separate pageblock_migratetype_init_range() function. This
iterates over the entire PFN range of the memory, ensuring that all
pageblocks are correctly initialized.
Also remove the stale confusing comment about MEMINIT_HOTPLUG above the
migratetype setting since it is an obsolete relic from commit 966cf44f637e
("mm: defer ZONE_DEVICE page initialization to the point where we init
pgmap") and no longer makes sense here.
Link: https://lore.kernel.org/20260428081855.1249045-6-songmuchun@bytedance.com
Fixes: c4386bd8ee3a ("mm/memremap: add ZONE_DEVICE support for compound pages")
Signed-off-by: Muchun Song <songmuchun@bytedance.com>
Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Reviewed-by: Oscar Salvador <osalvador@suse.de>
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
Acked-by: Liam R. Howlett <liam@infradead.org>
Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com>
Cc: Joao Martins <joao.m.martins@oracle.com>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
mm/mm_init.c | 34 +++++++++++++++++++---------------
1 file changed, 19 insertions(+), 15 deletions(-)
--- a/mm/mm_init.c
+++ b/mm/mm_init.c
@@ -650,6 +650,20 @@ static inline void fixup_hashdist(void)
static inline void fixup_hashdist(void) {}
#endif /* CONFIG_NUMA */
+#ifdef CONFIG_ZONE_DEVICE
+static __meminit void pageblock_migratetype_init_range(unsigned long pfn,
+ unsigned long nr_pages, int migratetype)
+{
+ const unsigned long end = pfn + nr_pages;
+
+ for (pfn = pageblock_align(pfn); pfn < end; pfn += pageblock_nr_pages) {
+ set_pageblock_migratetype(pfn_to_page(pfn), migratetype);
+ if (IS_ALIGNED(pfn, PAGES_PER_SECTION))
+ cond_resched();
+ }
+}
+#endif
+
#ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT
static inline void pgdat_set_deferred_range(pg_data_t *pgdat)
{
@@ -1000,21 +1014,6 @@ static void __ref __init_zone_device_pag
page->zone_device_data = NULL;
/*
- * Mark the block movable so that blocks are reserved for
- * movable at startup. This will force kernel allocations
- * to reserve their blocks rather than leaking throughout
- * the address space during boot when many long-lived
- * kernel allocations are made.
- *
- * Please note that MEMINIT_HOTPLUG path doesn't clear memmap
- * because this is done early in section_activate()
- */
- if (pageblock_aligned(pfn)) {
- set_pageblock_migratetype(page, MIGRATE_MOVABLE);
- cond_resched();
- }
-
- /*
* ZONE_DEVICE pages are released directly to the driver page allocator
* which will set the page count to 1 when allocating the page.
*/
@@ -1105,6 +1104,9 @@ void __ref memmap_init_zone_device(struc
__init_zone_device_page(page, pfn, zone_idx, nid, pgmap);
+ if (IS_ALIGNED(pfn, PAGES_PER_SECTION))
+ cond_resched();
+
if (pfns_per_compound == 1)
continue;
@@ -1112,6 +1114,8 @@ void __ref memmap_init_zone_device(struc
compound_nr_pages(pfn, altmap, pgmap));
}
+ pageblock_migratetype_init_range(start_pfn, nr_pages, MIGRATE_MOVABLE);
+
pr_debug("%s initialised %lu pages in %ums\n", __func__,
nr_pages, jiffies_to_msecs(jiffies - start));
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 522/602] mtd: maps: vmu-flash: fix fault in unaligned fixup
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (520 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 521/602] mm/mm_init: fix pageblock migratetype for ZONE_DEVICE compound pages Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 523/602] mm: prepare to move subsection_map_init() to mm/sparse-vmemmap.c Greg Kroah-Hartman
` (83 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Florian Fuchs, Miquel Raynal,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Fuchs <fuchsfl@gmail.com>
[ Upstream commit 79d1661502c6e4b6f626185cef72cf2fa78116e1 ]
Use kzalloc_obj() / kzalloc_objs() to allocate the memcard structs,
instead of kmalloc_obj() / kmalloc_objs() to prevent access to
uninitialized data.
Fixes runtime error: Fault in unaligned fixup: 0000 [#1] at
mtd_get_fact_prot_info.
Fixes: 47a72688fae7 ("mtd: flash mapping support for Dreamcast VMU.")
Cc: stable@vger.kernel.org
Signed-off-by: Florian Fuchs <fuchsfl@gmail.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/mtd/maps/vmu-flash.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
--- a/drivers/mtd/maps/vmu-flash.c
+++ b/drivers/mtd/maps/vmu-flash.c
@@ -610,7 +610,7 @@ static int vmu_connect(struct maple_devi
basic_flash_data = be32_to_cpu(mdev->devinfo.function_data[c - 1]);
- card = kmalloc(sizeof(struct memcard), GFP_KERNEL);
+ card = kzalloc_obj(struct memcard);
if (!card) {
error = -ENOMEM;
goto fail_nomem;
@@ -628,15 +628,13 @@ static int vmu_connect(struct maple_devi
* Not sure there are actually any multi-partition devices in the
* real world, but the hardware supports them, so, so will we
*/
- card->parts = kmalloc_array(card->partitions, sizeof(struct vmupart),
- GFP_KERNEL);
+ card->parts = kzalloc_objs(struct vmupart, card->partitions);
if (!card->parts) {
error = -ENOMEM;
goto fail_partitions;
}
- card->mtd = kmalloc_array(card->partitions, sizeof(struct mtd_info),
- GFP_KERNEL);
+ card->mtd = kzalloc_objs(struct mtd_info, card->partitions);
if (!card->mtd) {
error = -ENOMEM;
goto fail_mtd_info;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 523/602] mm: prepare to move subsection_map_init() to mm/sparse-vmemmap.c
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (521 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 522/602] mtd: maps: vmu-flash: fix fault in unaligned fixup Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 524/602] mm/sparse-vmemmap: fix DAX vmemmap accounting with optimization Greg Kroah-Hartman
` (82 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Hildenbrand (Arm),
Lorenzo Stoakes (Oracle), Mike Rapoport (Microsoft),
Axel Rasmussen, Liam Howlett, Michal Hocko, Oscar Salvador,
Sidhartha Kumar, Suren Baghdasaryan, Vlastimil Babka, Wei Xu,
Yuanchu Xie, Andrew Morton, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: "David Hildenbrand (Arm)" <david@kernel.org>
[ Upstream commit fead6dcff83b02f8d6dc3c1ebbe4e09c05c54ee5 ]
We want to move subsection_map_init() to mm/sparse-vmemmap.c.
To prepare for getting rid of subsection_map_init() in mm/sparse.c
completely, use a static inline function for !CONFIG_SPARSEMEM_VMEMMAP.
While at it, move the declaration to internal.h and rename it to
"sparse_init_subsection_map()".
Link: https://lkml.kernel.org/r/20260320-sparsemem_cleanups-v2-11-096addc8800d@kernel.org
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
Reviewed-by: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Cc: Axel Rasmussen <axelrasmussen@google.com>
Cc: Liam Howlett <liam.howlett@oracle.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Oscar Salvador <osalvador@suse.de>
Cc: Sidhartha Kumar <sidhartha.kumar@oracle.com>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: Wei Xu <weixugc@google.com>
Cc: Yuanchu Xie <yuanchu@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Stable-dep-of: 721a73e30c9e ("mm/sparse-vmemmap: fix DAX vmemmap accounting with optimization")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/arm64/mm/mmu.c | 5
arch/loongarch/mm/init.c | 5
arch/powerpc/mm/mem.c | 5
arch/riscv/mm/init.c | 5
arch/s390/mm/init.c | 5
arch/x86/mm/init_64.c | 5
include/linux/memory_hotplug.h | 8 -
include/linux/mmzone.h | 7
mm/internal.h | 47 ++++++
mm/memory_hotplug.c | 13 -
mm/memremap.c | 4
mm/mm_init.c | 2
mm/sparse-vmemmap.c | 310 +++++++++++++++++++++++++++++++++++++++++
mm/sparse.c | 80 ----------
14 files changed, 399 insertions(+), 102 deletions(-)
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -1384,12 +1384,13 @@ int arch_add_memory(int nid, u64 start,
return ret;
}
-void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
+void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap,
+ struct dev_pagemap *pgmap)
{
unsigned long start_pfn = start >> PAGE_SHIFT;
unsigned long nr_pages = size >> PAGE_SHIFT;
- __remove_pages(start_pfn, nr_pages, altmap);
+ __remove_pages(start_pfn, nr_pages, altmap, pgmap);
__remove_pgd_mapping(swapper_pg_dir, __phys_to_virt(start), size);
}
--- a/arch/loongarch/mm/init.c
+++ b/arch/loongarch/mm/init.c
@@ -103,12 +103,13 @@ int arch_add_memory(int nid, u64 start,
return ret;
}
-void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
+void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap,
+ struct dev_pagemap *pgmap)
{
unsigned long start_pfn = start >> PAGE_SHIFT;
unsigned long nr_pages = size >> PAGE_SHIFT;
- __remove_pages(start_pfn, nr_pages, altmap);
+ __remove_pages(start_pfn, nr_pages, altmap, pgmap);
}
#ifdef CONFIG_NUMA
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -157,12 +157,13 @@ int __ref arch_add_memory(int nid, u64 s
return rc;
}
-void __ref arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
+void __ref arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap,
+ struct dev_pagemap *pgmap)
{
unsigned long start_pfn = start >> PAGE_SHIFT;
unsigned long nr_pages = size >> PAGE_SHIFT;
- __remove_pages(start_pfn, nr_pages, altmap);
+ __remove_pages(start_pfn, nr_pages, altmap, pgmap);
arch_remove_linear_mapping(start, size);
}
#endif
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -1839,9 +1839,10 @@ int __ref arch_add_memory(int nid, u64 s
return ret;
}
-void __ref arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
+void __ref arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap,
+ struct dev_pagemap *pgmap)
{
- __remove_pages(start >> PAGE_SHIFT, size >> PAGE_SHIFT, altmap);
+ __remove_pages(start >> PAGE_SHIFT, size >> PAGE_SHIFT, altmap, pgmap);
remove_linear_mapping(start, size);
flush_tlb_all();
}
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -290,12 +290,13 @@ int arch_add_memory(int nid, u64 start,
return rc;
}
-void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
+void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap,
+ struct dev_pagemap *pgmap)
{
unsigned long start_pfn = start >> PAGE_SHIFT;
unsigned long nr_pages = size >> PAGE_SHIFT;
- __remove_pages(start_pfn, nr_pages, altmap);
+ __remove_pages(start_pfn, nr_pages, altmap, pgmap);
vmem_remove_mapping(start, size);
}
#endif /* CONFIG_MEMORY_HOTPLUG */
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -1293,12 +1293,13 @@ kernel_physical_mapping_remove(unsigned
remove_pagetable(start, end, true, NULL);
}
-void __ref arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap)
+void __ref arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap,
+ struct dev_pagemap *pgmap)
{
unsigned long start_pfn = start >> PAGE_SHIFT;
unsigned long nr_pages = size >> PAGE_SHIFT;
- __remove_pages(start_pfn, nr_pages, altmap);
+ __remove_pages(start_pfn, nr_pages, altmap, pgmap);
kernel_physical_mapping_remove(start, start + size);
}
#endif /* CONFIG_MEMORY_HOTPLUG */
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -153,9 +153,10 @@ static inline bool movable_node_is_enabl
return movable_node_enabled;
}
-extern void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap);
+extern void arch_remove_memory(u64 start, u64 size, struct vmem_altmap *altmap,
+ struct dev_pagemap *pgmap);
extern void __remove_pages(unsigned long start_pfn, unsigned long nr_pages,
- struct vmem_altmap *altmap);
+ struct vmem_altmap *altmap, struct dev_pagemap *pgmap);
/* reasonably generic interface to expand the physical pages */
extern int __add_pages(int nid, unsigned long start_pfn, unsigned long nr_pages,
@@ -321,7 +322,8 @@ extern int sparse_add_section(int nid, u
unsigned long nr_pages, struct vmem_altmap *altmap,
struct dev_pagemap *pgmap);
extern void sparse_remove_section(unsigned long pfn, unsigned long nr_pages,
- struct vmem_altmap *altmap);
+ struct vmem_altmap *altmap,
+ struct dev_pagemap *pgmap);
extern struct page *sparse_decode_mem_map(unsigned long coded_mem_map,
unsigned long pnum);
extern struct zone *zone_for_pfn_range(int online_type, int nid,
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -1815,15 +1815,13 @@ struct mem_section_usage {
unsigned long pageblock_flags[0];
};
-void subsection_map_init(unsigned long pfn, unsigned long nr_pages);
-
struct page;
struct page_ext;
struct mem_section {
/*
* This is, logically, a pointer to an array of struct
* pages. However, it is stored with some other magic.
- * (see sparse.c::sparse_init_one_section())
+ * (see sparse_init_one_section())
*
* Additionally during early boot we encode node id of
* the location of the section here to guide allocation.
@@ -2092,8 +2090,9 @@ void sparse_init(void);
#else
#define sparse_init() do {} while (0)
#define sparse_index_init(_sec, _nid) do {} while (0)
+#define sparse_vmemmap_init_nid_early(_nid) do {} while (0)
+#define sparse_vmemmap_init_nid_late(_nid) do {} while (0)
#define pfn_in_present_section pfn_valid
-#define subsection_map_init(_pfn, _nr_pages) do {} while (0)
#endif /* CONFIG_SPARSEMEM */
#endif /* !__GENERATING_BOUNDS.H */
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -749,6 +749,53 @@ extern void *memmap_alloc(phys_addr_t si
void memmap_init_range(unsigned long, int, unsigned long, unsigned long,
unsigned long, enum meminit_context, struct vmem_altmap *, int);
+#ifdef CONFIG_SPARSEMEM
+int sparse_index_init(unsigned long section_nr, int nid);
+
+static inline void sparse_init_one_section(struct mem_section *ms,
+ unsigned long pnum, struct page *mem_map,
+ struct mem_section_usage *usage, unsigned long flags)
+{
+ unsigned long coded_mem_map;
+
+ BUILD_BUG_ON(SECTION_MAP_LAST_BIT > PFN_SECTION_SHIFT);
+
+ /*
+ * We encode the start PFN of the section into the mem_map such that
+ * page_to_pfn() on !CONFIG_SPARSEMEM_VMEMMAP can simply subtract it
+ * from the page pointer to obtain the PFN.
+ */
+ coded_mem_map = (unsigned long)(mem_map - section_nr_to_pfn(pnum));
+ VM_WARN_ON_ONCE(coded_mem_map & ~SECTION_MAP_MASK);
+
+ ms->section_mem_map &= ~SECTION_MAP_MASK;
+ ms->section_mem_map |= coded_mem_map;
+ ms->section_mem_map |= flags | SECTION_HAS_MEM_MAP;
+ ms->usage = usage;
+}
+
+static inline void __section_mark_present(struct mem_section *ms,
+ unsigned long section_nr)
+{
+ if (section_nr > __highest_present_section_nr)
+ __highest_present_section_nr = section_nr;
+
+ ms->section_mem_map |= SECTION_MARKED_PRESENT;
+}
+#endif /* CONFIG_SPARSEMEM */
+
+/*
+ * mm/sparse-vmemmap.c
+ */
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
+void sparse_init_subsection_map(unsigned long pfn, unsigned long nr_pages);
+#else
+static inline void sparse_init_subsection_map(unsigned long pfn,
+ unsigned long nr_pages)
+{
+}
+#endif /* CONFIG_SPARSEMEM_VMEMMAP */
+
#if defined CONFIG_COMPACTION || defined CONFIG_CMA
/*
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -564,6 +564,7 @@ void remove_pfn_range_from_zone(struct z
* @pfn: starting pageframe (must be aligned to start of a section)
* @nr_pages: number of pages to remove (must be multiple of section size)
* @altmap: alternative device page map or %NULL if default memmap is used
+ * @pgmap: device page map or %NULL if not ZONE_DEVICE
*
* Generic helper function to remove section mappings and sysfs entries
* for the section of the memory we are removing. Caller needs to make
@@ -571,7 +572,7 @@ void remove_pfn_range_from_zone(struct z
* calling offline_pages().
*/
void __remove_pages(unsigned long pfn, unsigned long nr_pages,
- struct vmem_altmap *altmap)
+ struct vmem_altmap *altmap, struct dev_pagemap *pgmap)
{
const unsigned long end_pfn = pfn + nr_pages;
unsigned long cur_nr_pages;
@@ -586,7 +587,7 @@ void __remove_pages(unsigned long pfn, u
/* Select all remaining pages up to the next section boundary */
cur_nr_pages = min(end_pfn - pfn,
SECTION_ALIGN_UP(pfn + 1) - pfn);
- sparse_remove_section(pfn, cur_nr_pages, altmap);
+ sparse_remove_section(pfn, cur_nr_pages, altmap, pgmap);
}
}
@@ -1411,7 +1412,7 @@ static void remove_memory_blocks_and_alt
remove_memory_block_devices(cur_start, memblock_size);
- arch_remove_memory(cur_start, memblock_size, altmap);
+ arch_remove_memory(cur_start, memblock_size, altmap, NULL);
/* Verify that all vmemmap pages have actually been freed. */
WARN(altmap->alloc, "Altmap not fully unmapped");
@@ -1456,7 +1457,7 @@ static int create_altmaps_and_memory_blo
ret = create_memory_block_devices(cur_start, memblock_size,
params.altmap, group);
if (ret) {
- arch_remove_memory(cur_start, memblock_size, params.altmap);
+ arch_remove_memory(cur_start, memblock_size, params.altmap, NULL);
kfree(params.altmap);
goto out;
}
@@ -1534,7 +1535,7 @@ int add_memory_resource(int nid, struct
/* create memory block devices after memory was added */
ret = create_memory_block_devices(start, size, NULL, group);
if (ret) {
- arch_remove_memory(start, size, params.altmap);
+ arch_remove_memory(start, size, params.altmap, NULL);
goto error;
}
}
@@ -2273,7 +2274,7 @@ static int try_remove_memory(u64 start,
* No altmaps present, do the removal directly
*/
remove_memory_block_devices(start, size);
- arch_remove_memory(start, size, NULL);
+ arch_remove_memory(start, size, NULL, NULL);
} else {
/* all memblocks in the range have altmaps */
remove_memory_blocks_and_altmaps(start, size);
--- a/mm/memremap.c
+++ b/mm/memremap.c
@@ -122,10 +122,10 @@ static void pageunmap_range(struct dev_p
PHYS_PFN(range_len(range)));
if (pgmap->type == MEMORY_DEVICE_PRIVATE) {
__remove_pages(PHYS_PFN(range->start),
- PHYS_PFN(range_len(range)), NULL);
+ PHYS_PFN(range_len(range)), NULL, pgmap);
} else {
arch_remove_memory(range->start, range_len(range),
- pgmap_altmap(pgmap));
+ pgmap_altmap(pgmap), pgmap);
kasan_remove_zero_shadow(__va(range->start), range_len(range));
}
mem_hotplug_done();
--- a/mm/mm_init.c
+++ b/mm/mm_init.c
@@ -1835,7 +1835,7 @@ void __init free_area_init(unsigned long
pr_info(" node %3d: [mem %#018Lx-%#018Lx]\n", nid,
(u64)start_pfn << PAGE_SHIFT,
((u64)end_pfn << PAGE_SHIFT) - 1);
- subsection_map_init(start_pfn, end_pfn - start_pfn);
+ sparse_init_subsection_map(start_pfn, end_pfn - start_pfn);
}
/* Initialise every node */
--- a/mm/sparse-vmemmap.c
+++ b/mm/sparse-vmemmap.c
@@ -31,6 +31,8 @@
#include <asm/dma.h>
+#include "internal.h"
+
/*
* Allocate a block of memory to be used to back the virtual memory map
* or to back the page tables that are used to create the mapping.
@@ -476,3 +478,311 @@ struct page * __meminit __populate_secti
return pfn_to_page(pfn);
}
+
+static void subsection_mask_set(unsigned long *map, unsigned long pfn,
+ unsigned long nr_pages)
+{
+ int idx = subsection_map_index(pfn);
+ int end = subsection_map_index(pfn + nr_pages - 1);
+
+ bitmap_set(map, idx, end - idx + 1);
+}
+
+void __init sparse_init_subsection_map(unsigned long pfn, unsigned long nr_pages)
+{
+ int end_sec_nr = pfn_to_section_nr(pfn + nr_pages - 1);
+ unsigned long nr, start_sec_nr = pfn_to_section_nr(pfn);
+
+ for (nr = start_sec_nr; nr <= end_sec_nr; nr++) {
+ struct mem_section *ms;
+ unsigned long pfns;
+
+ pfns = min(nr_pages, PAGES_PER_SECTION
+ - (pfn & ~PAGE_SECTION_MASK));
+ ms = __nr_to_section(nr);
+ subsection_mask_set(ms->usage->subsection_map, pfn, pfns);
+
+ pr_debug("%s: sec: %lu pfns: %lu set(%d, %d)\n", __func__, nr,
+ pfns, subsection_map_index(pfn),
+ subsection_map_index(pfn + pfns - 1));
+
+ pfn += pfns;
+ nr_pages -= pfns;
+ }
+}
+
+#ifdef CONFIG_MEMORY_HOTPLUG
+
+/* Mark all memory sections within the pfn range as online */
+void online_mem_sections(unsigned long start_pfn, unsigned long end_pfn)
+{
+ unsigned long pfn;
+
+ for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
+ unsigned long section_nr = pfn_to_section_nr(pfn);
+ struct mem_section *ms = __nr_to_section(section_nr);
+
+ ms->section_mem_map |= SECTION_IS_ONLINE;
+ }
+}
+
+/* Mark all memory sections within the pfn range as offline */
+void offline_mem_sections(unsigned long start_pfn, unsigned long end_pfn)
+{
+ unsigned long pfn;
+
+ for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
+ unsigned long section_nr = pfn_to_section_nr(pfn);
+ struct mem_section *ms = __nr_to_section(section_nr);
+
+ ms->section_mem_map &= ~SECTION_IS_ONLINE;
+ }
+}
+
+static struct page * __meminit populate_section_memmap(unsigned long pfn,
+ unsigned long nr_pages, int nid, struct vmem_altmap *altmap,
+ struct dev_pagemap *pgmap)
+{
+ struct page *page = __populate_section_memmap(pfn, nr_pages, nid, altmap,
+ pgmap);
+
+ memmap_pages_add(DIV_ROUND_UP(nr_pages * sizeof(struct page), PAGE_SIZE));
+
+ return page;
+}
+
+static void depopulate_section_memmap(unsigned long pfn, unsigned long nr_pages,
+ struct vmem_altmap *altmap, struct dev_pagemap *pgmap)
+{
+ unsigned long start = (unsigned long) pfn_to_page(pfn);
+ unsigned long end = start + nr_pages * sizeof(struct page);
+
+ memmap_pages_add(-1L * (DIV_ROUND_UP(nr_pages * sizeof(struct page), PAGE_SIZE)));
+ vmemmap_free(start, end, altmap);
+}
+
+static void free_map_bootmem(struct page *memmap)
+{
+ unsigned long start = (unsigned long)memmap;
+ unsigned long end = (unsigned long)(memmap + PAGES_PER_SECTION);
+
+ memmap_boot_pages_add(-1L * (DIV_ROUND_UP(PAGES_PER_SECTION * sizeof(struct page),
+ PAGE_SIZE)));
+ vmemmap_free(start, end, NULL);
+}
+
+static int clear_subsection_map(unsigned long pfn, unsigned long nr_pages)
+{
+ DECLARE_BITMAP(map, SUBSECTIONS_PER_SECTION) = { 0 };
+ DECLARE_BITMAP(tmp, SUBSECTIONS_PER_SECTION) = { 0 };
+ struct mem_section *ms = __pfn_to_section(pfn);
+ unsigned long *subsection_map = ms->usage
+ ? &ms->usage->subsection_map[0] : NULL;
+
+ subsection_mask_set(map, pfn, nr_pages);
+ if (subsection_map)
+ bitmap_and(tmp, map, subsection_map, SUBSECTIONS_PER_SECTION);
+
+ if (WARN(!subsection_map || !bitmap_equal(tmp, map, SUBSECTIONS_PER_SECTION),
+ "section already deactivated (%#lx + %ld)\n",
+ pfn, nr_pages))
+ return -EINVAL;
+
+ bitmap_xor(subsection_map, map, subsection_map, SUBSECTIONS_PER_SECTION);
+ return 0;
+}
+
+static bool is_subsection_map_empty(struct mem_section *ms)
+{
+ return bitmap_empty(&ms->usage->subsection_map[0],
+ SUBSECTIONS_PER_SECTION);
+}
+
+static int fill_subsection_map(unsigned long pfn, unsigned long nr_pages)
+{
+ struct mem_section *ms = __pfn_to_section(pfn);
+ DECLARE_BITMAP(map, SUBSECTIONS_PER_SECTION) = { 0 };
+ unsigned long *subsection_map;
+ int rc = 0;
+
+ subsection_mask_set(map, pfn, nr_pages);
+
+ subsection_map = &ms->usage->subsection_map[0];
+
+ if (bitmap_empty(map, SUBSECTIONS_PER_SECTION))
+ rc = -EINVAL;
+ else if (bitmap_intersects(map, subsection_map, SUBSECTIONS_PER_SECTION))
+ rc = -EEXIST;
+ else
+ bitmap_or(subsection_map, map, subsection_map,
+ SUBSECTIONS_PER_SECTION);
+
+ return rc;
+}
+
+/*
+ * To deactivate a memory region, there are 3 cases to handle:
+ *
+ * 1. deactivation of a partial hot-added section:
+ * a) section was present at memory init.
+ * b) section was hot-added post memory init.
+ * 2. deactivation of a complete hot-added section.
+ * 3. deactivation of a complete section from memory init.
+ *
+ * For 1, when subsection_map does not empty we will not be freeing the
+ * usage map, but still need to free the vmemmap range.
+ */
+static void section_deactivate(unsigned long pfn, unsigned long nr_pages,
+ struct vmem_altmap *altmap, struct dev_pagemap *pgmap)
+{
+ struct mem_section *ms = __pfn_to_section(pfn);
+ bool section_is_early = early_section(ms);
+ struct page *memmap = NULL;
+ bool empty;
+
+ if (clear_subsection_map(pfn, nr_pages))
+ return;
+
+ empty = is_subsection_map_empty(ms);
+ if (empty) {
+ /*
+ * Mark the section invalid so that valid_section()
+ * return false. This prevents code from dereferencing
+ * ms->usage array.
+ */
+ ms->section_mem_map &= ~SECTION_HAS_MEM_MAP;
+
+ /*
+ * When removing an early section, the usage map is kept (as the
+ * usage maps of other sections fall into the same page). It
+ * will be re-used when re-adding the section - which is then no
+ * longer an early section. If the usage map is PageReserved, it
+ * was allocated during boot.
+ */
+ if (!PageReserved(virt_to_page(ms->usage))) {
+ kfree_rcu(ms->usage, rcu);
+ WRITE_ONCE(ms->usage, NULL);
+ }
+ memmap = pfn_to_page(SECTION_ALIGN_DOWN(pfn));
+ }
+
+ /*
+ * The memmap of early sections is always fully populated. See
+ * section_activate() and pfn_valid() .
+ */
+ if (!section_is_early)
+ depopulate_section_memmap(pfn, nr_pages, altmap, pgmap);
+ else if (memmap)
+ free_map_bootmem(memmap);
+
+ if (empty)
+ ms->section_mem_map = (unsigned long)NULL;
+}
+
+static struct page * __meminit section_activate(int nid, unsigned long pfn,
+ unsigned long nr_pages, struct vmem_altmap *altmap,
+ struct dev_pagemap *pgmap)
+{
+ struct mem_section *ms = __pfn_to_section(pfn);
+ struct mem_section_usage *usage = NULL;
+ struct page *memmap;
+ int rc;
+
+ if (!ms->usage) {
+ usage = kzalloc(mem_section_usage_size(), GFP_KERNEL);
+ if (!usage)
+ return ERR_PTR(-ENOMEM);
+ ms->usage = usage;
+ }
+
+ rc = fill_subsection_map(pfn, nr_pages);
+ if (rc) {
+ if (usage)
+ ms->usage = NULL;
+ kfree(usage);
+ return ERR_PTR(rc);
+ }
+
+ /*
+ * The early init code does not consider partially populated
+ * initial sections, it simply assumes that memory will never be
+ * referenced. If we hot-add memory into such a section then we
+ * do not need to populate the memmap and can simply reuse what
+ * is already there.
+ */
+ if (nr_pages < PAGES_PER_SECTION && early_section(ms))
+ return pfn_to_page(pfn);
+
+ memmap = populate_section_memmap(pfn, nr_pages, nid, altmap, pgmap);
+ if (!memmap) {
+ section_deactivate(pfn, nr_pages, altmap, pgmap);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ return memmap;
+}
+
+/**
+ * sparse_add_section - add a memory section, or populate an existing one
+ * @nid: The node to add section on
+ * @start_pfn: start pfn of the memory range
+ * @nr_pages: number of pfns to add in the section
+ * @altmap: alternate pfns to allocate the memmap backing store
+ * @pgmap: alternate compound page geometry for devmap mappings
+ *
+ * This is only intended for hotplug.
+ *
+ * Note that only VMEMMAP supports sub-section aligned hotplug,
+ * the proper alignment and size are gated by check_pfn_span().
+ *
+ *
+ * Return:
+ * * 0 - On success.
+ * * -EEXIST - Section has been present.
+ * * -ENOMEM - Out of memory.
+ */
+int __meminit sparse_add_section(int nid, unsigned long start_pfn,
+ unsigned long nr_pages, struct vmem_altmap *altmap,
+ struct dev_pagemap *pgmap)
+{
+ unsigned long section_nr = pfn_to_section_nr(start_pfn);
+ struct mem_section *ms;
+ struct page *memmap;
+ int ret;
+
+ ret = sparse_index_init(section_nr, nid);
+ if (ret < 0)
+ return ret;
+
+ memmap = section_activate(nid, start_pfn, nr_pages, altmap, pgmap);
+ if (IS_ERR(memmap))
+ return PTR_ERR(memmap);
+
+ /*
+ * Poison uninitialized struct pages in order to catch invalid flags
+ * combinations.
+ */
+ page_init_poison(memmap, sizeof(struct page) * nr_pages);
+
+ ms = __nr_to_section(section_nr);
+ __section_mark_present(ms, section_nr);
+
+ /* Align memmap to section boundary in the subsection case */
+ if (section_nr_to_pfn(section_nr) != start_pfn)
+ memmap = pfn_to_page(section_nr_to_pfn(section_nr));
+ sparse_init_one_section(ms, section_nr, memmap, ms->usage, 0);
+
+ return 0;
+}
+
+void sparse_remove_section(unsigned long pfn, unsigned long nr_pages,
+ struct vmem_altmap *altmap, struct dev_pagemap *pgmap)
+{
+ struct mem_section *ms = __pfn_to_section(pfn);
+
+ if (WARN_ON_ONCE(!valid_section(ms)))
+ return;
+
+ section_deactivate(pfn, nr_pages, altmap, pgmap);
+}
+#endif /* CONFIG_MEMORY_HOTPLUG */
--- a/mm/sparse.c
+++ b/mm/sparse.c
@@ -79,7 +79,7 @@ static noinline struct mem_section __ref
return section;
}
-static int __meminit sparse_index_init(unsigned long section_nr, int nid)
+int __meminit sparse_index_init(unsigned long section_nr, int nid)
{
unsigned long root = SECTION_NR_TO_ROOT(section_nr);
struct mem_section *section;
@@ -103,7 +103,7 @@ static int __meminit sparse_index_init(u
return 0;
}
#else /* !SPARSEMEM_EXTREME */
-static inline int sparse_index_init(unsigned long section_nr, int nid)
+int sparse_index_init(unsigned long section_nr, int nid)
{
return 0;
}
@@ -161,14 +161,6 @@ static void __meminit mminit_validate_me
* those loops early.
*/
unsigned long __highest_present_section_nr;
-static void __section_mark_present(struct mem_section *ms,
- unsigned long section_nr)
-{
- if (section_nr > __highest_present_section_nr)
- __highest_present_section_nr = section_nr;
-
- ms->section_mem_map |= SECTION_MARKED_PRESENT;
-}
#define for_each_present_section_nr(start, section_nr) \
for (section_nr = next_present_section_nr(start-1); \
@@ -180,44 +172,6 @@ static inline unsigned long first_presen
return next_present_section_nr(-1);
}
-#ifdef CONFIG_SPARSEMEM_VMEMMAP
-static void subsection_mask_set(unsigned long *map, unsigned long pfn,
- unsigned long nr_pages)
-{
- int idx = subsection_map_index(pfn);
- int end = subsection_map_index(pfn + nr_pages - 1);
-
- bitmap_set(map, idx, end - idx + 1);
-}
-
-void __init subsection_map_init(unsigned long pfn, unsigned long nr_pages)
-{
- int end_sec_nr = pfn_to_section_nr(pfn + nr_pages - 1);
- unsigned long nr, start_sec_nr = pfn_to_section_nr(pfn);
-
- for (nr = start_sec_nr; nr <= end_sec_nr; nr++) {
- struct mem_section *ms;
- unsigned long pfns;
-
- pfns = min(nr_pages, PAGES_PER_SECTION
- - (pfn & ~PAGE_SECTION_MASK));
- ms = __nr_to_section(nr);
- subsection_mask_set(ms->usage->subsection_map, pfn, pfns);
-
- pr_debug("%s: sec: %lu pfns: %lu set(%d, %d)\n", __func__, nr,
- pfns, subsection_map_index(pfn),
- subsection_map_index(pfn + pfns - 1));
-
- pfn += pfns;
- nr_pages -= pfns;
- }
-}
-#else
-void __init subsection_map_init(unsigned long pfn, unsigned long nr_pages)
-{
-}
-#endif
-
/* Record a memory area against a node. */
static void __init memory_present(int nid, unsigned long start, unsigned long end)
{
@@ -268,20 +222,6 @@ static void __init memblocks_present(voi
memory_present(nid, start, end);
}
-/*
- * Subtle, we encode the real pfn into the mem_map such that
- * the identity pfn - section_mem_map will return the actual
- * physical page frame number.
- */
-static unsigned long sparse_encode_mem_map(struct page *mem_map, unsigned long pnum)
-{
- unsigned long coded_mem_map =
- (unsigned long)(mem_map - (section_nr_to_pfn(pnum)));
- BUILD_BUG_ON(SECTION_MAP_LAST_BIT > PFN_SECTION_SHIFT);
- BUG_ON(coded_mem_map & ~SECTION_MAP_MASK);
- return coded_mem_map;
-}
-
#ifdef CONFIG_MEMORY_HOTPLUG
/*
* Decode mem_map from the coded memmap
@@ -294,16 +234,6 @@ struct page *sparse_decode_mem_map(unsig
}
#endif /* CONFIG_MEMORY_HOTPLUG */
-static void __meminit sparse_init_one_section(struct mem_section *ms,
- unsigned long pnum, struct page *mem_map,
- struct mem_section_usage *usage, unsigned long flags)
-{
- ms->section_mem_map &= ~SECTION_MAP_MASK;
- ms->section_mem_map |= sparse_encode_mem_map(mem_map, pnum)
- | SECTION_HAS_MEM_MAP | flags;
- ms->usage = usage;
-}
-
static unsigned long usemap_size(void)
{
return BITS_TO_LONGS(SECTION_BLOCKFLAGS_BITS) * sizeof(unsigned long);
@@ -587,6 +517,7 @@ void __init sparse_init(void)
vmemmap_populate_print_last();
}
+#ifndef CONFIG_SPARSEMEM_VMEMMAP
#ifdef CONFIG_MEMORY_HOTPLUG
/* Mark all memory sections within the pfn range as online */
@@ -930,7 +861,6 @@ int __meminit sparse_add_section(int nid
page_init_poison(memmap, sizeof(struct page) * nr_pages);
ms = __nr_to_section(section_nr);
- set_section_nid(section_nr, nid);
__section_mark_present(ms, section_nr);
/* Align memmap to section boundary in the subsection case */
@@ -942,7 +872,8 @@ int __meminit sparse_add_section(int nid
}
void sparse_remove_section(unsigned long pfn, unsigned long nr_pages,
- struct vmem_altmap *altmap)
+ struct vmem_altmap *altmap,
+ struct dev_pagemap *pgmap)
{
struct mem_section *ms = __pfn_to_section(pfn);
@@ -952,3 +883,4 @@ void sparse_remove_section(unsigned long
section_deactivate(pfn, nr_pages, altmap);
}
#endif /* CONFIG_MEMORY_HOTPLUG */
+#endif /* !CONFIG_SPARSEMEM_VMEMMAP */
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 524/602] mm/sparse-vmemmap: fix DAX vmemmap accounting with optimization
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (522 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 523/602] mm: prepare to move subsection_map_init() to mm/sparse-vmemmap.c Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 525/602] thunderbolt: Keep XDomain reference during the lifetime of a service Greg Kroah-Hartman
` (81 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Muchun Song,
Mike Rapoport (Microsoft), Oscar Salvador,
David Hildenbrand (Arm), Liam R. Howlett, Aneesh Kumar K.V,
Joao Martins, Lorenzo Stoakes, Madhavan Srinivasan,
Michael Ellerman, Michal Hocko, Nicholas Piggin,
Suren Baghdasaryan, Vlastimil Babka, Andrew Morton, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Muchun Song <songmuchun@bytedance.com>
[ Upstream commit 721a73e30c9e3e8fcffe1725bcede1bbd20b4918 ]
When vmemmap optimization is enabled for DAX, the nr_memmap_pages counter
in /proc/vmstat is incorrect. The current code always accounts for the
full, non-optimized vmemmap size, but vmemmap optimization reduces the
actual number of vmemmap pages by reusing tail pages. This causes the
system to overcount vmemmap usage, leading to inaccurate page statistics
in /proc/vmstat.
Fix this by introducing section_nr_vmemmap_pages(), which returns the
exact vmemmap page count for a given pfn range based on whether
optimization is in effect.
Link: https://lore.kernel.org/20260428081855.1249045-5-songmuchun@bytedance.com
Fixes: 15995a352474 ("mm: report per-page metadata information")
Signed-off-by: Muchun Song <songmuchun@bytedance.com>
Acked-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Acked-by: Oscar Salvador <osalvador@suse.de>
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
Acked-by: Liam R. Howlett <liam@infradead.org>
Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.ibm.com>
Cc: Joao Martins <joao.m.martins@oracle.com>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
mm/sparse-vmemmap.c | 34 ++++++++++++++++++++++++++++++----
1 file changed, 30 insertions(+), 4 deletions(-)
--- a/mm/sparse-vmemmap.c
+++ b/mm/sparse-vmemmap.c
@@ -539,6 +539,31 @@ void offline_mem_sections(unsigned long
}
}
+static int __meminit section_nr_vmemmap_pages(unsigned long pfn, unsigned long nr_pages,
+ struct vmem_altmap *altmap, struct dev_pagemap *pgmap)
+{
+ const unsigned int order = pgmap ? pgmap->vmemmap_shift : 0;
+ const unsigned long pages_per_compound = 1UL << order;
+
+ VM_WARN_ON_ONCE(!IS_ALIGNED(pfn | nr_pages, PAGES_PER_SUBSECTION));
+ VM_WARN_ON_ONCE(nr_pages > PAGES_PER_SECTION);
+
+ if (!vmemmap_can_optimize(altmap, pgmap))
+ return DIV_ROUND_UP(nr_pages * sizeof(struct page), PAGE_SIZE);
+
+ if (order < PFN_SECTION_SHIFT) {
+ VM_WARN_ON_ONCE(!IS_ALIGNED(pfn | nr_pages, pages_per_compound));
+ return VMEMMAP_RESERVE_NR * nr_pages / pages_per_compound;
+ }
+
+ VM_WARN_ON_ONCE(!IS_ALIGNED(pfn | nr_pages, PAGES_PER_SECTION));
+
+ if (IS_ALIGNED(pfn, pages_per_compound))
+ return VMEMMAP_RESERVE_NR;
+
+ return 0;
+}
+
static struct page * __meminit populate_section_memmap(unsigned long pfn,
unsigned long nr_pages, int nid, struct vmem_altmap *altmap,
struct dev_pagemap *pgmap)
@@ -546,7 +571,7 @@ static struct page * __meminit populate_
struct page *page = __populate_section_memmap(pfn, nr_pages, nid, altmap,
pgmap);
- memmap_pages_add(DIV_ROUND_UP(nr_pages * sizeof(struct page), PAGE_SIZE));
+ memmap_pages_add(section_nr_vmemmap_pages(pfn, nr_pages, altmap, pgmap));
return page;
}
@@ -557,7 +582,7 @@ static void depopulate_section_memmap(un
unsigned long start = (unsigned long) pfn_to_page(pfn);
unsigned long end = start + nr_pages * sizeof(struct page);
- memmap_pages_add(-1L * (DIV_ROUND_UP(nr_pages * sizeof(struct page), PAGE_SIZE)));
+ memmap_pages_add(-section_nr_vmemmap_pages(pfn, nr_pages, altmap, pgmap));
vmemmap_free(start, end, altmap);
}
@@ -565,9 +590,10 @@ static void free_map_bootmem(struct page
{
unsigned long start = (unsigned long)memmap;
unsigned long end = (unsigned long)(memmap + PAGES_PER_SECTION);
+ unsigned long pfn = page_to_pfn(memmap);
- memmap_boot_pages_add(-1L * (DIV_ROUND_UP(PAGES_PER_SECTION * sizeof(struct page),
- PAGE_SIZE)));
+ memmap_boot_pages_add(-section_nr_vmemmap_pages(pfn, PAGES_PER_SECTION,
+ NULL, NULL));
vmemmap_free(start, end, NULL);
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 525/602] thunderbolt: Keep XDomain reference during the lifetime of a service
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (523 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 524/602] mm/sparse-vmemmap: fix DAX vmemmap accounting with optimization Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 526/602] thunderbolt: Remove service debugfs entries during unregister Greg Kroah-Hartman
` (80 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Mika Westerberg, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mika Westerberg <mika.westerberg@linux.intel.com>
[ Upstream commit 8b4060998637f06975fceee9b73845d8672d411e ]
This is needed because we release the service ID in tb_service_release()
and the ID array is owned by the parent XDomain.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Stable-dep-of: 2c5d2d3c3f70 ("thunderbolt: Prevent XDomain delayed work use-after-free on disconnect")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/thunderbolt/xdomain.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/thunderbolt/xdomain.c
+++ b/drivers/thunderbolt/xdomain.c
@@ -1008,6 +1008,7 @@ static void tb_service_release(struct de
ida_free(&xd->service_ids, svc->id);
kfree(svc->key);
kfree(svc);
+ tb_xdomain_put(xd);
}
const struct device_type tb_service_type = {
@@ -1116,7 +1117,7 @@ static void enumerate_services(struct tb
svc->id = id;
svc->dev.bus = &tb_bus_type;
svc->dev.type = &tb_service_type;
- svc->dev.parent = &xd->dev;
+ svc->dev.parent = get_device(&xd->dev);
dev_set_name(&svc->dev, "%s.%d", dev_name(&xd->dev), svc->id);
tb_service_debugfs_init(svc);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 526/602] thunderbolt: Remove service debugfs entries during unregister
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (524 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 525/602] thunderbolt: Keep XDomain reference during the lifetime of a service Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 527/602] thunderbolt: Remove XDomain from the bus without holding tb->lock Greg Kroah-Hartman
` (79 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Mika Westerberg, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mika Westerberg <mika.westerberg@linux.intel.com>
[ Upstream commit 4d5fc3f4068568dfcb8cbe2852b4adc56394aa26 ]
We add them as part of the register path so to keep it symmetric remove
them as part of the unregister path. This also removes them even if the
service itself is not yet released (but is unregistered), thus allowing
new register with the same service name to happen.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Stable-dep-of: 2c5d2d3c3f70 ("thunderbolt: Prevent XDomain delayed work use-after-free on disconnect")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/thunderbolt/xdomain.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
--- a/drivers/thunderbolt/xdomain.c
+++ b/drivers/thunderbolt/xdomain.c
@@ -1004,7 +1004,6 @@ static void tb_service_release(struct de
struct tb_service *svc = container_of(dev, struct tb_service, dev);
struct tb_xdomain *xd = tb_service_parent(svc);
- tb_service_debugfs_remove(svc);
ida_free(&xd->service_ids, svc->id);
kfree(svc->key);
kfree(svc);
@@ -1019,6 +1018,14 @@ const struct device_type tb_service_type
};
EXPORT_SYMBOL_GPL(tb_service_type);
+static void __unregister_service(struct device *dev)
+{
+ struct tb_service *svc = tb_to_service(dev);
+
+ tb_service_debugfs_remove(svc);
+ device_unregister(&svc->dev);
+}
+
static int remove_missing_service(struct device *dev, void *data)
{
struct tb_xdomain *xd = data;
@@ -1030,7 +1037,7 @@ static int remove_missing_service(struct
if (!tb_property_find(xd->remote_properties, svc->key,
TB_PROPERTY_TYPE_DIRECTORY))
- device_unregister(dev);
+ __unregister_service(dev);
return 0;
}
@@ -1123,6 +1130,7 @@ static void enumerate_services(struct tb
tb_service_debugfs_init(svc);
if (device_register(&svc->dev)) {
+ tb_service_debugfs_remove(svc);
put_device(&svc->dev);
break;
}
@@ -2053,7 +2061,7 @@ void tb_xdomain_add(struct tb_xdomain *x
static int unregister_service(struct device *dev, void *data)
{
- device_unregister(dev);
+ __unregister_service(dev);
return 0;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 527/602] thunderbolt: Remove XDomain from the bus without holding tb->lock
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (525 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 526/602] thunderbolt: Remove service debugfs entries during unregister Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 528/602] thunderbolt: Prevent XDomain delayed work use-after-free on disconnect Greg Kroah-Hartman
` (78 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Mika Westerberg, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mika Westerberg <mika.westerberg@linux.intel.com>
[ Upstream commit a8937f35cf39c39c64325aa84d0463d866850857 ]
Currently we call device_unregister() for services and the XDomain
itself with tb->lock held. This prevents the service drivers from
calling any functions that may take it. For this reason separate
removing the XDomain from the topology data structures (where we need
the lock) from unregistering the device from the bus (where remove
callbacks of the drivers are being called).
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Stable-dep-of: 2c5d2d3c3f70 ("thunderbolt: Prevent XDomain delayed work use-after-free on disconnect")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/thunderbolt/debugfs.c | 2 +
drivers/thunderbolt/domain.c | 30 +++++++++++++++++++++
drivers/thunderbolt/icm.c | 5 +++
drivers/thunderbolt/switch.c | 14 +++++++++
drivers/thunderbolt/tb.c | 59 ++++++++++++++++++++----------------------
drivers/thunderbolt/tb.h | 2 +
drivers/thunderbolt/xdomain.c | 53 +++++++++++++++++++++++--------------
7 files changed, 115 insertions(+), 50 deletions(-)
--- a/drivers/thunderbolt/debugfs.c
+++ b/drivers/thunderbolt/debugfs.c
@@ -1508,6 +1508,8 @@ static void margining_port_remove(struct
if (!port->usb4)
return;
+ if (!port->usb4->margining)
+ return;
snprintf(dir_name, sizeof(dir_name), "port%d", port->port);
parent = debugfs_lookup(dir_name, port->sw->debugfs_dir);
--- a/drivers/thunderbolt/domain.c
+++ b/drivers/thunderbolt/domain.c
@@ -871,6 +871,36 @@ int tb_domain_disconnect_all_paths(struc
return bus_for_each_dev(&tb_bus_type, NULL, tb, disconnect_xdomain);
}
+struct unregister_context {
+ const struct tb *tb;
+ int n;
+};
+
+static int unregister_unplugged_xdomain(struct device *dev, void *data)
+{
+ struct unregister_context *ctx = data;
+ struct tb_xdomain *xd;
+
+ xd = tb_to_xdomain(dev);
+ if (xd && xd->tb == ctx->tb && xd->is_unplugged) {
+ tb_xdomain_unregister(xd);
+ ctx->n++;
+ }
+ return 0;
+}
+
+int tb_domain_unregister_unplugged_xdomains(struct tb *tb)
+{
+ struct unregister_context ctx;
+
+ ctx.tb = tb_domain_get(tb);
+ ctx.n = 0;
+ bus_for_each_dev(&tb_bus_type, NULL, &ctx, unregister_unplugged_xdomain);
+ tb_domain_put(tb);
+
+ return ctx.n;
+}
+
int tb_domain_init(void)
{
int ret;
--- a/drivers/thunderbolt/icm.c
+++ b/drivers/thunderbolt/icm.c
@@ -713,6 +713,7 @@ static void remove_xdomain(struct tb_xdo
sw = tb_to_switch(xd->dev.parent);
tb_port_at(xd->route, sw)->xdomain = NULL;
+ xd->is_unplugged = true;
tb_xdomain_remove(xd);
}
@@ -1728,6 +1729,8 @@ static void icm_handle_notification(stru
kfree(n->pkg);
kfree(n);
+
+ tb_domain_unregister_unplugged_xdomains(tb);
}
static void icm_handle_event(struct tb *tb, enum tb_cfg_pkg_type type,
@@ -2078,6 +2081,8 @@ static void icm_rescan_work(struct work_
if (tb->root_switch)
icm_free_unplugged_children(tb->root_switch);
mutex_unlock(&tb->lock);
+
+ tb_domain_unregister_unplugged_xdomains(tb);
}
static void icm_complete(struct tb *tb)
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -3554,6 +3554,20 @@ int tb_switch_resume(struct tb_switch *s
tb_port_warn(port,
"lost during suspend, disconnecting\n");
tb_sw_set_unplugged(port->remote->sw);
+ } else if (port->xdomain) {
+ /*
+ * If the user replaced the XDomain with
+ * another router, this will succeed in
+ * which case we must remove the XDomain
+ * before adding the new router.
+ */
+ err = tb_cfg_get_upstream_port(sw->tb->ctl,
+ port->xdomain->route);
+ if (err > 0) {
+ tb_port_warn(port,
+ "XDomain was disconnected\n");
+ port->xdomain->is_unplugged = true;
+ }
}
}
}
--- a/drivers/thunderbolt/tb.c
+++ b/drivers/thunderbolt/tb.c
@@ -2450,6 +2450,8 @@ put_sw:
out:
mutex_unlock(&tb->lock);
+ tb_domain_unregister_unplugged_xdomains(tb);
+
pm_runtime_mark_last_busy(&tb->dev);
pm_runtime_put_autosuspend(&tb->dev);
@@ -3008,6 +3010,24 @@ static void tb_restore_children(struct t
}
}
+static void tb_free_unplugged_xdomains(struct tb_switch *sw)
+{
+ struct tb_port *port;
+
+ tb_switch_for_each_port(sw, port) {
+ if (tb_is_upstream_port(port))
+ continue;
+ if (port->xdomain && port->xdomain->is_unplugged) {
+ tb_retimer_remove_all(port);
+ tb_xdomain_remove(port->xdomain);
+ tb_port_unconfigure_xdomain(port);
+ port->xdomain = NULL;
+ } else if (port->remote) {
+ tb_free_unplugged_xdomains(port->remote->sw);
+ }
+ }
+}
+
static int tb_resume_noirq(struct tb *tb)
{
struct tb_cm *tcm = tb_priv(tb);
@@ -3027,6 +3047,7 @@ static int tb_resume_noirq(struct tb *tb
tb_switch_resume(tb->root_switch, false);
tb_free_invalid_tunnels(tb);
tb_free_unplugged_children(tb->root_switch);
+ tb_free_unplugged_xdomains(tb->root_switch);
tb_restore_children(tb->root_switch);
/*
@@ -3069,28 +3090,6 @@ static int tb_resume_noirq(struct tb *tb
return 0;
}
-static int tb_free_unplugged_xdomains(struct tb_switch *sw)
-{
- struct tb_port *port;
- int ret = 0;
-
- tb_switch_for_each_port(sw, port) {
- if (tb_is_upstream_port(port))
- continue;
- if (port->xdomain && port->xdomain->is_unplugged) {
- tb_retimer_remove_all(port);
- tb_xdomain_remove(port->xdomain);
- tb_port_unconfigure_xdomain(port);
- port->xdomain = NULL;
- ret++;
- } else if (port->remote) {
- ret += tb_free_unplugged_xdomains(port->remote->sw);
- }
- }
-
- return ret;
-}
-
static int tb_freeze_noirq(struct tb *tb)
{
struct tb_cm *tcm = tb_priv(tb);
@@ -3110,14 +3109,14 @@ static int tb_thaw_noirq(struct tb *tb)
static void tb_complete(struct tb *tb)
{
/*
- * Release any unplugged XDomains and if there is a case where
+ * Unregister unplugged XDomains and if there is a case where
* another domain is swapped in place of unplugged XDomain we
* need to run another rescan.
*/
- mutex_lock(&tb->lock);
- if (tb_free_unplugged_xdomains(tb->root_switch))
- tb_scan_switch(tb->root_switch);
- mutex_unlock(&tb->lock);
+ if (tb_domain_unregister_unplugged_xdomains(tb)) {
+ scoped_guard(mutex, &tb->lock)
+ tb_scan_switch(tb->root_switch);
+ }
}
static int tb_runtime_suspend(struct tb *tb)
@@ -3144,11 +3143,11 @@ static void tb_remove_work(struct work_s
struct tb *tb = tcm_to_tb(tcm);
mutex_lock(&tb->lock);
- if (tb->root_switch) {
+ if (tb->root_switch)
tb_free_unplugged_children(tb->root_switch);
- tb_free_unplugged_xdomains(tb->root_switch);
- }
mutex_unlock(&tb->lock);
+
+ tb_free_unplugged_xdomains(tb->root_switch);
}
static int tb_runtime_resume(struct tb *tb)
--- a/drivers/thunderbolt/tb.h
+++ b/drivers/thunderbolt/tb.h
@@ -786,6 +786,7 @@ int tb_domain_disconnect_xdomain_paths(s
int transmit_path, int transmit_ring,
int receive_path, int receive_ring);
int tb_domain_disconnect_all_paths(struct tb *tb);
+int tb_domain_unregister_unplugged_xdomains(struct tb *tb);
static inline struct tb *tb_domain_get(struct tb *tb)
{
@@ -1233,6 +1234,7 @@ struct tb_xdomain *tb_xdomain_alloc(stru
const uuid_t *remote_uuid);
void tb_xdomain_add(struct tb_xdomain *xd);
void tb_xdomain_remove(struct tb_xdomain *xd);
+void tb_xdomain_unregister(struct tb_xdomain *xd);
struct tb_xdomain *tb_xdomain_find_by_link_depth(struct tb *tb, u8 link,
u8 depth);
--- a/drivers/thunderbolt/xdomain.c
+++ b/drivers/thunderbolt/xdomain.c
@@ -2066,41 +2066,54 @@ static int unregister_service(struct dev
}
/**
- * tb_xdomain_remove() - Remove XDomain from the bus
+ * tb_xdomain_remove() - Remove XDomain
* @xd: XDomain to remove
*
- * This will stop all ongoing configuration work and remove the XDomain
- * along with any services from the bus. When the last reference to @xd
- * is released the object will be released as well.
+ * This will stop all ongoing configuration work. XDomain is not removed
+ * from the bus if it was added. That needs to be done separately by
+ * calling tb_xdomain_unregister().
+ *
+ * Called with @tb->lock held.
*/
void tb_xdomain_remove(struct tb_xdomain *xd)
{
tb_xdomain_debugfs_remove(xd);
-
stop_handshake(xd);
-
- device_for_each_child_reverse(&xd->dev, xd, unregister_service);
-
tb_xdomain_link_exit(xd);
- /*
- * Undo runtime PM here explicitly because it is possible that
- * the XDomain was never added to the bus and thus device_del()
- * is not called for it (device_del() would handle this otherwise).
- */
- pm_runtime_disable(&xd->dev);
- pm_runtime_put_noidle(&xd->dev);
- pm_runtime_set_suspended(&xd->dev);
-
if (!device_is_registered(&xd->dev)) {
+ /*
+ * Undo runtime PM here explicitly because it is
+ * possible that the XDomain was never added to the bus
+ * and thus device_del() is not called for it
+ * (device_del() would handle this otherwise).
+ */
+ pm_runtime_disable(&xd->dev);
+ pm_runtime_put_noidle(&xd->dev);
+ pm_runtime_set_suspended(&xd->dev);
put_device(&xd->dev);
- } else {
- dev_info(&xd->dev, "host disconnected\n");
- device_unregister(&xd->dev);
}
}
/**
+ * tb_xdomain_unregister() - Unregister XDomain
+ * @xd: XDomain to unregister
+ *
+ * This will unregister the XDomain along with any services from the
+ * bus. When the last reference to @xd is released the object will be
+ * released as well.
+ */
+void tb_xdomain_unregister(struct tb_xdomain *xd)
+{
+ lockdep_assert_not_held(&xd->tb->lock);
+
+ device_for_each_child_reverse(&xd->dev, xd, unregister_service);
+
+ dev_info(&xd->dev, "host disconnected\n");
+ device_unregister(&xd->dev);
+}
+
+/**
* tb_xdomain_lane_bonding_enable() - Enable lane bonding on XDomain
* @xd: XDomain connection
*
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 528/602] thunderbolt: Prevent XDomain delayed work use-after-free on disconnect
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (526 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 527/602] thunderbolt: Remove XDomain from the bus without holding tb->lock Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 529/602] dma: dw-edma: Fix build warning in dw_edma_pcie_probe() Greg Kroah-Hartman
` (77 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Michael Bommarito, Mika Westerberg,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <michael.bommarito@gmail.com>
[ Upstream commit 2c5d2d3c3f70cde2565d7b279b544893a2035842 ]
tb_xdp_handle_request() runs on system_wq and queues
xd->state_work via queue_delayed_work() in three request handlers:
PROPERTIES_CHANGED_REQUEST, UUID_REQUEST (via start_handshake),
and LINK_STATE_CHANGE_REQUEST. Similarly, update_xdomain() queues
xd->properties_changed_work when local properties change.
Concurrently, tb_xdomain_remove() calls stop_handshake() which does
cancel_delayed_work_sync() on both delayed works. Later,
tb_xdomain_unregister() calls device_unregister() which eventually
frees the xdomain. Since commit 559c1e1e0134 ("thunderbolt: Run
tb_xdp_handle_request() in system workqueue") moved the request
handler off tb->wq, the handler and the remove path are no longer
serialized. If queue_delayed_work() executes after
cancel_delayed_work_sync() but before the xdomain is freed, the
delayed work fires on a freed object.
Add xd->removing that tb_xdomain_remove() sets under xd->lock
before calling stop_handshake(). Each external queue site holds
the same lock and checks removing before calling
queue_delayed_work(). This provides the mutual exclusion needed:
either the queue site acquires the lock first and queues work that
the subsequent cancel will see, or the remove path acquires the
lock first and the queue site observes removing == true and skips
the queue.
Fixes: 559c1e1e0134 ("thunderbolt: Run tb_xdp_handle_request() in system workqueue")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/thunderbolt/xdomain.c | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
--- a/drivers/thunderbolt/xdomain.c
+++ b/drivers/thunderbolt/xdomain.c
@@ -905,6 +905,19 @@ void tb_unregister_service_driver(struct
}
EXPORT_SYMBOL_GPL(tb_unregister_service_driver);
+static int update_xdomain(struct device *dev, void *data)
+{
+ struct tb_xdomain *xd;
+
+ xd = tb_to_xdomain(dev);
+ if (xd) {
+ queue_delayed_work(xd->tb->wq, &xd->properties_changed_work,
+ msecs_to_jiffies(50));
+ }
+
+ return 0;
+}
+
static ssize_t key_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -2480,19 +2493,6 @@ bool tb_xdomain_handle_request(struct tb
return ret > 0;
}
-static int update_xdomain(struct device *dev, void *data)
-{
- struct tb_xdomain *xd;
-
- xd = tb_to_xdomain(dev);
- if (xd) {
- queue_delayed_work(xd->tb->wq, &xd->properties_changed_work,
- msecs_to_jiffies(50));
- }
-
- return 0;
-}
-
static void update_all_xdomains(void)
{
bus_for_each_dev(&tb_bus_type, NULL, NULL, update_xdomain);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 529/602] dma: dw-edma: Fix build warning in dw_edma_pcie_probe()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (527 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 528/602] thunderbolt: Prevent XDomain delayed work use-after-free on disconnect Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 530/602] dmaengine: dw-edma: Fix confusing cleanup.h syntax Greg Kroah-Hartman
` (76 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Abinash Singh, Manivannan Sadhasivam,
Vinod Koul, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abinash Singh <abinashlalotra@gmail.com>
[ Upstream commit 3df63fa8f2afd051848e37ef1b8299dee28d4f87 ]
The function dw_edma_pcie_probe() in dw-edma-pcie.c triggered a
frame size warning:
ld.lld:warning:
drivers/dma/dw-edma/dw-edma-pcie.c:162:0: stack frame size (1040) exceeds limit (1024) in function 'dw_edma_pcie_probe'
This patch reduces the stack usage by dynamically allocating the
`vsec_data` structure using kmalloc(), rather than placing it on
the stack. This eliminates the overflow warning and improves kernel
robustness.
Signed-off-by: Abinash Singh <abinashsinghlalotra@gmail.com>
Acked-by: Manivannan Sadhasivam <mani@kernel.org>
Link: https://lore.kernel.org/r/20250705160055.808165-1-abinashsinghlalotra@gmail.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Stable-dep-of: 11d7cfe0c119 ("dmaengine: dw-edma-pcie: Reject devices without driver data")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/dma/dw-edma/dw-edma-pcie.c | 62 +++++++++++++++++++------------------
1 file changed, 33 insertions(+), 29 deletions(-)
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -160,12 +160,16 @@ static int dw_edma_pcie_probe(struct pci
const struct pci_device_id *pid)
{
struct dw_edma_pcie_data *pdata = (void *)pid->driver_data;
- struct dw_edma_pcie_data vsec_data;
+ struct dw_edma_pcie_data *vsec_data __free(kfree) = NULL;
struct device *dev = &pdev->dev;
struct dw_edma_chip *chip;
int err, nr_irqs;
int i, mask;
+ vsec_data = kmalloc(sizeof(*vsec_data), GFP_KERNEL);
+ if (!vsec_data)
+ return -ENOMEM;
+
/* Enable PCI device */
err = pcim_enable_device(pdev);
if (err) {
@@ -173,23 +177,23 @@ static int dw_edma_pcie_probe(struct pci
return err;
}
- memcpy(&vsec_data, pdata, sizeof(struct dw_edma_pcie_data));
+ memcpy(vsec_data, pdata, sizeof(struct dw_edma_pcie_data));
/*
* Tries to find if exists a PCIe Vendor-Specific Extended Capability
* for the DMA, if one exists, then reconfigures it.
*/
- dw_edma_pcie_get_vsec_dma_data(pdev, &vsec_data);
+ dw_edma_pcie_get_vsec_dma_data(pdev, vsec_data);
/* Mapping PCI BAR regions */
- mask = BIT(vsec_data.rg.bar);
- for (i = 0; i < vsec_data.wr_ch_cnt; i++) {
- mask |= BIT(vsec_data.ll_wr[i].bar);
- mask |= BIT(vsec_data.dt_wr[i].bar);
- }
- for (i = 0; i < vsec_data.rd_ch_cnt; i++) {
- mask |= BIT(vsec_data.ll_rd[i].bar);
- mask |= BIT(vsec_data.dt_rd[i].bar);
+ mask = BIT(vsec_data->rg.bar);
+ for (i = 0; i < vsec_data->wr_ch_cnt; i++) {
+ mask |= BIT(vsec_data->ll_wr[i].bar);
+ mask |= BIT(vsec_data->dt_wr[i].bar);
+ }
+ for (i = 0; i < vsec_data->rd_ch_cnt; i++) {
+ mask |= BIT(vsec_data->ll_rd[i].bar);
+ mask |= BIT(vsec_data->dt_rd[i].bar);
}
err = pcim_iomap_regions(pdev, mask, pci_name(pdev));
if (err) {
@@ -212,7 +216,7 @@ static int dw_edma_pcie_probe(struct pci
return -ENOMEM;
/* IRQs allocation */
- nr_irqs = pci_alloc_irq_vectors(pdev, 1, vsec_data.irqs,
+ nr_irqs = pci_alloc_irq_vectors(pdev, 1, vsec_data->irqs,
PCI_IRQ_MSI | PCI_IRQ_MSIX);
if (nr_irqs < 1) {
pci_err(pdev, "fail to alloc IRQ vector (number of IRQs=%u)\n",
@@ -223,22 +227,22 @@ static int dw_edma_pcie_probe(struct pci
/* Data structure initialization */
chip->dev = dev;
- chip->mf = vsec_data.mf;
+ chip->mf = vsec_data->mf;
chip->nr_irqs = nr_irqs;
chip->ops = &dw_edma_pcie_plat_ops;
- chip->ll_wr_cnt = vsec_data.wr_ch_cnt;
- chip->ll_rd_cnt = vsec_data.rd_ch_cnt;
+ chip->ll_wr_cnt = vsec_data->wr_ch_cnt;
+ chip->ll_rd_cnt = vsec_data->rd_ch_cnt;
- chip->reg_base = pcim_iomap_table(pdev)[vsec_data.rg.bar];
+ chip->reg_base = pcim_iomap_table(pdev)[vsec_data->rg.bar];
if (!chip->reg_base)
return -ENOMEM;
for (i = 0; i < chip->ll_wr_cnt; i++) {
struct dw_edma_region *ll_region = &chip->ll_region_wr[i];
struct dw_edma_region *dt_region = &chip->dt_region_wr[i];
- struct dw_edma_block *ll_block = &vsec_data.ll_wr[i];
- struct dw_edma_block *dt_block = &vsec_data.dt_wr[i];
+ struct dw_edma_block *ll_block = &vsec_data->ll_wr[i];
+ struct dw_edma_block *dt_block = &vsec_data->dt_wr[i];
ll_region->vaddr.io = pcim_iomap_table(pdev)[ll_block->bar];
if (!ll_region->vaddr.io)
@@ -262,8 +266,8 @@ static int dw_edma_pcie_probe(struct pci
for (i = 0; i < chip->ll_rd_cnt; i++) {
struct dw_edma_region *ll_region = &chip->ll_region_rd[i];
struct dw_edma_region *dt_region = &chip->dt_region_rd[i];
- struct dw_edma_block *ll_block = &vsec_data.ll_rd[i];
- struct dw_edma_block *dt_block = &vsec_data.dt_rd[i];
+ struct dw_edma_block *ll_block = &vsec_data->ll_rd[i];
+ struct dw_edma_block *dt_block = &vsec_data->dt_rd[i];
ll_region->vaddr.io = pcim_iomap_table(pdev)[ll_block->bar];
if (!ll_region->vaddr.io)
@@ -295,31 +299,31 @@ static int dw_edma_pcie_probe(struct pci
pci_dbg(pdev, "Version:\tUnknown (0x%x)\n", chip->mf);
pci_dbg(pdev, "Registers:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p)\n",
- vsec_data.rg.bar, vsec_data.rg.off, vsec_data.rg.sz,
+ vsec_data->rg.bar, vsec_data->rg.off, vsec_data->rg.sz,
chip->reg_base);
for (i = 0; i < chip->ll_wr_cnt; i++) {
pci_dbg(pdev, "L. List:\tWRITE CH%.2u, BAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
- i, vsec_data.ll_wr[i].bar,
- vsec_data.ll_wr[i].off, chip->ll_region_wr[i].sz,
+ i, vsec_data->ll_wr[i].bar,
+ vsec_data->ll_wr[i].off, chip->ll_region_wr[i].sz,
chip->ll_region_wr[i].vaddr.io, &chip->ll_region_wr[i].paddr);
pci_dbg(pdev, "Data:\tWRITE CH%.2u, BAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
- i, vsec_data.dt_wr[i].bar,
- vsec_data.dt_wr[i].off, chip->dt_region_wr[i].sz,
+ i, vsec_data->dt_wr[i].bar,
+ vsec_data->dt_wr[i].off, chip->dt_region_wr[i].sz,
chip->dt_region_wr[i].vaddr.io, &chip->dt_region_wr[i].paddr);
}
for (i = 0; i < chip->ll_rd_cnt; i++) {
pci_dbg(pdev, "L. List:\tREAD CH%.2u, BAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
- i, vsec_data.ll_rd[i].bar,
- vsec_data.ll_rd[i].off, chip->ll_region_rd[i].sz,
+ i, vsec_data->ll_rd[i].bar,
+ vsec_data->ll_rd[i].off, chip->ll_region_rd[i].sz,
chip->ll_region_rd[i].vaddr.io, &chip->ll_region_rd[i].paddr);
pci_dbg(pdev, "Data:\tREAD CH%.2u, BAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
- i, vsec_data.dt_rd[i].bar,
- vsec_data.dt_rd[i].off, chip->dt_region_rd[i].sz,
+ i, vsec_data->dt_rd[i].bar,
+ vsec_data->dt_rd[i].off, chip->dt_region_rd[i].sz,
chip->dt_region_rd[i].vaddr.io, &chip->dt_region_rd[i].paddr);
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 530/602] dmaengine: dw-edma: Fix confusing cleanup.h syntax
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (528 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 529/602] dma: dw-edma: Fix build warning in dw_edma_pcie_probe() Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 531/602] dmaengine: dw-edma-pcie: Reject devices without driver data Greg Kroah-Hartman
` (75 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Krzysztof Kozlowski,
Manivannan Sadhasivam, Vinod Koul, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
[ Upstream commit f9ef8dedee34e2d7828d5a6a0643cd969aaa8437 ]
Initializing automatic __free variables to NULL without need (e.g.
branches with different allocations), followed by actual allocation is
in contrary to explicit coding rules guiding cleanup.h:
"Given that the "__free(...) = NULL" pattern for variables defined at
the top of the function poses this potential interdependency problem the
recommendation is to always define and assign variables in one statement
and not group variable definitions at the top of the function when
__free() is used."
Code does not have a bug, but is less readable and uses discouraged
coding practice, so fix that by moving declaration to the place of
assignment.
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
Link: https://patch.msgid.link/20251208020729.4654-2-krzysztof.kozlowski@oss.qualcomm.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Stable-dep-of: 11d7cfe0c119 ("dmaengine: dw-edma-pcie: Reject devices without driver data")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/dma/dw-edma/dw-edma-pcie.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -160,13 +160,13 @@ static int dw_edma_pcie_probe(struct pci
const struct pci_device_id *pid)
{
struct dw_edma_pcie_data *pdata = (void *)pid->driver_data;
- struct dw_edma_pcie_data *vsec_data __free(kfree) = NULL;
struct device *dev = &pdev->dev;
struct dw_edma_chip *chip;
int err, nr_irqs;
int i, mask;
- vsec_data = kmalloc(sizeof(*vsec_data), GFP_KERNEL);
+ struct dw_edma_pcie_data *vsec_data __free(kfree) =
+ kmalloc(sizeof(*vsec_data), GFP_KERNEL);
if (!vsec_data)
return -ENOMEM;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 531/602] dmaengine: dw-edma-pcie: Reject devices without driver data
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (529 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 530/602] dmaengine: dw-edma: Fix confusing cleanup.h syntax Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 532/602] i2c: imx: separate atomic, dma and non-dma use case Greg Kroah-Hartman
` (74 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Koichiro Den, Frank Li, Vinod Koul,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Koichiro Den <den@valinux.co.jp>
[ Upstream commit 11d7cfe0c119691b2dafbb699bbca90258c678aa ]
dw_edma_pcie_probe() treats the PCI device ID driver_data as the
template for the controller layout and copies it unconditionally. A
device bound dynamically via sysfs can match the driver without that
data, which leads to a NULL pointer dereference.
Reject such matches before enabling the device.
Fixes: 41aaff2a2ac0 ("dmaengine: Add Synopsys eDMA IP PCIe glue-logic")
Cc: stable@vger.kernel.org
Signed-off-by: Koichiro Den <den@valinux.co.jp>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20260521142153.2957432-3-den@valinux.co.jp
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/dma/dw-edma/dw-edma-pcie.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -165,6 +165,9 @@ static int dw_edma_pcie_probe(struct pci
int err, nr_irqs;
int i, mask;
+ if (!pdata)
+ return -ENODEV;
+
struct dw_edma_pcie_data *vsec_data __free(kfree) =
kmalloc(sizeof(*vsec_data), GFP_KERNEL);
if (!vsec_data)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 532/602] i2c: imx: separate atomic, dma and non-dma use case
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (530 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 531/602] dmaengine: dw-edma-pcie: Reject devices without driver data Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 533/602] i2c: imx: fix locked bus on SMBus block-read of 0 (atomic) Greg Kroah-Hartman
` (73 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Stefan Eichenberger, Frank Li,
Oleksij Rempel, Andi Shyti, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefan Eichenberger <stefan.eichenberger@toradex.com>
[ Upstream commit b460b15b3cc23ef3639cc51043bf8b2a70ca1878 ]
Separate the atomic, dma and non-dma use case as a preparation step for
moving the non-dma use case to the isr to avoid rescheduling while a
transfer is in progress.
Signed-off-by: Stefan Eichenberger <stefan.eichenberger@toradex.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Acked-by: Oleksij Rempel <o.rempel@pengutronix.de>
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
Stable-dep-of: cb2fc3785769 ("i2c: imx: fix locked bus on SMBus block-read of 0 (atomic)")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/i2c/busses/i2c-imx.c | 107 ++++++++++++++++++++++++++++---------------
1 file changed, 70 insertions(+), 37 deletions(-)
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -1007,6 +1007,43 @@ static int i2c_imx_dma_write(struct imx_
return i2c_imx_acked(i2c_imx);
}
+static int i2c_imx_prepare_read(struct imx_i2c_struct *i2c_imx,
+ struct i2c_msg *msgs, bool atomic,
+ bool use_dma)
+{
+ int result;
+ unsigned int temp = 0;
+
+ /* write slave address */
+ imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
+ result = i2c_imx_trx_complete(i2c_imx, atomic);
+ if (result)
+ return result;
+ result = i2c_imx_acked(i2c_imx);
+ if (result)
+ return result;
+
+ dev_dbg(&i2c_imx->adapter.dev, "<%s> setup bus\n", __func__);
+
+ /* setup bus to read data */
+ temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+ temp &= ~I2CR_MTX;
+
+ /*
+ * Reset the I2CR_TXAK flag initially for SMBus block read since the
+ * length is unknown
+ */
+ if (msgs->len - 1)
+ temp &= ~I2CR_TXAK;
+ if (use_dma)
+ temp |= I2CR_DMAEN;
+
+ imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
+ imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); /* dummy read */
+
+ return 0;
+}
+
static int i2c_imx_dma_read(struct imx_i2c_struct *i2c_imx,
struct i2c_msg *msgs, bool is_lastmsg)
{
@@ -1017,6 +1054,11 @@ static int i2c_imx_dma_read(struct imx_i
struct imx_i2c_dma *dma = i2c_imx->dma;
struct device *dev = &i2c_imx->adapter.dev;
+ result = i2c_imx_prepare_read(i2c_imx, msgs, false, true);
+ if (result)
+ return result;
+
+ dev_dbg(&i2c_imx->adapter.dev, "<%s> read data\n", __func__);
dma->chan_using = dma->chan_rx;
dma->dma_transfer_dir = DMA_DEV_TO_MEM;
@@ -1127,50 +1169,24 @@ static int i2c_imx_write(struct imx_i2c_
return 0;
}
+static int i2c_imx_atomic_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
+{
+ return i2c_imx_write(i2c_imx, msgs, true);
+}
+
static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
bool is_lastmsg, bool atomic)
{
int i, result;
unsigned int temp;
int block_data = msgs->flags & I2C_M_RECV_LEN;
- int use_dma = i2c_imx->dma && msgs->flags & I2C_M_DMA_SAFE &&
- msgs->len >= DMA_THRESHOLD && !block_data;
-
- dev_dbg(&i2c_imx->adapter.dev,
- "<%s> write slave address: addr=0x%x\n",
- __func__, i2c_8bit_addr_from_msg(msgs));
- /* write slave address */
- imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
- result = i2c_imx_trx_complete(i2c_imx, atomic);
- if (result)
- return result;
- result = i2c_imx_acked(i2c_imx);
+ result = i2c_imx_prepare_read(i2c_imx, msgs, atomic, false);
if (result)
return result;
- dev_dbg(&i2c_imx->adapter.dev, "<%s> setup bus\n", __func__);
-
- /* setup bus to read data */
- temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
- temp &= ~I2CR_MTX;
-
- /*
- * Reset the I2CR_TXAK flag initially for SMBus block read since the
- * length is unknown
- */
- if ((msgs->len - 1) || block_data)
- temp &= ~I2CR_TXAK;
- if (use_dma)
- temp |= I2CR_DMAEN;
- imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
- imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR); /* dummy read */
-
dev_dbg(&i2c_imx->adapter.dev, "<%s> read data\n", __func__);
- if (use_dma)
- return i2c_imx_dma_read(i2c_imx, msgs, is_lastmsg);
-
/* read data */
for (i = 0; i < msgs->len; i++) {
u8 len = 0;
@@ -1237,6 +1253,12 @@ static int i2c_imx_read(struct imx_i2c_s
return 0;
}
+static int i2c_imx_atomic_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
+ bool is_lastmsg)
+{
+ return i2c_imx_read(i2c_imx, msgs, is_lastmsg, true);
+}
+
static int i2c_imx_xfer_common(struct i2c_adapter *adapter,
struct i2c_msg *msgs, int num, bool atomic)
{
@@ -1244,6 +1266,7 @@ static int i2c_imx_xfer_common(struct i2
int result;
bool is_lastmsg = false;
struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(adapter);
+ int use_dma = 0;
/* Start I2C transfer */
result = i2c_imx_start(i2c_imx, atomic);
@@ -1296,15 +1319,25 @@ static int i2c_imx_xfer_common(struct i2
(temp & I2SR_SRW ? 1 : 0), (temp & I2SR_IIF ? 1 : 0),
(temp & I2SR_RXAK ? 1 : 0));
#endif
+
+ use_dma = i2c_imx->dma && msgs[i].len >= DMA_THRESHOLD &&
+ msgs[i].flags & I2C_M_DMA_SAFE;
if (msgs[i].flags & I2C_M_RD) {
- result = i2c_imx_read(i2c_imx, &msgs[i], is_lastmsg, atomic);
+ int block_data = msgs->flags & I2C_M_RECV_LEN;
+
+ if (atomic)
+ result = i2c_imx_atomic_read(i2c_imx, &msgs[i], is_lastmsg);
+ else if (use_dma && !block_data)
+ result = i2c_imx_dma_read(i2c_imx, &msgs[i], is_lastmsg);
+ else
+ result = i2c_imx_read(i2c_imx, &msgs[i], is_lastmsg, false);
} else {
- if (!atomic &&
- i2c_imx->dma && msgs[i].len >= DMA_THRESHOLD &&
- msgs[i].flags & I2C_M_DMA_SAFE)
+ if (atomic)
+ result = i2c_imx_atomic_write(i2c_imx, &msgs[i]);
+ else if (use_dma)
result = i2c_imx_dma_write(i2c_imx, &msgs[i]);
else
- result = i2c_imx_write(i2c_imx, &msgs[i], atomic);
+ result = i2c_imx_write(i2c_imx, &msgs[i], false);
}
if (result)
goto fail0;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 533/602] i2c: imx: fix locked bus on SMBus block-read of 0 (atomic)
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (531 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 532/602] i2c: imx: separate atomic, dma and non-dma use case Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 534/602] xfrm: Use nested-BH locking for nat_keepalive_sk_ipv[46] Greg Kroah-Hartman
` (72 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Vincent Jardin, Oleksij Rempel,
Carlos Song, Stefan Eichenberger, Andi Shyti, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vincent Jardin <vjardin@free.fr>
[ Upstream commit cb2fc37857693b55909fb77dc2c87cfbc1cdc476 ]
SMBus 3.1 6.5.7 allows a Block Read byte count of 0, but the atomic
(polling) path rejects it as -EPROTO. Worse, it returns without a
NACK+STOP: the next receive cycle has already started, so the target
keeps holding SDA and the bus stays stuck until a power cycle for
this i2c controller.
Reading I2DR to obtain the count likewise arms the next byte on the
count > I2C_SMBUS_BLOCK_MAX path, which also returned -EPROTO directly
and left the bus held.
Handle both: NACK the in-flight dummy byte (TXAK) and extend msgs->len so
the existing last-byte handling emits STOP; the dummy byte is discarded.
A count of 0 is a valid empty block read; a count above
I2C_SMBUS_BLOCK_MAX is still reported as -EPROTO, but only after the bus
has been released.
The interrupt-driven path has the same flaw from a later commit and is
fixed separately, as it carries a different Fixes: tag and stable range.
Fixes: 8e8782c71595 ("i2c: imx: add SMBus block read support")
Signed-off-by: Vincent Jardin <vjardin@free.fr>
Cc: <stable@vger.kernel.org> # v3.16+
Acked-by: Oleksij Rempel <o.rempel@pengutronix.de>
Acked-by: Carlos Song <carlos.song@nxp.com>
Reviewed-by: Stefan Eichenberger <eichest@gmail.com>
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
Link: https://lore.kernel.org/r/20260713-for-upstream-i2c-lx2160-fix-v1-v3-1-073ac9e103a5@free.fr
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/i2c/busses/i2c-imx.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -1180,6 +1180,7 @@ static int i2c_imx_read(struct imx_i2c_s
int i, result;
unsigned int temp;
int block_data = msgs->flags & I2C_M_RECV_LEN;
+ int block_err = 0;
result = i2c_imx_prepare_read(i2c_imx, msgs, atomic, false);
if (result)
@@ -1201,8 +1202,20 @@ static int i2c_imx_read(struct imx_i2c_s
*/
if ((!i) && block_data) {
len = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
- if ((len == 0) || (len > I2C_SMBUS_BLOCK_MAX))
- return -EPROTO;
+ if ((len == 0) || (len > I2C_SMBUS_BLOCK_MAX)) {
+ /*
+ * SMBus 3.1 6.5.7: support count byte of 0.
+ * I2C_SMBUS_BLOCK_MAX case should not hold the SDA either.
+ */
+ if (len > I2C_SMBUS_BLOCK_MAX)
+ block_err = -EPROTO;
+ temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2CR);
+ temp |= I2CR_TXAK;
+ imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
+ msgs->buf[0] = 0;
+ msgs->len = 2;
+ continue;
+ }
dev_dbg(&i2c_imx->adapter.dev,
"<%s> read length: 0x%X\n",
__func__, len);
@@ -1250,7 +1263,7 @@ static int i2c_imx_read(struct imx_i2c_s
"<%s> read byte: B%d=0x%X\n",
__func__, i, msgs->buf[i]);
}
- return 0;
+ return block_err;
}
static int i2c_imx_atomic_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs,
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 534/602] xfrm: Use nested-BH locking for nat_keepalive_sk_ipv[46]
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (532 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 533/602] i2c: imx: fix locked bus on SMBus block-read of 0 (atomic) Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 535/602] xfrm: nat_keepalive: avoid double free on send error Greg Kroah-Hartman
` (71 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Steffen Klassert, Herbert Xu,
Sebastian Andrzej Siewior, Paolo Abeni, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
[ Upstream commit 9c607d4b6589d4d380a85784514bcf4cceee1e11 ]
nat_keepalive_sk_ipv[46] is a per-CPU variable and relies on disabled BH
for its locking. Without per-CPU locking in local_bh_disable() on
PREEMPT_RT this data structure requires explicit locking.
Use sock_bh_locked which has a sock pointer and a local_lock_t. Use
local_lock_nested_bh() for locking. This change adds only lockdep
coverage and does not alter the functional behaviour for !PREEMPT_RT.
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Link: https://patch.msgid.link/20250512092736.229935-7-bigeasy@linutronix.de
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Stable-dep-of: 226f4a490d1a ("xfrm: nat_keepalive: avoid double free on send error")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/xfrm/xfrm_nat_keepalive.c | 30 ++++++++++++++++++++----------
1 file changed, 20 insertions(+), 10 deletions(-)
--- a/net/xfrm/xfrm_nat_keepalive.c
+++ b/net/xfrm/xfrm_nat_keepalive.c
@@ -9,9 +9,13 @@
#include <net/ip6_checksum.h>
#include <net/xfrm.h>
-static DEFINE_PER_CPU(struct sock *, nat_keepalive_sk_ipv4);
+static DEFINE_PER_CPU(struct sock_bh_locked, nat_keepalive_sk_ipv4) = {
+ .bh_lock = INIT_LOCAL_LOCK(bh_lock),
+};
#if IS_ENABLED(CONFIG_IPV6)
-static DEFINE_PER_CPU(struct sock *, nat_keepalive_sk_ipv6);
+static DEFINE_PER_CPU(struct sock_bh_locked, nat_keepalive_sk_ipv6) = {
+ .bh_lock = INIT_LOCAL_LOCK(bh_lock),
+};
#endif
struct nat_keepalive {
@@ -56,10 +60,12 @@ static int nat_keepalive_send_ipv4(struc
skb_dst_set(skb, &rt->dst);
- sk = *this_cpu_ptr(&nat_keepalive_sk_ipv4);
+ local_lock_nested_bh(&nat_keepalive_sk_ipv4.bh_lock);
+ sk = this_cpu_read(nat_keepalive_sk_ipv4.sock);
sock_net_set(sk, net);
err = ip_build_and_send_pkt(skb, sk, fl4.saddr, fl4.daddr, NULL, tos);
sock_net_set(sk, &init_net);
+ local_unlock_nested_bh(&nat_keepalive_sk_ipv4.bh_lock);
return err;
}
@@ -89,15 +95,19 @@ static int nat_keepalive_send_ipv6(struc
fl6.fl6_sport = ka->encap_sport;
fl6.fl6_dport = ka->encap_dport;
- sk = *this_cpu_ptr(&nat_keepalive_sk_ipv6);
+ local_lock_nested_bh(&nat_keepalive_sk_ipv6.bh_lock);
+ sk = this_cpu_read(nat_keepalive_sk_ipv6.sock);
sock_net_set(sk, net);
dst = ipv6_stub->ipv6_dst_lookup_flow(net, sk, &fl6, NULL);
- if (IS_ERR(dst))
+ if (IS_ERR(dst)) {
+ local_unlock_nested_bh(&nat_keepalive_sk_ipv6.bh_lock);
return PTR_ERR(dst);
+ }
skb_dst_set(skb, dst);
err = ipv6_stub->ip6_xmit(sk, skb, &fl6, skb->mark, NULL, 0, 0);
sock_net_set(sk, &init_net);
+ local_unlock_nested_bh(&nat_keepalive_sk_ipv6.bh_lock);
return err;
}
#endif
@@ -202,7 +212,7 @@ static void nat_keepalive_work(struct wo
(ctx.next_run - ctx.now) * HZ);
}
-static int nat_keepalive_sk_init(struct sock * __percpu *socks,
+static int nat_keepalive_sk_init(struct sock_bh_locked __percpu *socks,
unsigned short family)
{
struct sock *sk;
@@ -214,22 +224,22 @@ static int nat_keepalive_sk_init(struct
if (err < 0)
goto err;
- *per_cpu_ptr(socks, i) = sk;
+ per_cpu_ptr(socks, i)->sock = sk;
}
return 0;
err:
for_each_possible_cpu(i)
- inet_ctl_sock_destroy(*per_cpu_ptr(socks, i));
+ inet_ctl_sock_destroy(per_cpu_ptr(socks, i)->sock);
return err;
}
-static void nat_keepalive_sk_fini(struct sock * __percpu *socks)
+static void nat_keepalive_sk_fini(struct sock_bh_locked __percpu *socks)
{
int i;
for_each_possible_cpu(i)
- inet_ctl_sock_destroy(*per_cpu_ptr(socks, i));
+ inet_ctl_sock_destroy(per_cpu_ptr(socks, i)->sock);
}
void xfrm_nat_keepalive_state_updated(struct xfrm_state *x)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 535/602] xfrm: nat_keepalive: avoid double free on send error
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (533 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 534/602] xfrm: Use nested-BH locking for nat_keepalive_sk_ipv[46] Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 536/602] tcp: defer md5sig_info kfree past RCU grace period in tcp_connect Greg Kroah-Hartman
` (70 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yuan Tan, Xin Liu, Qianyu Luo,
Ren Wei, Eyal Birger, Steffen Klassert, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qianyu Luo <qianyuluo3@gmail.com>
[ Upstream commit 226f4a490d1a938fc838d8f8c46a4eca864c0d78 ]
nat_keepalive_send() frees the keepalive skb whenever the IPv4 or IPv6
send helper reports an error.
That cleanup is only correct before the skb is handed to the output
path. Once ip_build_and_send_pkt() or ip6_xmit() takes ownership, the
networking stack may already have consumed the skb before returning an
error, so freeing it again is unsafe.
Handle the pre-handoff failure cases inside nat_keepalive_send_ipv4()
and nat_keepalive_send_ipv6(), where the caller still owns the skb, and
keep nat_keepalive_send() responsible only for family dispatch and the
unsupported-family cleanup path.
Fixes: f531d13bdfe3 ("xfrm: support sending NAT keepalives in ESP in UDP states")
Cc: stable@vger.kernel.org
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Signed-off-by: Qianyu Luo <qianyuluo3@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
Reviewed-by: Eyal Birger <eyal.birger@gmail.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/xfrm/xfrm_nat_keepalive.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
--- a/net/xfrm/xfrm_nat_keepalive.c
+++ b/net/xfrm/xfrm_nat_keepalive.c
@@ -55,8 +55,10 @@ static int nat_keepalive_send_ipv4(struc
ka->encap_sport, sock_net_uid(net, NULL));
rt = ip_route_output_key(net, &fl4);
- if (IS_ERR(rt))
+ if (IS_ERR(rt)) {
+ kfree_skb(skb);
return PTR_ERR(rt);
+ }
skb_dst_set(skb, &rt->dst);
@@ -101,6 +103,7 @@ static int nat_keepalive_send_ipv6(struc
dst = ipv6_stub->ipv6_dst_lookup_flow(net, sk, &fl6, NULL);
if (IS_ERR(dst)) {
local_unlock_nested_bh(&nat_keepalive_sk_ipv6.bh_lock);
+ kfree_skb(skb);
return PTR_ERR(dst);
}
@@ -118,7 +121,6 @@ static void nat_keepalive_send(struct na
sizeof(struct ipv6hdr)) +
sizeof(struct udphdr);
const u8 nat_ka_payload = 0xFF;
- int err = -EAFNOSUPPORT;
struct sk_buff *skb;
struct udphdr *uh;
@@ -140,16 +142,17 @@ static void nat_keepalive_send(struct na
switch (ka->family) {
case AF_INET:
- err = nat_keepalive_send_ipv4(skb, ka);
+ nat_keepalive_send_ipv4(skb, ka);
break;
#if IS_ENABLED(CONFIG_IPV6)
case AF_INET6:
- err = nat_keepalive_send_ipv6(skb, ka, uh);
+ nat_keepalive_send_ipv6(skb, ka, uh);
break;
#endif
- }
- if (err)
+ default:
kfree_skb(skb);
+ break;
+ }
}
struct nat_keepalive_work_ctx {
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 536/602] tcp: defer md5sig_info kfree past RCU grace period in tcp_connect
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (534 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 535/602] xfrm: nat_keepalive: avoid double free on send error Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 537/602] tcp: Decrement tcp_md5_needed static branch Greg Kroah-Hartman
` (69 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Eric Dumazet, Michael Bommarito,
Dmitry Safonov, Qihang, Dmitry Safonov, Jakub Kicinski,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <michael.bommarito@gmail.com>
[ Upstream commit b74cd55038905d5e74c1de109ab78a30b2ea0e1f ]
The md5+ao reconciliation in tcp_connect() (net/ipv4/tcp_output.c)
has two symmetric branches:
if (needs_md5) {
tcp_ao_destroy_sock(sk, false);
} else if (needs_ao) {
tcp_clear_md5_list(sk);
kfree(rcu_replace_pointer(tp->md5sig_info, NULL, ...));
}
Both branches free a per-socket auth-info object while the socket is
in TCP_SYN_SENT and is already on the inet ehash (inserted by
inet_hash_connect() in tcp_v4_connect()). Both branches are reachable
by softirq RX-path readers that load the corresponding info pointer
via implicit RCU before bh_lock_sock_nested() is taken.
The needs_md5 branch is fixed in the prior patch by re-introducing
the call_rcu() free in tcp_ao_destroy_sock(): the equivalent per-key
loop runs inside tcp_ao_info_free_rcu(), the RCU callback, so by the
time it frees each tcp_ao_key all softirq readers that captured the
container have already completed rcu_read_unlock().
The needs_ao branch is not symmetric in the same way. The container
free can be deferred via kfree_rcu(md5sig, rcu) -- struct
tcp_md5sig_info already has the required rcu member
(include/net/tcp.h:1999-2002), and the rest of the tree already does
this in the tcp_md5sig_info_add() rollback paths
(net/ipv4/tcp_ipv4.c:1410, 1436). But the per-key teardown is done
by tcp_clear_md5_list() in process context BEFORE the container's
RCU grace period: it walks &md5sig->head and frees each
tcp_md5sig_key with bare hlist_del + kfree. A concurrent softirq
reader in __tcp_md5_do_lookup() / __tcp_md5_do_lookup_exact()
(tcp_ipv4.c:1253, 1298) walks the same list via
hlist_for_each_entry_rcu() and races with that bare kfree on the
keys themselves -- a per-key slab use-after-free of the same class
as the TCP-AO bug, on the same race window.
Fix this in two halves:
1. Convert the bare kfree() in tcp_connect() to kfree_rcu() so the
md5sig_info container joins the rest of the md5sig lifecycle.
The local-variable lift is mechanical and required because
kfree_rcu() is a macro that expects an lvalue.
2. Make tcp_clear_md5_list() RCU-safe by replacing hlist_del +
kfree(key) with hlist_del_rcu + kfree_rcu(key, rcu). struct
tcp_md5sig_key already carries the rcu member
(include/net/tcp.h:1995) and tcp_md5_do_del()
(net/ipv4/tcp_ipv4.c:1456) already uses kfree_rcu, so this
restores the lifecycle invariant the rest of the file follows
rather than introducing a one-off.
The other caller of tcp_clear_md5_list() is tcp_md5_destruct_sock()
(net/ipv4/tcp.c:412), which runs from the sock destructor when the
socket is already unhashed and unreachable; the extra grace period
there is unnecessary but harmless. Making the helper unconditionally
RCU-safe is the cleaner contract.
The needs_ao branch is not reachable by the userns reproducer used
to demonstrate the AO-side splat (the repro installs both keys but
ends up in the needs_md5 branch because the connect peer matches
the MD5 key, not the AO key); however the symmetric race exists
and a maintainer touching this code should not have to think about
which branch escapes RCU and which one does not.
Fixes: 51e547e8c89c ("tcp: Free TCP-AO/TCP-MD5 info/keys without RCU")
Cc: stable@vger.kernel.org # v6.18+
Suggested-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Reviewed-by: Dmitry Safonov <dima@arista.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
[also credits to Qihang, who found that this races with tcp-diag]
Reported-by: Qihang <q.h.hack.winter@gmail.com>
Signed-off-by: Dmitry Safonov <0x7f454c46@gmail.com>
Link: https://patch.msgid.link/20260625-tcp-md5-connect-v3-2-1fd313d6c1e0@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: 6f6e860e370c ("tcp: Decrement tcp_md5_needed static branch")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ipv4/tcp_output.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -4119,9 +4119,13 @@ int tcp_connect(struct sock *sk)
if (needs_md5) {
tcp_ao_destroy_sock(sk, false);
} else if (needs_ao) {
+ struct tcp_md5sig_info *md5sig;
+
tcp_clear_md5_list(sk);
- kfree(rcu_replace_pointer(tp->md5sig_info, NULL,
- lockdep_sock_is_held(sk)));
+ md5sig = rcu_replace_pointer(tp->md5sig_info, NULL,
+ lockdep_sock_is_held(sk));
+ if (md5sig)
+ kfree_rcu(md5sig, rcu);
}
}
#endif
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 537/602] tcp: Decrement tcp_md5_needed static branch
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (535 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 536/602] tcp: defer md5sig_info kfree past RCU grace period in tcp_connect Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 538/602] nvmet: Introduce nvmet_req_transfer_len() Greg Kroah-Hartman
` (68 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Qihang, Dmitry Safonov,
Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Safonov <0x7f454c46@gmail.com>
[ Upstream commit 6f6e860e370c9e4e919b92118a25e9e1f82e9180 ]
In case of early freeing an unwanted TCP-MD5 key on TCP-AO connect(),
md5sig_info is freed right away (and set to NULL). Later, at
the moment of socket destruction, the static branch counter
is not getting decremented.
Add a missing decrement for TCP-MD5 static branch.
Reported-by: Qihang <q.h.hack.winter@gmail.com>
Fixes: 0aadc73995d0 ("net/tcp: Prevent TCP-MD5 with TCP-AO being set")
Cc: stable@vger.kernel.org
Signed-off-by: Dmitry Safonov <0x7f454c46@gmail.com>
Link: https://patch.msgid.link/20260625-tcp-md5-connect-v3-3-1fd313d6c1e0@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ipv4/tcp_output.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -4124,8 +4124,8 @@ int tcp_connect(struct sock *sk)
tcp_clear_md5_list(sk);
md5sig = rcu_replace_pointer(tp->md5sig_info, NULL,
lockdep_sock_is_held(sk));
- if (md5sig)
- kfree_rcu(md5sig, rcu);
+ kfree_rcu(md5sig, rcu);
+ static_branch_slow_dec_deferred(&tcp_md5_needed);
}
}
#endif
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 538/602] nvmet: Introduce nvmet_req_transfer_len()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (536 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 537/602] tcp: Decrement tcp_md5_needed static branch Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 539/602] nvmet-auth: reject short AUTH_RECEIVE buffers Greg Kroah-Hartman
` (67 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Damien Le Moal, Christoph Hellwig,
Rick Wertenbroek, Manivannan Sadhasivam, Keith Busch, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Damien Le Moal <dlemoal@kernel.org>
[ Upstream commit 43043c9b97258a008b3402cfbbf1c5d82151c77f ]
Add the new function nvmet_req_transfer_len() to parse a request command
to extract the transfer length of the command. This function
implementation relies on multiple helper functions for parsing I/O
commands (nvmet_io_cmd_transfer_len()), admin commands
(nvmet_admin_cmd_data_len()) and fabrics connect commands
(nvmet_connect_cmd_data_len).
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Tested-by: Rick Wertenbroek <rick.wertenbroek@gmail.com>
Tested-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: Keith Busch <kbusch@kernel.org>
Stable-dep-of: 779575bc35c6 ("nvmet-auth: reject short AUTH_RECEIVE buffers")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/nvme/target/admin-cmd.c | 21 ++++++++++++++++
drivers/nvme/target/core.c | 37 ++++++++++++++++++++++++++++
drivers/nvme/target/discovery.c | 14 ++++++++++
drivers/nvme/target/fabrics-cmd-auth.c | 14 +++++++++-
drivers/nvme/target/fabrics-cmd.c | 43 +++++++++++++++++++++++++++++++++
drivers/nvme/target/nvmet.h | 8 ++++++
6 files changed, 135 insertions(+), 2 deletions(-)
--- a/drivers/nvme/target/admin-cmd.c
+++ b/drivers/nvme/target/admin-cmd.c
@@ -1008,6 +1008,27 @@ out:
nvmet_req_complete(req, status);
}
+u32 nvmet_admin_cmd_data_len(struct nvmet_req *req)
+{
+ struct nvme_command *cmd = req->cmd;
+
+ if (nvme_is_fabrics(cmd))
+ return nvmet_fabrics_admin_cmd_data_len(req);
+ if (nvmet_is_disc_subsys(nvmet_req_subsys(req)))
+ return nvmet_discovery_cmd_data_len(req);
+
+ switch (cmd->common.opcode) {
+ case nvme_admin_get_log_page:
+ return nvmet_get_log_page_len(cmd);
+ case nvme_admin_identify:
+ return NVME_IDENTIFY_DATA_SIZE;
+ case nvme_admin_get_features:
+ return nvmet_feat_data_len(req, le32_to_cpu(cmd->common.cdw10));
+ default:
+ return 0;
+ }
+}
+
u16 nvmet_parse_admin_cmd(struct nvmet_req *req)
{
struct nvme_command *cmd = req->cmd;
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -891,6 +891,33 @@ static inline u16 nvmet_io_cmd_check_acc
return 0;
}
+static u32 nvmet_io_cmd_transfer_len(struct nvmet_req *req)
+{
+ struct nvme_command *cmd = req->cmd;
+ u32 metadata_len = 0;
+
+ if (nvme_is_fabrics(cmd))
+ return nvmet_fabrics_io_cmd_data_len(req);
+
+ if (!req->ns)
+ return 0;
+
+ switch (req->cmd->common.opcode) {
+ case nvme_cmd_read:
+ case nvme_cmd_write:
+ case nvme_cmd_zone_append:
+ if (req->sq->ctrl->pi_support && nvmet_ns_has_pi(req->ns))
+ metadata_len = nvmet_rw_metadata_len(req);
+ return nvmet_rw_data_len(req) + metadata_len;
+ case nvme_cmd_dsm:
+ return nvmet_dsm_len(req);
+ case nvme_cmd_zone_mgmt_recv:
+ return (le32_to_cpu(req->cmd->zmr.numd) + 1) << 2;
+ default:
+ return 0;
+ }
+}
+
static u16 nvmet_parse_io_cmd(struct nvmet_req *req)
{
struct nvme_command *cmd = req->cmd;
@@ -1015,6 +1042,16 @@ void nvmet_req_uninit(struct nvmet_req *
}
EXPORT_SYMBOL_GPL(nvmet_req_uninit);
+size_t nvmet_req_transfer_len(struct nvmet_req *req)
+{
+ if (likely(req->sq->qid != 0))
+ return nvmet_io_cmd_transfer_len(req);
+ if (unlikely(!req->sq->ctrl))
+ return nvmet_connect_cmd_data_len(req);
+ return nvmet_admin_cmd_data_len(req);
+}
+EXPORT_SYMBOL_GPL(nvmet_req_transfer_len);
+
bool nvmet_check_transfer_len(struct nvmet_req *req, size_t len)
{
if (unlikely(len != req->transfer_len)) {
--- a/drivers/nvme/target/discovery.c
+++ b/drivers/nvme/target/discovery.c
@@ -373,6 +373,20 @@ static void nvmet_execute_disc_get_featu
nvmet_req_complete(req, stat);
}
+u32 nvmet_discovery_cmd_data_len(struct nvmet_req *req)
+{
+ struct nvme_command *cmd = req->cmd;
+
+ switch (cmd->common.opcode) {
+ case nvme_admin_get_log_page:
+ return nvmet_get_log_page_len(req->cmd);
+ case nvme_admin_identify:
+ return NVME_IDENTIFY_DATA_SIZE;
+ default:
+ return 0;
+ }
+}
+
u16 nvmet_parse_discovery_cmd(struct nvmet_req *req)
{
struct nvme_command *cmd = req->cmd;
--- a/drivers/nvme/target/fabrics-cmd-auth.c
+++ b/drivers/nvme/target/fabrics-cmd-auth.c
@@ -188,6 +188,11 @@ static u8 nvmet_auth_failure2(void *d)
return data->rescode_exp;
}
+u32 nvmet_auth_send_data_len(struct nvmet_req *req)
+{
+ return le32_to_cpu(req->cmd->auth_send.tl);
+}
+
void nvmet_execute_auth_send(struct nvmet_req *req)
{
struct nvmet_ctrl *ctrl = req->sq->ctrl;
@@ -215,7 +220,7 @@ void nvmet_execute_auth_send(struct nvme
offsetof(struct nvmf_auth_send_command, spsp1);
goto done;
}
- tl = le32_to_cpu(req->cmd->auth_send.tl);
+ tl = nvmet_auth_send_data_len(req);
if (!tl) {
status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
req->error_loc =
@@ -438,6 +443,11 @@ static void nvmet_auth_failure1(struct n
data->rescode_exp = req->sq->dhchap_status;
}
+u32 nvmet_auth_receive_data_len(struct nvmet_req *req)
+{
+ return le32_to_cpu(req->cmd->auth_receive.al);
+}
+
void nvmet_execute_auth_receive(struct nvmet_req *req)
{
struct nvmet_ctrl *ctrl = req->sq->ctrl;
@@ -463,7 +473,7 @@ void nvmet_execute_auth_receive(struct n
offsetof(struct nvmf_auth_receive_command, spsp1);
goto done;
}
- al = le32_to_cpu(req->cmd->auth_receive.al);
+ al = nvmet_auth_receive_data_len(req);
if (!al) {
status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
req->error_loc =
--- a/drivers/nvme/target/fabrics-cmd.c
+++ b/drivers/nvme/target/fabrics-cmd.c
@@ -82,6 +82,22 @@ static void nvmet_execute_prop_get(struc
nvmet_req_complete(req, status);
}
+u32 nvmet_fabrics_admin_cmd_data_len(struct nvmet_req *req)
+{
+ struct nvme_command *cmd = req->cmd;
+
+ switch (cmd->fabrics.fctype) {
+#ifdef CONFIG_NVME_TARGET_AUTH
+ case nvme_fabrics_type_auth_send:
+ return nvmet_auth_send_data_len(req);
+ case nvme_fabrics_type_auth_receive:
+ return nvmet_auth_receive_data_len(req);
+#endif
+ default:
+ return 0;
+ }
+}
+
u16 nvmet_parse_fabrics_admin_cmd(struct nvmet_req *req)
{
struct nvme_command *cmd = req->cmd;
@@ -111,6 +127,22 @@ u16 nvmet_parse_fabrics_admin_cmd(struct
return 0;
}
+u32 nvmet_fabrics_io_cmd_data_len(struct nvmet_req *req)
+{
+ struct nvme_command *cmd = req->cmd;
+
+ switch (cmd->fabrics.fctype) {
+#ifdef CONFIG_NVME_TARGET_AUTH
+ case nvme_fabrics_type_auth_send:
+ return nvmet_auth_send_data_len(req);
+ case nvme_fabrics_type_auth_receive:
+ return nvmet_auth_receive_data_len(req);
+#endif
+ default:
+ return 0;
+ }
+}
+
u16 nvmet_parse_fabrics_io_cmd(struct nvmet_req *req)
{
struct nvme_command *cmd = req->cmd;
@@ -342,6 +374,17 @@ out_ctrl_put:
goto out;
}
+u32 nvmet_connect_cmd_data_len(struct nvmet_req *req)
+{
+ struct nvme_command *cmd = req->cmd;
+
+ if (!nvme_is_fabrics(cmd) ||
+ cmd->fabrics.fctype != nvme_fabrics_type_connect)
+ return 0;
+
+ return sizeof(struct nvmf_connect_data);
+}
+
u16 nvmet_parse_connect_cmd(struct nvmet_req *req)
{
struct nvme_command *cmd = req->cmd;
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -466,18 +466,24 @@ void nvmet_start_keep_alive_timer(struct
void nvmet_stop_keep_alive_timer(struct nvmet_ctrl *ctrl);
u16 nvmet_parse_connect_cmd(struct nvmet_req *req);
+u32 nvmet_connect_cmd_data_len(struct nvmet_req *req);
void nvmet_bdev_set_limits(struct block_device *bdev, struct nvme_id_ns *id);
u16 nvmet_bdev_parse_io_cmd(struct nvmet_req *req);
u16 nvmet_file_parse_io_cmd(struct nvmet_req *req);
u16 nvmet_bdev_zns_parse_io_cmd(struct nvmet_req *req);
+u32 nvmet_admin_cmd_data_len(struct nvmet_req *req);
u16 nvmet_parse_admin_cmd(struct nvmet_req *req);
+u32 nvmet_discovery_cmd_data_len(struct nvmet_req *req);
u16 nvmet_parse_discovery_cmd(struct nvmet_req *req);
u16 nvmet_parse_fabrics_admin_cmd(struct nvmet_req *req);
+u32 nvmet_fabrics_admin_cmd_data_len(struct nvmet_req *req);
u16 nvmet_parse_fabrics_io_cmd(struct nvmet_req *req);
+u32 nvmet_fabrics_io_cmd_data_len(struct nvmet_req *req);
bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq,
struct nvmet_sq *sq, const struct nvmet_fabrics_ops *ops);
void nvmet_req_uninit(struct nvmet_req *req);
+size_t nvmet_req_transfer_len(struct nvmet_req *req);
bool nvmet_check_transfer_len(struct nvmet_req *req, size_t len);
bool nvmet_check_data_len_lte(struct nvmet_req *req, size_t data_len);
void nvmet_req_complete(struct nvmet_req *req, u16 status);
@@ -720,7 +726,9 @@ static inline void nvmet_req_bio_put(str
}
#ifdef CONFIG_NVME_TARGET_AUTH
+u32 nvmet_auth_send_data_len(struct nvmet_req *req);
void nvmet_execute_auth_send(struct nvmet_req *req);
+u32 nvmet_auth_receive_data_len(struct nvmet_req *req);
void nvmet_execute_auth_receive(struct nvmet_req *req);
int nvmet_auth_set_key(struct nvmet_host *host, const char *secret,
bool set_ctrl);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 539/602] nvmet-auth: reject short AUTH_RECEIVE buffers
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (537 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 538/602] nvmet: Introduce nvmet_req_transfer_len() Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 540/602] ovl: use linked upper dentry in copy-up tmpfile Greg Kroah-Hartman
` (66 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Hannes Reinecke, Michael Bommarito,
Keith Busch, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <michael.bommarito@gmail.com>
[ Upstream commit 779575bc35c687697ba69e904f2cd22e60112534 ]
nvmet_execute_auth_receive() trusts the AUTH_RECEIVE allocation length
after checking only that it is nonzero and matches the transfer length.
In the SUCCESS1 and FAILURE1/default states, that lets a remote NVMe-oF
initiator reach the fixed-size DH-HMAC-CHAP response builders with a
kmalloc() buffer shorter than the response, so nvmet_auth_success1() and
nvmet_auth_failure1() write past the allocation; both only WARN_ON the
short length and then format the message anyway.
Impact: A remote NVMe-oF initiator with access to an auth-enabled target
can trigger a 16-byte heap out-of-bounds write via a one-byte
AUTH_RECEIVE allocation length.
Compute the minimum response length for the current DH-HMAC-CHAP step in
nvmet_auth_receive_data_len() and report a zero data length when the
host-supplied allocation length is shorter, so the existing zero-length
check in nvmet_execute_auth_receive() rejects the command before any
builder runs. The SUCCESS1 minimum is sizeof(struct
nvmf_auth_dhchap_success1_data) plus the HMAC hash length, because the
response hash is written into the rval[] flexible-array tail, so the
minimum is state dependent rather than a flat sizeof. CHALLENGE keeps its
existing variable-length guard in nvmet_auth_challenge().
This is reachable only when in-band DH-HMAC-CHAP authentication is
configured on the target.
Fixes: db1312dd9548 ("nvmet: implement basic In-Band Authentication")
Cc: stable@vger.kernel.org
Assisted-by: Codex:gpt-5-5-xhigh
Assisted-by: Claude:claude-opus-4-8
Reviewed-by: Hannes Reinecke <hare@kernel.org>
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Signed-off-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/nvme/target/fabrics-cmd-auth.c | 26 +++++++++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
--- a/drivers/nvme/target/fabrics-cmd-auth.c
+++ b/drivers/nvme/target/fabrics-cmd-auth.c
@@ -445,7 +445,31 @@ static void nvmet_auth_failure1(struct n
u32 nvmet_auth_receive_data_len(struct nvmet_req *req)
{
- return le32_to_cpu(req->cmd->auth_receive.al);
+ struct nvmet_ctrl *ctrl = req->sq->ctrl;
+ u32 al = le32_to_cpu(req->cmd->auth_receive.al);
+ u32 min_len;
+
+ /*
+ * Reject too-short al before kmalloc(al), since the SUCCESS1 and
+ * FAILURE1/default builders write fixed response headers into it.
+ */
+ switch (req->sq->dhchap_step) {
+ case NVME_AUTH_DHCHAP_MESSAGE_CHALLENGE:
+ return al;
+ case NVME_AUTH_DHCHAP_MESSAGE_SUCCESS1:
+ min_len = sizeof(struct nvmf_auth_dhchap_success1_data);
+ if (req->sq->dhchap_c2)
+ min_len += nvme_auth_hmac_hash_len(ctrl->shash_id);
+ break;
+ default:
+ min_len = sizeof(struct nvmf_auth_dhchap_failure_data);
+ break;
+ }
+
+ if (al < min_len)
+ return 0;
+
+ return al;
}
void nvmet_execute_auth_receive(struct nvmet_req *req)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 540/602] ovl: use linked upper dentry in copy-up tmpfile
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (538 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 539/602] nvmet-auth: reject short AUTH_RECEIVE buffers Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 541/602] bpf: Refactor {acquire,release}_reference_state Greg Kroah-Hartman
` (65 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Souvik Banerjee, Amir Goldstein,
Miklos Szeredi, Christian Brauner (Amutable), Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Souvik Banerjee <souvik@amlalabs.com>
[ Upstream commit e348eecd4d8fa8d18a5157ff59f7be1dc59c5928 ]
ovl_copy_up_tmpfile() stores the disconnected O_TMPFILE dentry as the
overlay's upper dentry reference via ovl_inode_update(). vfs_tmpfile()
allocated this dentry via d_alloc(parentpath->dentry, &slash_name), so
d_name is "/" and d_parent is c->workdir. Local upper filesystems
(ext4, btrfs, xfs, ...) immediately rename it to "#<inum>" via
d_mark_tmpfile() inside their ->tmpfile() op; FUSE and virtiofs do
not, so both fields stay that way. Neither identifies the destination
directory and filename where ovl_do_link() actually linked the file.
When the upper filesystem implements ->d_revalidate() (e.g. FUSE or
virtiofs), ovl_revalidate_real() calls it with the dentry's parent
inode and a snapshot of d_name. The server tries to look up "/" inside
c->workdir, fails, and overlayfs reports -ESTALE.
This causes persistent ESTALE errors for any file that was copied up via
the tmpfile path, breaking dpkg, apt, and other tools that do
rename-over-existing on overlayfs with a FUSE/virtiofs upper.
Before commit 6b52243f633e ("ovl: fold copy-up helpers into callers"),
the tmpfile copy-up path used a dedicated helper ovl_link_tmpfile()
that captured the linked destination dentry returned by ovl_do_link():
err = ovl_do_link(temp, udir, upper);
...
if (!err)
*newdentry = dget(upper);
and published it via ovl_inode_update(d_inode(c->dentry), newdentry).
The fold inlined ovl_do_link() into ovl_copy_up_tmpfile() but dropped
the dget(upper) capture, and rewrote the publish line as
ovl_inode_update(d_inode(c->dentry), dget(temp)) — where temp is the
disconnected O_TMPFILE dentry.
Fix by keeping a reference to the linked destination dentry after
ovl_do_link() succeeds, and publishing that dentry at the existing
ovl_inode_update() call site. The non-tmpfile/workdir path continues to
publish the renamed temporary dentry.
Reproducer:
- Mount overlayfs with virtiofs (or a FUSE fs whose server advertises
FUSE_TMPFILE) as upper
- Run: dpkg -i <any .deb>
- Observe: "error installing new file '...': Stale file handle"
Fixes: 6b52243f633e ("ovl: fold copy-up helpers into callers")
Cc: stable@vger.kernel.org # v4.20+
Signed-off-by: Souvik Banerjee <souvik@amlalabs.com>
Link: https://patch.msgid.link/20260501232735.2610824-1-souvik@amlalabs.com
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Reviewed-by: Miklos Szeredi <mszeredi@redhat.com>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
[ adapted scoped credential and creation helpers to explicit credential, locking, lookup, and cleanup handling ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/overlayfs/copy_up.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -864,7 +864,7 @@ static int ovl_copy_up_tmpfile(struct ov
{
struct ovl_fs *ofs = OVL_FS(c->dentry->d_sb);
struct inode *udir = d_inode(c->destdir);
- struct dentry *temp, *upper;
+ struct dentry *temp, *upper, *newdentry = NULL;
struct file *tmpfile;
struct ovl_cu_creds cc;
int err;
@@ -901,6 +901,14 @@ static int ovl_copy_up_tmpfile(struct ov
err = PTR_ERR(upper);
if (!IS_ERR(upper)) {
err = ovl_do_link(ofs, temp, udir, upper);
+ if (!err) {
+ /*
+ * Record the linked dentry -- not the disconnected
+ * O_TMPFILE dentry -- so that ->d_revalidate() on
+ * the upper fs sees the real parent/name.
+ */
+ newdentry = dget(upper);
+ }
dput(upper);
}
inode_unlock(udir);
@@ -916,7 +924,7 @@ static int ovl_copy_up_tmpfile(struct ov
if (!c->metacopy)
ovl_set_upperdata(d_inode(c->dentry));
- ovl_inode_update(d_inode(c->dentry), dget(temp));
+ ovl_inode_update(d_inode(c->dentry), newdentry);
out:
ovl_end_write(c->dentry);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 541/602] bpf: Refactor {acquire,release}_reference_state
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (539 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 540/602] ovl: use linked upper dentry in copy-up tmpfile Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 542/602] bpf: Refactor check_ctx_access() Greg Kroah-Hartman
` (64 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Eduard Zingerman,
Kumar Kartikeya Dwivedi, Alexei Starovoitov, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kumar Kartikeya Dwivedi <memxor@gmail.com>
[ Upstream commit 769b0f1c821455ab29baf42491e1ea1d726451fa ]
In preparation for introducing support for more reference types which
have to add and remove reference state, refactor the
acquire_reference_state and release_reference_state functions to share
common logic.
The acquire_reference_state function simply handles growing the acquired
refs and returning the pointer to the new uninitialized element, which
can be filled in by the caller.
The release_reference_state function simply erases a reference state
entry in the acquired_refs array and shrinks it. The callers are
responsible for finding the suitable element by matching on various
fields of the reference state and requesting deletion through this
function. It is not supposed to be called directly.
Existing callers of release_reference_state were using it to find and
remove state for a given ref_obj_id without scrubbing the associated
registers in the verifier state. Introduce release_reference_nomark to
provide this functionality and convert callers. We now use this new
release_reference_nomark function within release_reference as well.
It needs to operate on a verifier state instead of taking verifier env
as mark_ptr_or_null_regs requires operating on verifier state of the
two branches of a NULL condition check, therefore env->cur_state cannot
be used directly.
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20241204030400.208005-3-memxor@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Stable-dep-of: 5e0b273e0a62 ("bpf: Reset register bounds before narrowing retval range in check_mem_access()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
kernel/bpf/verifier.c | 28 +++++++++++++++-------------
1 file changed, 15 insertions(+), 13 deletions(-)
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -7207,11 +7207,12 @@ static int check_mem_access(struct bpf_v
if (!err && value_regno >= 0 && (t == BPF_READ || rdonly_mem))
mark_reg_unknown(env, regs, value_regno);
} else if (reg->type == PTR_TO_CTX) {
- bool is_retval = false;
+ struct bpf_insn_access_aux info = {
+ .reg_type = SCALAR_VALUE,
+ .is_ldsx = is_ldsx,
+ .log = &env->log,
+ };
struct bpf_retval_range range;
- enum bpf_reg_type reg_type = SCALAR_VALUE;
- struct btf *btf = NULL;
- u32 btf_id = 0;
if (t == BPF_WRITE && value_regno >= 0 &&
is_pointer_value(env, value_regno)) {
@@ -7223,8 +7224,9 @@ static int check_mem_access(struct bpf_v
if (err < 0)
return err;
- err = check_ctx_access(env, insn_idx, off, size, t, ®_type, &btf,
- &btf_id, &is_retval, is_ldsx);
+ err = check_ctx_access(env, insn_idx, off, size, t, &info.reg_type,
+ &info.btf, &info.btf_id, &info.is_retval,
+ info.is_ldsx);
if (err)
verbose_linfo(env, insn_idx, "; ");
if (!err && t == BPF_READ && value_regno >= 0) {
@@ -7232,8 +7234,8 @@ static int check_mem_access(struct bpf_v
* PTR_TO_PACKET[_META,_END]. In the latter
* case, we know the offset is zero.
*/
- if (reg_type == SCALAR_VALUE) {
- if (is_retval && get_func_retval_range(env->prog, &range)) {
+ if (info.reg_type == SCALAR_VALUE) {
+ if (info.is_retval && get_func_retval_range(env->prog, &range)) {
err = __mark_reg_s32_range(env, regs, value_regno,
range.minval, range.maxval);
if (err)
@@ -7244,7 +7246,7 @@ static int check_mem_access(struct bpf_v
} else {
mark_reg_known_zero(env, regs,
value_regno);
- if (type_may_be_null(reg_type))
+ if (type_may_be_null(info.reg_type))
regs[value_regno].id = ++env->id_gen;
/* A load of ctx field could have different
* actual load size with the one encoded in the
@@ -7252,12 +7254,12 @@ static int check_mem_access(struct bpf_v
* a sub-register.
*/
regs[value_regno].subreg_def = DEF_NOT_SUBREG;
- if (base_type(reg_type) == PTR_TO_BTF_ID) {
- regs[value_regno].btf = btf;
- regs[value_regno].btf_id = btf_id;
+ if (base_type(info.reg_type) == PTR_TO_BTF_ID) {
+ regs[value_regno].btf = info.btf;
+ regs[value_regno].btf_id = info.btf_id;
}
}
- regs[value_regno].type = reg_type;
+ regs[value_regno].type = info.reg_type;
}
} else if (reg->type == PTR_TO_STACK) {
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 542/602] bpf: Refactor check_ctx_access()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (540 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 541/602] bpf: Refactor {acquire,release}_reference_state Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 543/602] bpf: Reset register bounds before narrowing retval range in check_mem_access() Greg Kroah-Hartman
` (63 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Amery Hung, Alexei Starovoitov,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amery Hung <ameryhung@gmail.com>
[ Upstream commit 201b62ccc83153d2925d310a2afe762905e0c455 ]
Reduce the variable passing madness surrounding check_ctx_access().
Currently, check_mem_access() passes many pointers to local variables to
check_ctx_access(). They are used to initialize "struct
bpf_insn_access_aux info" in check_ctx_access() and then passed to
is_valid_access(). Then, check_ctx_access() takes the data our from
info and write them back the pointers to pass them back. This can be
simpilified by moving info up to check_mem_access().
No functional change.
Signed-off-by: Amery Hung <ameryhung@gmail.com>
Link: https://lore.kernel.org/r/20250221175644.1822383-1-ameryhung@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Stable-dep-of: 5e0b273e0a62 ("bpf: Reset register bounds before narrowing retval range in check_mem_access()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
kernel/bpf/verifier.c | 27 +++++----------------------
1 file changed, 5 insertions(+), 22 deletions(-)
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -5829,18 +5829,10 @@ static int check_packet_access(struct bp
/* check access to 'struct bpf_context' fields. Supports fixed offsets only */
static int check_ctx_access(struct bpf_verifier_env *env, int insn_idx, int off, int size,
- enum bpf_access_type t, enum bpf_reg_type *reg_type,
- struct btf **btf, u32 *btf_id, bool *is_retval, bool is_ldsx)
+ enum bpf_access_type t, struct bpf_insn_access_aux *info)
{
- struct bpf_insn_access_aux info = {
- .reg_type = *reg_type,
- .log = &env->log,
- .is_retval = false,
- .is_ldsx = is_ldsx,
- };
-
if (env->ops->is_valid_access &&
- env->ops->is_valid_access(off, size, t, env->prog, &info)) {
+ env->ops->is_valid_access(off, size, t, env->prog, info)) {
/* A non zero info.ctx_field_size indicates that this field is a
* candidate for later verifier transformation to load the whole
* field and then apply a mask when accessed with a narrower
@@ -5848,15 +5840,8 @@ static int check_ctx_access(struct bpf_v
* will only allow for whole field access and rejects any other
* type of narrower access.
*/
- *reg_type = info.reg_type;
- *is_retval = info.is_retval;
-
- if (base_type(*reg_type) == PTR_TO_BTF_ID) {
- *btf = info.btf;
- *btf_id = info.btf_id;
- } else {
- env->insn_aux_data[insn_idx].ctx_field_size = info.ctx_field_size;
- }
+ if (base_type(info->reg_type) != PTR_TO_BTF_ID)
+ env->insn_aux_data[insn_idx].ctx_field_size = info->ctx_field_size;
/* remember the offset of last byte accessed in ctx */
if (env->prog->aux->max_ctx_offset < off + size)
env->prog->aux->max_ctx_offset = off + size;
@@ -7224,9 +7209,7 @@ static int check_mem_access(struct bpf_v
if (err < 0)
return err;
- err = check_ctx_access(env, insn_idx, off, size, t, &info.reg_type,
- &info.btf, &info.btf_id, &info.is_retval,
- info.is_ldsx);
+ err = check_ctx_access(env, insn_idx, off, size, t, &info);
if (err)
verbose_linfo(env, insn_idx, "; ");
if (!err && t == BPF_READ && value_regno >= 0) {
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 543/602] bpf: Reset register bounds before narrowing retval range in check_mem_access()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (541 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 542/602] bpf: Refactor check_ctx_access() Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 544/602] block: add helper add_disk_final() Greg Kroah-Hartman
` (62 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Tristan Madani, Eduard Zingerman,
Alexei Starovoitov, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <tristan@talencesecurity.com>
[ Upstream commit 5e0b273e0a62cc04ec338c7b502797c66c2ed42a ]
When the BPF verifier processes a context load of an LSM hook return
value, it calls __mark_reg_s32_range() to narrow the register to the
hook's valid range. However, __mark_reg_s32_range() intersects the new
range with the register's existing bounds using max_t()/min_t() rather
than replacing them.
If the destination register carries stale bounds from a prior instruction
(e.g. BPF_MOV64_IMM), the intersection can produce a range narrower than
reality. The verifier then believes it knows the register's exact value,
while at runtime the actual hook return value is loaded, creating a
verifier/runtime mismatch that can be used to bypass BPF memory safety
checks.
The else branch already calls mark_reg_unknown() to reset register state
before any narrowing. Apply the same reset in the is_retval path so
stale bounds are cleared before __mark_reg_s32_range() intersects.
Fixes: 5d99e198be27 ("bpf, lsm: Add check for BPF LSM return value")
Cc: stable@vger.kernel.org
Signed-off-by: Tristan Madani <tristan@talencesecurity.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20260622230123.3695446-2-tristmd@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
kernel/bpf/verifier.c | 1 +
1 file changed, 1 insertion(+)
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -7219,6 +7219,7 @@ static int check_mem_access(struct bpf_v
*/
if (info.reg_type == SCALAR_VALUE) {
if (info.is_retval && get_func_retval_range(env->prog, &range)) {
+ mark_reg_unknown(env, regs, value_regno);
err = __mark_reg_s32_range(env, regs, value_regno,
range.minval, range.maxval);
if (err)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 544/602] block: add helper add_disk_final()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (542 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 543/602] bpf: Reset register bounds before narrowing retval range in check_mem_access() Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 545/602] block: remove redundant GD_NEED_PART_SCAN in add_disk_final() Greg Kroah-Hartman
` (61 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Ming Lei, Hannes Reinecke,
Nilay Shroff, Christoph Hellwig, Jens Axboe, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Lei <ming.lei@redhat.com>
[ Upstream commit 5fad1490ef510e3b70ad8b0a5a1e28a26638a95f ]
Add helper add_disk_final() for scanning partitions, announcing disk and
handling the last thing for adding disk.
No functional change, and prepare for prevent adding disk from happening
when updating nr_hw_queues.
Signed-off-by: Ming Lei <ming.lei@redhat.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Nilay Shroff <nilay@linux.ibm.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20250505141805.2751237-8-ming.lei@redhat.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Stable-dep-of: 181bb9c9eae4 ("block: remove redundant GD_NEED_PART_SCAN in add_disk_final()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
block/genhd.c | 46 +++++++++++++++++++++++++++-------------------
1 file changed, 27 insertions(+), 19 deletions(-)
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -382,6 +382,32 @@ int disk_scan_partitions(struct gendisk
return ret;
}
+static void add_disk_final(struct gendisk *disk)
+{
+ struct device *ddev = disk_to_dev(disk);
+
+ if (!(disk->flags & GENHD_FL_HIDDEN)) {
+ /* Make sure the first partition scan will be proceed */
+ if (get_capacity(disk) && disk_has_partscan(disk))
+ set_bit(GD_NEED_PART_SCAN, &disk->state);
+
+ bdev_add(disk->part0, ddev->devt);
+ if (get_capacity(disk))
+ disk_scan_partitions(disk, BLK_OPEN_READ);
+
+ /*
+ * Announce the disk and partitions after all partitions are
+ * created. (for hidden disks uevents remain suppressed forever)
+ */
+ dev_set_uevent_suppress(ddev, 0);
+ disk_uevent(disk, KOBJ_ADD);
+ }
+
+ blk_apply_bdi_limits(disk->bdi, &disk->queue->limits);
+ disk_add_events(disk);
+ set_bit(GD_ADDED, &disk->state);
+}
+
/**
* device_add_disk - add disk information to kernel list
* @parent: parent device for the disk
@@ -500,21 +526,6 @@ int __must_check device_add_disk(struct
&disk->bdi->dev->kobj, "bdi");
if (ret)
goto out_unregister_bdi;
-
- /* Make sure the first partition scan will be proceed */
- if (get_capacity(disk) && disk_has_partscan(disk))
- set_bit(GD_NEED_PART_SCAN, &disk->state);
-
- bdev_add(disk->part0, ddev->devt);
- if (get_capacity(disk))
- disk_scan_partitions(disk, BLK_OPEN_READ);
-
- /*
- * Announce the disk and partitions after all partitions are
- * created. (for hidden disks uevents remain suppressed forever)
- */
- dev_set_uevent_suppress(ddev, 0);
- disk_uevent(disk, KOBJ_ADD);
} else {
/*
* Even if the block_device for a hidden gendisk is not
@@ -523,10 +534,7 @@ int __must_check device_add_disk(struct
*/
disk->part0->bd_dev = MKDEV(disk->major, disk->first_minor);
}
-
- blk_apply_bdi_limits(disk->bdi, &disk->queue->limits);
- disk_add_events(disk);
- set_bit(GD_ADDED, &disk->state);
+ add_disk_final(disk);
return 0;
out_unregister_bdi:
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 545/602] block: remove redundant GD_NEED_PART_SCAN in add_disk_final()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (543 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 544/602] block: add helper add_disk_final() Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 546/602] dm-integrity: fix leaking uninitialized kernel memory Greg Kroah-Hartman
` (60 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Connor Williamson, Christoph Hellwig,
Jens Axboe, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Connor Williamson <connordw@amazon.com>
[ Upstream commit 181bb9c9eae4f69fe510a62a42c2932d0314a800 ]
add_disk_final() sets GD_NEED_PART_SCAN before calling bdev_add(),
then calls disk_scan_partitions() which sets the flag itself. The
early set is redundant and introduces a race.
Between bdev_add() and disk_scan_partitions(), concurrent openers
(multipathd, blkid, LVM) see the flag in blkdev_get_whole() and
trigger bdev_disk_changed(). When disk_scan_partitions() then runs,
it calls bdev_disk_changed() again, dropping the partitions the
concurrent opener already created before re-adding them, which can
result in transient partition disappearances.
The race is observable by inserting an msleep() between bdev_add()
and disk_scan_partitions() while running concurrent open() calls
during device bind. Without artificial delay, it manifests under
scheduling pressure during boot on systems with aggressive device
scanners (multipathd, systemd-udevd).
Therefore, do not set GD_NEED_PART_SCAN in add_disk_final(). Other
GD_NEED_PART_SCAN consumers (blkdev_get_whole(),
sd_need_revalidate()) should not be affected as the flag
is set internally by disk_scan_partitions().
The retry-on-next-open intention from commit e5cfefa97bcc
("block: fix scan partition for exclusively open device again")
should also not be affected as the early return paths in
disk_scan_partitions() should be unreachable at device registration
time (bd_holder is NULL and open_partitions is zero).
Fixes: e5cfefa97bcc ("block: fix scan partition for exclusively open device again")
Cc: stable@vger.kernel.org
Signed-off-by: Connor Williamson <connordw@amazon.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Link: https://patch.msgid.link/20260615130715.53693-1-connordw@amazon.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
block/genhd.c | 4 ----
1 file changed, 4 deletions(-)
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -387,10 +387,6 @@ static void add_disk_final(struct gendis
struct device *ddev = disk_to_dev(disk);
if (!(disk->flags & GENHD_FL_HIDDEN)) {
- /* Make sure the first partition scan will be proceed */
- if (get_capacity(disk) && disk_has_partscan(disk))
- set_bit(GD_NEED_PART_SCAN, &disk->state);
-
bdev_add(disk->part0, ddev->devt);
if (get_capacity(disk))
disk_scan_partitions(disk, BLK_OPEN_READ);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 546/602] dm-integrity: fix leaking uninitialized kernel memory
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (544 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 545/602] block: remove redundant GD_NEED_PART_SCAN in add_disk_final() Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 547/602] cleanup: add a scoped version of CLASS() Greg Kroah-Hartman
` (59 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Mikulas Patocka, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikulas Patocka <mpatocka@redhat.com>
[ Upstream commit 7bb03b2b01b814a9fc14afbfc2cbb2cca5b34750 ]
If hash size is less than device's tuple size, dm-integrity is supposed
to zero the remaining space. There was a bug in the code that zeroing
didn't work. This commit fixes it.
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Assisted-by: Claude:claude-opus-4.6
Fixes: fb0987682c62 ("dm-integrity: introduce the Inline mode")
Cc: stable@vger.kernel.org
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/md/dm-integrity.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -2502,7 +2502,7 @@ skip_spinlock:
struct bio_vec bv = bio_iter_iovec(bio, dio->bio_details.bi_iter);
const char *mem = bvec_kmap_local(&bv);
if (ic->tag_size < ic->tuple_size)
- memset(dio->integrity_payload + pos + ic->tag_size, 0, ic->tuple_size - ic->tuple_size);
+ memset(dio->integrity_payload + pos + ic->tag_size, 0, ic->tuple_size - ic->tag_size);
integrity_sector_checksum(ic, dio->bio_details.bi_iter.bi_sector, mem, dio->integrity_payload + pos);
kunmap_local(mem);
pos += ic->tuple_size;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 547/602] cleanup: add a scoped version of CLASS()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (545 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 546/602] dm-integrity: fix leaking uninitialized kernel memory Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 548/602] cleanup: fix scoped_class() Greg Kroah-Hartman
` (58 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Christian Brauner, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Brauner <brauner@kernel.org>
[ Upstream commit 5c21c5f22d0701ac6c1cafc0e8de4bf42e5c53e5 ]
This will make it possible to use:
scoped_class() {
}
constructs to limit variables to certain scopes and still perform
auto-cleanup.
Signed-off-by: Christian Brauner <brauner@kernel.org>
Stable-dep-of: 981ccd97f715 ("dm: avoid leaking the caller's thread keyring via the table device file")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/cleanup.h | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/include/linux/cleanup.h
+++ b/include/linux/cleanup.h
@@ -277,6 +277,14 @@ static inline class_##_name##_t class_##
class_##_name##_t var __cleanup(class_##_name##_destructor) = \
class_##_name##_constructor
+#define scoped_class(_name, var, args) \
+ for (CLASS(_name, var)(args); \
+ __guard_ptr(_name)(&var) || !__is_cond_ptr(_name); \
+ ({ goto _label; })) \
+ if (0) { \
+_label: \
+ break; \
+ } else
/*
* DEFINE_GUARD(name, type, lock, unlock):
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 548/602] cleanup: fix scoped_class()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (546 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 547/602] cleanup: add a scoped version of CLASS() Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 549/602] cred: add kernel_cred() helper Greg Kroah-Hartman
` (57 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jens Axboe, Christian Brauner,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Brauner <brauner@kernel.org>
[ Upstream commit 4e97bae1b412cd6ed8053b3d8a242122952985cc ]
This is a class, not a guard so why on earth is it checking for guard
pointers or conditional lock acquisition? None of it makes any sense at
all.
I'm not sure what happened back then. Maybe I had a brief psychedelic
period that I completely forgot about and spaced out into a zone where
that initial macro implementation made any sense at all.
Link: https://patch.msgid.link/20251103-work-creds-init_cred-v1-1-cb3ec8711a6a@kernel.org
Fixes: 5c21c5f22d07 ("cleanup: add a scoped version of CLASS()")
Reviewed-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Christian Brauner <brauner@kernel.org>
Stable-dep-of: 981ccd97f715 ("dm: avoid leaking the caller's thread keyring via the table device file")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/cleanup.h | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
--- a/include/linux/cleanup.h
+++ b/include/linux/cleanup.h
@@ -277,15 +277,16 @@ static inline class_##_name##_t class_##
class_##_name##_t var __cleanup(class_##_name##_destructor) = \
class_##_name##_constructor
-#define scoped_class(_name, var, args) \
- for (CLASS(_name, var)(args); \
- __guard_ptr(_name)(&var) || !__is_cond_ptr(_name); \
- ({ goto _label; })) \
- if (0) { \
-_label: \
- break; \
+#define __scoped_class(_name, var, _label, args...) \
+ for (CLASS(_name, var)(args); ; ({ goto _label; })) \
+ if (0) { \
+_label: \
+ break; \
} else
+#define scoped_class(_name, var, args...) \
+ __scoped_class(_name, var, __UNIQUE_ID(label), args)
+
/*
* DEFINE_GUARD(name, type, lock, unlock):
* trivial wrapper around DEFINE_CLASS() above specifically
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 549/602] cred: add kernel_cred() helper
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (547 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 548/602] cleanup: fix scoped_class() Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 550/602] cred: add scoped_with_kernel_creds() Greg Kroah-Hartman
` (56 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jens Axboe, Christian Brauner,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Brauner <brauner@kernel.org>
[ Upstream commit 4c7ceeb62d3330b6fb2b549ae833a92c0f481f3e ]
Access kernel creds based off of init_task. This will let us avoid any
direct access to init_cred.
Link: https://patch.msgid.link/20251103-work-creds-init_cred-v1-2-cb3ec8711a6a@kernel.org
Reviewed-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Christian Brauner <brauner@kernel.org>
Stable-dep-of: 981ccd97f715 ("dm: avoid leaking the caller's thread keyring via the table device file")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/cred.h | 7 +++++++
1 file changed, 7 insertions(+)
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -20,6 +20,8 @@
struct cred;
struct inode;
+extern struct task_struct init_task;
+
/*
* COW Supplementary groups list
*/
@@ -158,6 +160,11 @@ extern void abort_creds(struct cred *);
extern const struct cred *override_creds(const struct cred *);
extern void revert_creds(const struct cred *);
extern struct cred *prepare_kernel_cred(struct task_struct *);
+static inline const struct cred *kernel_cred(void)
+{
+ /* shut up sparse */
+ return rcu_dereference_raw(init_task.cred);
+}
extern int set_security_override(struct cred *, u32);
extern int set_security_override_from_ctx(struct cred *, const char *);
extern int set_create_files_as(struct cred *, struct inode *);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 550/602] cred: add scoped_with_kernel_creds()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (548 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 549/602] cred: add kernel_cred() helper Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 551/602] dm: avoid leaking the callers thread keyring via the table device file Greg Kroah-Hartman
` (55 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jens Axboe, Christian Brauner,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Brauner <brauner@kernel.org>
[ Upstream commit ae40e6c65791f47c76cc14d0cce2707fe6053f72 ]
Add a new cleanup class for override creds. We can make use of this in a
bunch of places going forward.
Based on this scoped_with_kernel_creds() that can be used to temporarily
assume kernel credentials for specific tasks such as firmware loading,
or coredump socket connections. At no point will the caller interact
with the kernel credentials directly.
Link: https://patch.msgid.link/20251103-work-creds-init_cred-v1-4-cb3ec8711a6a@kernel.org
Reviewed-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Christian Brauner <brauner@kernel.org>
Stable-dep-of: 981ccd97f715 ("dm: avoid leaking the caller's thread keyring via the table device file")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/cred.h | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -205,6 +205,14 @@ static inline struct cred *get_new_cred(
return get_new_cred_many(cred, 1);
}
+DEFINE_CLASS(override_creds,
+ const struct cred *,
+ revert_creds(_T),
+ override_creds(override_cred), const struct cred *override_cred)
+
+#define scoped_with_kernel_creds() \
+ scoped_class(override_creds, __UNIQUE_ID(cred), kernel_cred())
+
/**
* get_cred_many - Get references on a set of credentials
* @cred: The credentials to reference
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 551/602] dm: avoid leaking the callers thread keyring via the table device file
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (549 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 550/602] cred: add scoped_with_kernel_creds() Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 552/602] wifi: libertas_tf: fix use-after-free in lbtf_free_adapter() Greg Kroah-Hartman
` (54 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Ingo Blechschmidt, Mikulas Patocka,
Ondrej Kozina, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ingo Blechschmidt <iblech@speicherleck.de>
[ Upstream commit 981ccd97f7153d310dfa92a534525bbaf46752c2 ]
The refactoring in commit a28d893eb327 ("md: port block device access to file")
accidentally causes the caller's thread keyring to be kept alive long
beyond the caller's lifetime.
As a result, "cryptsetup luksSuspend" silently fails to wipe the
LUKS volume key from memory.
In detail: "cryptsetup luksOpen" uses its supposedly ephemeral thread
keyring to pass the volume key to the kernel. dm-crypt's
crypt_set_keyring_key() copies the key material into its own
crypt_config structure and then drops its own reference to the key in
the keyring with key_put().
With this fix, restoring pre-v6.9 behavior, the copy in the thread
keyring is then promptly garbage collected, such that exactly one copy
of the volume key remains. This single copy is correctly wiped from
memory on "cryptsetup luksSuspend".
Without this fix, the thread keyring and the volume key in it remains.
This second copy is only freed on "luksClose". "luksSuspend" neither
knows about this copy nor has any way to remove it, so the key remains
recoverable from RAM after a suspend that is documented to have wiped it.
This fix should not introduce new security problems, as the code is
anyway gated by CAP_SYS_ADMIN. The device-mapper core, not the calling
task, is the legitimate owner of this long-lived file.
Fixes: a28d893eb327 ("md: port block device access to file")
Closes: https://gitlab.com/cryptsetup/cryptsetup/-/work_items/993
Link: https://www.speicherleck.de/iblech/cryptsetup-luksSuspend-issue-reproduction/
Signed-off-by: Ingo Blechschmidt <iblech@speicherleck.de>
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Cc: stable@vger.kernel.org
Tested-by: Ondrej Kozina <okozina@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/md/dm.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -737,7 +737,16 @@ static struct table_device *open_table_d
return ERR_PTR(-ENOMEM);
refcount_set(&td->count, 1);
- bdev_file = bdev_file_open_by_dev(dev, mode, _dm_claim_ptr, NULL);
+ /*
+ * Open the backing device with kernel rather than caller
+ * credentials. Otherwise the caller's credentials would be
+ * pinned in bdev_file->f_cred until the table device is closed.
+ * That would keep the caller's thread keyring alive long beyond the
+ * lifetime of the caller, breaking userspace expectation (e.g.
+ * cryptsetup(8) leaking the LUKS volume key).
+ */
+ scoped_with_kernel_creds()
+ bdev_file = bdev_file_open_by_dev(dev, mode, _dm_claim_ptr, NULL);
if (IS_ERR(bdev_file)) {
r = PTR_ERR(bdev_file);
goto out_free_td;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 552/602] wifi: libertas_tf: fix use-after-free in lbtf_free_adapter()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (550 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 551/602] dm: avoid leaking the callers thread keyring via the table device file Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 553/602] mmc: vub300: fix use-after-free on disconnect Greg Kroah-Hartman
` (53 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Maoyi Xie, Johannes Berg,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maoyi Xie <maoyixie.tju@gmail.com>
[ Upstream commit aa6dcd5c8dd9ba1d7d0f60093bcda41c0d6d438d ]
lbtf_free_adapter() calls timer_delete(&priv->command_timer), which does
not wait for a running command_timer_fn() callback. lbtf_free_adapter()
runs on the teardown path right before ieee80211_free_hw() frees priv,
both in lbtf_remove_card() and in the probe error path. command_timer is
armed by mod_timer() in lbtf_cmd() whenever a firmware command is sent.
command_timer_fn() dereferences priv. If a command times out as the
device is removed, command_timer_fn() runs concurrently with teardown and
dereferences priv after it has been freed.
This is the same use-after-free that commit 03cc8f90d053 ("wifi: libertas:
fix use-after-free in lbs_free_adapter()") fixed in the sibling libertas
driver. The libertas_tf variant has the identical pattern and was left
unchanged. Use timer_delete_sync() so any in-flight callback completes
before priv is freed.
Fixes: 06b16ae53192 ("libertas_tf: main.c, data paths and mac80211 handlers")
Cc: stable@vger.kernel.org
Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
Link: https://patch.msgid.link/178211481807.2212567.8773346114561900100@maoyixie.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/wireless/marvell/libertas_tf/main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/wireless/marvell/libertas_tf/main.c
+++ b/drivers/net/wireless/marvell/libertas_tf/main.c
@@ -174,7 +174,7 @@ static void lbtf_free_adapter(struct lbt
{
lbtf_deb_enter(LBTF_DEB_MAIN);
lbtf_free_cmd_buffer(priv);
- del_timer(&priv->command_timer);
+ timer_delete_sync(&priv->command_timer);
lbtf_deb_leave(LBTF_DEB_MAIN);
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 553/602] mmc: vub300: fix use-after-free on disconnect
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (551 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 552/602] wifi: libertas_tf: fix use-after-free in lbtf_free_adapter() Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 554/602] mmc: vub300: rename probe error labels Greg Kroah-Hartman
` (52 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Binbin Zhou, Johan Hovold,
Ulf Hansson
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <johan@kernel.org>
The vub300 driver maintains an explicit reference count for the
controller and its driver data and the last reference can in theory be
dropped after the driver has been unbound.
This specifically means that the controller allocation must not be
device managed as that can lead to use-after-free.
Note that the lifetime is currently also incorrectly tied the parent USB
device rather than interface, which can lead to memory leaks if the
driver is unbound without its device being physically disconnected (e.g.
on probe deferral).
Fix both issues by reverting to non-managed allocation of the controller.
Fixes: dcfdd698dc52 ("mmc: vub300: Use devm_mmc_alloc_host() helper")
Cc: stable@vger.kernel.org # 6.17+
Cc: Binbin Zhou <zhoubinbin@loongson.cn>
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
(cherry picked from commit 8f4d20a710225ec7a565f6a0459862d3b1f32330)
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/mmc/host/vub300.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
--- a/drivers/mmc/host/vub300.c
+++ b/drivers/mmc/host/vub300.c
@@ -2279,7 +2279,7 @@ static int vub300_probe(struct usb_inter
dev_err(&vub300->udev->dev,
"Could not find two sets of bulk-in/out endpoint pairs\n");
retval = -EINVAL;
- goto error5;
+ goto err_free_host;
}
retval =
usb_control_msg(vub300->udev, usb_rcvctrlpipe(vub300->udev, 0),
@@ -2288,14 +2288,14 @@ static int vub300_probe(struct usb_inter
0x0000, 0x0000, &vub300->hc_info,
sizeof(vub300->hc_info), 1000);
if (retval < 0)
- goto error5;
+ goto err_free_host;
retval =
usb_control_msg(vub300->udev, usb_sndctrlpipe(vub300->udev, 0),
SET_ROM_WAIT_STATES,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
firmware_rom_wait_states, 0x0000, NULL, 0, 1000);
if (retval < 0)
- goto error5;
+ goto err_free_host;
dev_info(&vub300->udev->dev,
"operating_mode = %s %s %d MHz %s %d byte USB packets\n",
(mmc->caps & MMC_CAP_SDIO_IRQ) ? "IRQs" : "POLL",
@@ -2310,7 +2310,7 @@ static int vub300_probe(struct usb_inter
0x0000, 0x0000, &vub300->system_port_status,
sizeof(vub300->system_port_status), 1000);
if (retval < 0) {
- goto error5;
+ goto err_free_host;
} else if (sizeof(vub300->system_port_status) == retval) {
vub300->card_present =
(0x0001 & vub300->system_port_status.port_flags) ? 1 : 0;
@@ -2318,7 +2318,7 @@ static int vub300_probe(struct usb_inter
(0x0010 & vub300->system_port_status.port_flags) ? 1 : 0;
} else {
retval = -EINVAL;
- goto error5;
+ goto err_free_host;
}
usb_set_intfdata(interface, vub300);
INIT_DELAYED_WORK(&vub300->pollwork, vub300_pollwork_thread);
@@ -2348,7 +2348,7 @@ static int vub300_probe(struct usb_inter
return 0;
error6:
del_timer_sync(&vub300->inactivity_timer);
-error5:
+err_free_host:
mmc_free_host(mmc);
/*
* and hence also frees vub300
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 554/602] mmc: vub300: rename probe error labels
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (552 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 553/602] mmc: vub300: fix use-after-free on disconnect Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 555/602] mmc: vub300: fix use-after-free on probe failure Greg Kroah-Hartman
` (51 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Johan Hovold, Ulf Hansson
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <johan@kernel.org>
Error labels should be named after what they do.
Rename the probe error labels.
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
(cherry picked from commit 5b8b35d6f4fa758dd5e8ae18526ea1c73f6787e0)
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/mmc/host/vub300.c | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
--- a/drivers/mmc/host/vub300.c
+++ b/drivers/mmc/host/vub300.c
@@ -2114,19 +2114,19 @@ static int vub300_probe(struct usb_inter
command_out_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!command_out_urb) {
retval = -ENOMEM;
- goto error0;
+ goto err_put_udev;
}
command_res_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!command_res_urb) {
retval = -ENOMEM;
- goto error1;
+ goto err_free_out_urb;
}
/* this also allocates memory for our VUB300 mmc host device */
mmc = mmc_alloc_host(sizeof(struct vub300_mmc_host), &udev->dev);
if (!mmc) {
retval = -ENOMEM;
dev_err(&udev->dev, "not enough memory for the mmc_host\n");
- goto error4;
+ goto err_free_res_urb;
}
/* MMC core transfer sizes tunable parameters */
mmc->caps = 0;
@@ -2343,23 +2343,25 @@ static int vub300_probe(struct usb_inter
interface_to_InterfaceNumber(interface));
retval = mmc_add_host(mmc);
if (retval)
- goto error6;
+ goto err_delete_timer;
return 0;
-error6:
- del_timer_sync(&vub300->inactivity_timer);
+
+err_delete_timer:
+ timer_delete_sync(&vub300->inactivity_timer);
err_free_host:
mmc_free_host(mmc);
/*
* and hence also frees vub300
* which is contained at the end of struct mmc
*/
-error4:
+err_free_res_urb:
usb_free_urb(command_res_urb);
-error1:
+err_free_out_urb:
usb_free_urb(command_out_urb);
-error0:
+err_put_udev:
usb_put_dev(udev);
+
return retval;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 555/602] mmc: vub300: fix use-after-free on probe failure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (553 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 554/602] mmc: vub300: rename probe error labels Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 556/602] locking/rt: Fix the incorrect RCU protection in rt_spin_unlock() Greg Kroah-Hartman
` (50 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Guangshuo Li, Johan Hovold,
Ulf Hansson
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <lgs201920130244@gmail.com>
The vub300 driver lifetime-manages its controller state using
vub300->kref, with vub300_delete() freeing the mmc host when the last
reference is dropped. The probe error path after the inactivity timer has
been armed still bypasses that lifetime rule, however, and falls through
to mmc_free_host() directly if mmc_add_host() fails.
The race window is between arming the inactivity timer and reaching the
probe error unwind after mmc_add_host() fails:
probe thread timer/workqueue
------------ ---------------
kref_init(&vub300->kref) ref = 1
kref_get(&vub300->kref) ref = 2, timer ref
add_timer(inactivity_timer) fires after one second
|
| race window
|<---------------------------------------------------->
|
mmc_add_host(mmc)
inactivity timer fires
vub300_queue_dead_work()
kref_get() ref = 3
queue_work(deadwork)
mmc_add_host() fails
timer_delete_sync()
mmc_free_host(mmc)
frees vub300
deadwork runs
use-after-free
The inactivity timeout is one second, so this would require
mmc_add_host() to both fail and take more than one second to do so. This
is unlikely to happen in practice, but the error path is still wrong.
timer_delete_sync() only waits for the timer callback itself. It does
not flush deadwork that the callback may already have queued. As a
result, queued deadwork can still hold a kref while the probe error path
directly frees the backing mmc host, including the vub300 storage.
Fix this by using the same lifetime mechanism as disconnect. Clear
vub300->interface so that the timer callback and any queued deadwork
return early and drop their references, then drop the initial probe
reference and return without falling through to err_free_host.
Fixes: 0613ad2401f8 ("mmc: vub300: fix return value check of mmc_add_host()")
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
Reviewed-by: Johan Hovold <johan@kernel.org>
Cc: stable@vger.kernel.org
Signed-off-by: Ulf Hansson <ulfh@kernel.org>
(cherry picked from commit a3b5f242997a3be7404112fd48784881560aea57)
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/mmc/host/vub300.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
--- a/drivers/mmc/host/vub300.c
+++ b/drivers/mmc/host/vub300.c
@@ -2343,12 +2343,16 @@ static int vub300_probe(struct usb_inter
interface_to_InterfaceNumber(interface));
retval = mmc_add_host(mmc);
if (retval)
- goto err_delete_timer;
+ goto err_stop_io;
return 0;
-err_delete_timer:
- timer_delete_sync(&vub300->inactivity_timer);
+err_stop_io:
+ vub300->interface = NULL;
+ kref_put(&vub300->kref, vub300_delete);
+
+ return retval;
+
err_free_host:
mmc_free_host(mmc);
/*
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 556/602] locking/rt: Fix the incorrect RCU protection in rt_spin_unlock()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (554 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 555/602] mmc: vub300: fix use-after-free on probe failure Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 557/602] net: mana: Validate the packet length reported by the NIC Greg Kroah-Hartman
` (49 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, syzbot+000c800a02097aaa10ed,
Thomas Gleixner, Sebastian Andrzej Siewior, Al Viro, Sasha Levin,
Jann Horn
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Gleixner <tglx@kernel.org>
[ Upstream commit 89038cc87d80c77e7aa6f42a64b2573b74af339f ]
rt_spin_unlock() releases the RCU protection before unlocking the
lock. That opens the door for the following UAF scenario:
T1 T2
spin_lock(&p->lock); rcu_read_lock();
invalidate(p); p = rcu_dereference(ptr);
rcu_assign_pointer(ptr, NULL); if (!p) return;
spin_unlock(&p->lock); spin_lock(&p->lock)
lock(&lock->lock);
rcu_read_lock();
kfree_rcu(p); rcu_read_unlock();
....
spin_unlock(&p->lock)
rcu_read_unlock(); // Ends grace period
rcu_do_batch()
kfree(p);
UAF -> rt_mutex_cmpxchg_release(&lock->lock...)
Regular spinlocks keep preemption disabled accross the unlock operation,
which provides full RCU protection, but the RT substitution fails to
resemble that. Same applies for the rwlock substitution.
Move the rcu_read_unlock() invocation past the unlock operations to match
the non-RT semantics. This makes it asymmetric vs. rt_xxx_lock(), but
that's harmless as the caller needs to hold RCU read lock across the lock
operation. The migrate_enable() call stays before the unlock operation
because there is no per CPU operation in the unlock path which would
require migration to be kept disabled.
Fixes: 0f383b6dc96e ("locking/spinlock: Provide RT variant")
Reported-by: syzbot+000c800a02097aaa10ed@syzkaller.appspotmail.com
Decoded-by: Jann Horn <jannh@google.com>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Acked-by: Al Viro <viro@zeniv.linux.org.uk>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/87jyrud75z.ffs@fw13
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
kernel/locking/spinlock_rt.c | 27 ++++++++++++++++++++++++---
1 file changed, 24 insertions(+), 3 deletions(-)
--- a/kernel/locking/spinlock_rt.c
+++ b/kernel/locking/spinlock_rt.c
@@ -79,10 +79,27 @@ void __sched rt_spin_unlock(spinlock_t *
{
spin_release(&lock->dep_map, _RET_IP_);
migrate_enable();
- rcu_read_unlock();
if (unlikely(!rt_mutex_cmpxchg_release(&lock->lock, current, NULL)))
rt_mutex_slowunlock(&lock->lock);
+
+ /*
+ * This must be last to prevent the following UAF:
+ *
+ * T1 T2
+ * spin_lock(&p->lock); rcu_read_lock();
+ * invalidate(p); p = rcu_dereference(ptr);
+ * rcu_assign_pointer(ptr, NULL); if (!p) return;
+ * spin_unlock(&p->lock); spin_lock(&p->lock);
+ * kfree_rcu(p); rcu_read_unlock();
+ * ....
+ * spin_unlock(&p->lock)
+ * rcu_read_unlock(); // Ends grace period
+ * rcu_do_batch()
+ * kfree(p);
+ * UAF -> rt_mutex_cmpxchg_release(&p->lock.lock...)
+ */
+ rcu_read_unlock();
}
EXPORT_SYMBOL(rt_spin_unlock);
@@ -262,17 +279,21 @@ void __sched rt_read_unlock(rwlock_t *rw
{
rwlock_release(&rwlock->dep_map, _RET_IP_);
migrate_enable();
- rcu_read_unlock();
rwbase_read_unlock(&rwlock->rwbase, TASK_RTLOCK_WAIT);
+
+ /* This must be last. See comment in rt_spin_unlock() */
+ rcu_read_unlock();
}
EXPORT_SYMBOL(rt_read_unlock);
void __sched rt_write_unlock(rwlock_t *rwlock)
{
rwlock_release(&rwlock->dep_map, _RET_IP_);
- rcu_read_unlock();
migrate_enable();
rwbase_write_unlock(&rwlock->rwbase);
+
+ /* This must be last. See comment in rt_spin_unlock() */
+ rcu_read_unlock();
}
EXPORT_SYMBOL(rt_write_unlock);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 557/602] net: mana: Validate the packet length reported by the NIC
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (555 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 556/602] locking/rt: Fix the incorrect RCU protection in rt_spin_unlock() Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 558/602] net: ip6_tunnel: require CAP_NET_ADMIN in the device netns for changelink Greg Kroah-Hartman
` (48 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Haiyang Zhang, Dexuan Cui,
Paolo Abeni, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dexuan Cui <decui@microsoft.com>
[ Upstream commit 2e2a83b4998af4384e677d3b2ac08565274279bf ]
Validate the packet length reported in the RX CQE before passing it
to skb processing. The CQE is supplied by the NIC device and should
not be blindly trusted.
Cc: stable@vger.kernel.org
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: Dexuan Cui <decui@microsoft.com>
Fixes: ca9c54d2d6a5 ("net: mana: Add a driver for Microsoft Azure Network Adapter (MANA)")
Link: https://patch.msgid.link/20260702041237.617719-2-decui@microsoft.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/microsoft/mana/mana_en.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -1724,6 +1724,19 @@ static void mana_process_rx_cqe(struct m
rxbuf_oob = &rxq->rx_oobs[curr];
WARN_ON_ONCE(rxbuf_oob->wqe_inf.wqe_size_in_bu != 1);
+ if (unlikely(pktlen > rxq->datasize)) {
+ /* Increase it even if mana_rx_skb() isn't called. */
+ rxq->rx_cq.work_done++;
+
+ ++ndev->stats.rx_dropped;
+ netdev_warn_once(ndev,
+ "Dropped oversized RX packet: len=%u, datasize=%u\n",
+ pktlen, rxq->datasize);
+
+ /* Reuse the RX buffer since rxbuf_oob is unchanged. */
+ goto drop;
+ }
+
mana_refill_rx_oob(dev, rxq, rxbuf_oob, &old_buf, &old_fp);
/* Unsuccessful refill will have old_buf == NULL.
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 558/602] net: ip6_tunnel: require CAP_NET_ADMIN in the device netns for changelink
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (556 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 557/602] net: mana: Validate the packet length reported by the NIC Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 559/602] gve: fix header buffer corruption with header-split and HW-GRO Greg Kroah-Hartman
` (47 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Xiao Liang, Maoyi Xie,
Kuniyuki Iwashima, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maoyi Xie <maoyixie.tju@gmail.com>
[ Upstream commit 2496fa0b7d180b3ad356b514e7ff93bb14e6140a ]
ip6_tnl_changelink() operates on at most two netns, dev_net(dev) and the
tunnel link netns t->net. They differ once the device is created in or
moved to a netns other than the one the request runs in. The rtnl
changelink path checks CAP_NET_ADMIN only against dev_net(dev), so a
caller privileged there but not in t->net can rewrite a tunnel that
lives in t->net.
Gate ip6_tnl_changelink() on rtnl_dev_link_net_capable() at its top,
before any attribute is parsed.
Reported-by: Xiao Liang <shaw.leon@gmail.com>
Closes: https://lore.kernel.org/netdev/CABAhCOSzP1vaThGV35_VnsRCb=87_CPjPVsTHbq905k8A+BuUg@mail.gmail.com/
Fixes: 0bd8762824e7 ("ip6tnl: add x-netns support")
Cc: stable@vger.kernel.org
Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Link: https://patch.msgid.link/20260612085941.3158249-5-maoyixie.tju@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ipv6/ip6_tunnel.c | 3 +++
1 file changed, 3 insertions(+)
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -2053,6 +2053,9 @@ static int ip6_tnl_changelink(struct net
struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
struct ip_tunnel_encap ipencap;
+ if (!rtnl_dev_link_net_capable(dev, net))
+ return -EPERM;
+
if (dev == ip6n->fb_tnl_dev)
return -EINVAL;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 559/602] gve: fix header buffer corruption with header-split and HW-GRO
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (557 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 558/602] net: ip6_tunnel: require CAP_NET_ADMIN in the device netns for changelink Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 560/602] gpio: mt7621: avoid corruption of shared interrupt trigger state Greg Kroah-Hartman
` (46 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Ankit Garg, Praveen Kaligineedi,
Jordan Rhee, Harshitha Ramamurthy, Joshua Washington,
Eric Dumazet, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ankit Garg <nktgrg@google.com>
[ Upstream commit d676c9a73bdcd8237425dbb826f2bd1a25c36e40 ]
The DQO RX datapath programs a per-buffer-queue-descriptor
header_buf_addr at post time and reads the split header back at
completion time. Both the post and the read currently index the
header buffer by queue position rather than by the buffer's identity:
- post (gve_rx_post_buffers_dqo): header_buf_addr is computed from
bufq->tail
- read (gve_rx_dqo): the header is read from desc_idx (the completion
queue head index)
This relies on the buffer-queue index and the completion-queue index
being equal for the start of every packet, i.e. on the device consuming
posted buffers and returning completions in the exact same order. That
assumption does not hold once HW-GRO is enabled with multiple
flows: coalesced segments are accepted and completed in an order that
may differ from the order buffers were posted, and segments from
different flows may interleave.
That results in two problems:
1. Wrong header slot on read. Because the read offset is derived from
the completion index (desc_idx) while the device wrote the header to
the address programmed for the buffer's buf_id, the driver can copy
a header belonging to a different packet. This shows up as
throughput drop (about 30% drop and large numbers of TCP
retransmissions) with header-split and HW-GRO both enabled and many
streams.
2. Header buffer reused while still owned by the device. The driver
advances bufq->head by one per completion and re-posts buffers based
on that. Arrival of N RX completions only guarantees that at least N
RX buffer descriptors have been read by the device. It does not
guarantee that the device has relinquished the ownership of all the
buffers corresponding to those N descriptors. With out-of-order
completions (e.g. the completion for a packet copied into buffer N
arrives before the completion for a packet copied into buffer N-1),
the driver can re-post and overwrite a header buffer that the device
is still going to write into, corrupting the header of a packet
whose completion has not yet been processed.
Fix both issues by indexing the header buffer by buf_id on both the post
and read paths. Reading from buf_id's slot is therefore always correct
regardless of completion ordering (fixes problem 1).
Indexing by buf_id also ties each header slot to the lifetime of its
buffer state. A buffer state is only returned to the free/recycle lists
when its own completion (buf_id) is processed, so its header slot can
only be re-posted after the device is done with it. This makes header
slot reuse safe under out-of-order completions (fixes problem 2).
Allocate (gve_rx_alloc_hdr_bufs) and free (gve_rx_free_hdr_bufs) the
header buffers based on num_buf_states to match the buf_id indexing.
Cc: stable@vger.kernel.org
Fixes: 5e37d8254e7f ("gve: Add header split data path")
Signed-off-by: Ankit Garg <nktgrg@google.com>
Reviewed-by: Praveen Kaligineedi <pkaligineedi@google.com>
Reviewed-by: Jordan Rhee <jordanrhee@google.com>
Reviewed-by: Harshitha Ramamurthy <hramamurthy@google.com>
Signed-off-by: Joshua Washington <joshwash@google.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260617013208.3781453-1-joshwash@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/google/gve/gve_rx_dqo.c | 28 +++++++++++++++++----------
1 file changed, 18 insertions(+), 10 deletions(-)
--- a/drivers/net/ethernet/google/gve/gve_rx_dqo.c
+++ b/drivers/net/ethernet/google/gve/gve_rx_dqo.c
@@ -212,11 +212,13 @@ static void gve_rx_starvation_timer(stru
static void gve_rx_free_hdr_bufs(struct gve_priv *priv, struct gve_rx_ring *rx)
{
struct device *hdev = &priv->pdev->dev;
- int buf_count = rx->dqo.bufq.mask + 1;
if (rx->dqo.hdr_bufs.data) {
- dma_free_coherent(hdev, priv->header_buf_size * buf_count,
- rx->dqo.hdr_bufs.data, rx->dqo.hdr_bufs.addr);
+ size_t size =
+ (size_t)priv->header_buf_size * rx->dqo.num_buf_states;
+
+ dma_free_coherent(hdev, size, rx->dqo.hdr_bufs.data,
+ rx->dqo.hdr_bufs.addr);
rx->dqo.hdr_bufs.data = NULL;
}
}
@@ -421,7 +423,7 @@ int gve_rx_alloc_ring_dqo(struct gve_pri
/* Allocate header buffers for header-split */
if (cfg->enable_header_split)
- if (gve_rx_alloc_hdr_bufs(priv, rx, buffer_queue_slots))
+ if (gve_rx_alloc_hdr_bufs(priv, rx, rx->dqo.num_buf_states))
goto err;
/* Allocate RX completion queue */
@@ -557,10 +559,13 @@ void gve_rx_post_buffers_dqo(struct gve_
desc->buf_id = cpu_to_le16(buf_state - rx->dqo.buf_states);
desc->buf_addr = cpu_to_le64(buf_state->addr +
buf_state->page_info.page_offset);
- if (rx->dqo.hdr_bufs.data)
+ if (rx->dqo.hdr_bufs.data) {
+ u16 buf_id = le16_to_cpu(desc->buf_id);
+
desc->header_buf_addr =
cpu_to_le64(rx->dqo.hdr_bufs.addr +
- priv->header_buf_size * bufq->tail);
+ (size_t)priv->header_buf_size * buf_id);
+ }
bufq->tail = (bufq->tail + 1) & bufq->mask;
complq->num_free_slots--;
@@ -827,10 +832,13 @@ static int gve_rx_dqo(struct napi_struct
int unsplit = 0;
if (hdr_len && !hbo) {
- rx->ctx.skb_head = gve_rx_copy_data(priv->dev, napi,
- rx->dqo.hdr_bufs.data +
- desc_idx * priv->header_buf_size,
- hdr_len);
+ size_t offset =
+ (size_t)buffer_id * priv->header_buf_size;
+
+ rx->ctx.skb_head =
+ gve_rx_copy_data(priv->dev, napi,
+ rx->dqo.hdr_bufs.data + offset,
+ hdr_len);
if (unlikely(!rx->ctx.skb_head))
goto error;
rx->ctx.skb_tail = rx->ctx.skb_head;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 560/602] gpio: mt7621: avoid corruption of shared interrupt trigger state
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (558 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 559/602] gve: fix header buffer corruption with header-split and HW-GRO Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 561/602] octeontx2-af: cn10k: restrict VF LMTLINE sharing to its own PF Greg Kroah-Hartman
` (45 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sashiko, Sergio Paracuellos,
Bartosz Golaszewski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sergio Paracuellos <sergio.paracuellos@gmail.com>
[ Upstream commit 1781172526d1092323af443fa03f00e6de560401 ]
The bank-shared fields like 'rising' and 'falling' are modified using
non-atomic read-modify-write operations. Since every gpio chip instance
represents an entire bank of 32 pins, if 'mediatek_gpio_irq_type()' is
called concurrently for different IRQs on the same bank a possible overwrite
of each other's configuration is possible. Thus, protect this state with
'gpio_generic_lock_irqsave' lock in the same way it is handled in irp_chip
'mediatek_gpio_irq_mask()' and 'mediatek_gpio_irq_unmask()' callbacks.
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-bot@kernel.org>
Fixes: 4ba9c3afda41 ("gpio: mt7621: Add a driver for MT7621")
Signed-off-by: Sergio Paracuellos <sergio.paracuellos@gmail.com>
Link: https://patch.msgid.link/20260626060112.2498324-2-sergio.paracuellos@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
[ Changed `guard(gpio_generic_lock_irqsave)(&rg->chip)` to `guard(spinlock_irqsave)(&rg->lock)` as the generic GPIO chip lock does not exist in this tree. ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpio/gpio-mt7621.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/gpio/gpio-mt7621.c
+++ b/drivers/gpio/gpio-mt7621.c
@@ -156,6 +156,8 @@ mediatek_gpio_irq_type(struct irq_data *
int pin = d->hwirq;
u32 mask = BIT(pin);
+ guard(spinlock_irqsave)(&rg->lock);
+
if (type == IRQ_TYPE_PROBE) {
if ((rg->rising | rg->falling |
rg->hlevel | rg->llevel) & mask)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 561/602] octeontx2-af: cn10k: restrict VF LMTLINE sharing to its own PF
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (559 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 560/602] gpio: mt7621: avoid corruption of shared interrupt trigger state Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 562/602] bootconfig: move xbc_snprint_cmdline() to lib/bootconfig.c Greg Kroah-Hartman
` (44 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yuhao Jiang, Junrui Luo,
Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Junrui Luo <moonafterrain@outlook.com>
[ Upstream commit 8cdcf3d2caacdee7ddd363705fb4d93b0c1a0915 ]
rvu_mbox_handler_lmtst_tbl_setup() uses req->base_pcifunc as a direct
index into the LMT map table to read another function's LMTLINE
physical base address and copy it into the caller's own LMT map table
entry. The mailbox dispatcher authenticates req->hdr.pcifunc from the
IRQ source, but req->base_pcifunc is a separate payload field and is
not sanitized.
Reject the request with -EPERM when a VF caller's base_pcifunc is not a
valid function under its own PF. is_pf_func_valid() bounds the FUNC field
to the PF's configured VF count, keeping the computed index inside the
caller's own slot block.
Fixes: 893ae97214c3 ("octeontx2-af: cn10k: Support configurable LMTST regions")
Reported-by: Yuhao Jiang <danisjiang@gmail.com>
Cc: stable@vger.kernel.org
Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
Link: https://patch.msgid.link/SYBPR01MB78811656934E713B77DA6CEDAFE62@SYBPR01MB7881.ausprd01.prod.outlook.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
[ Dropped `rvu->pdev` argument from `rvu_get_pf()` calls and folded in the `is_pf_func_valid()` de-static plus its `rvu.h` declaration from commit 2156a29aecff. ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/marvell/octeontx2/af/rvu.c | 2 +-
drivers/net/ethernet/marvell/octeontx2/af/rvu.h | 1 +
drivers/net/ethernet/marvell/octeontx2/af/rvu_cn10k.c | 9 +++++++++
3 files changed, 11 insertions(+), 1 deletion(-)
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
@@ -440,7 +440,7 @@ struct rvu_pfvf *rvu_get_pfvf(struct rvu
return &rvu->pf[rvu_get_pf(pcifunc)];
}
-static bool is_pf_func_valid(struct rvu *rvu, u16 pcifunc)
+bool is_pf_func_valid(struct rvu *rvu, u16 pcifunc)
{
int pf, vf, nvfs;
u64 cfg;
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
@@ -825,6 +825,7 @@ int rvu_get_pf(u16 pcifunc);
struct rvu_pfvf *rvu_get_pfvf(struct rvu *rvu, int pcifunc);
void rvu_get_pf_numvfs(struct rvu *rvu, int pf, int *numvfs, int *hwvf);
bool is_block_implemented(struct rvu_hwinfo *hw, int blkaddr);
+bool is_pf_func_valid(struct rvu *rvu, u16 pcifunc);
bool is_pffunc_map_valid(struct rvu *rvu, u16 pcifunc, int blktype);
int rvu_get_lf(struct rvu *rvu, struct rvu_block *block, u16 pcifunc, u16 slot);
int rvu_lf_reset(struct rvu *rvu, struct rvu_block *block, int lf);
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_cn10k.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_cn10k.c
@@ -178,6 +178,15 @@ int rvu_mbox_handler_lmtst_tbl_setup(str
* pcifunc (will be the one who is calling this mailbox).
*/
if (req->base_pcifunc) {
+ /* A VF is untrusted and must not redirect its LMTLINE to
+ * another PF's region, so confine VF callers to their own PF.
+ */
+ if (is_vf(req->hdr.pcifunc) &&
+ (!is_pf_func_valid(rvu, req->base_pcifunc) ||
+ rvu_get_pf(req->hdr.pcifunc) !=
+ rvu_get_pf(req->base_pcifunc)))
+ return -EPERM;
+
/* Calculating the LMT table index equivalent to primary
* pcifunc.
*/
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 562/602] bootconfig: move xbc_snprint_cmdline() to lib/bootconfig.c
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (560 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 561/602] octeontx2-af: cn10k: restrict VF LMTLINE sharing to its own PF Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 563/602] bootconfig: fix NULL-pointer arithmetic in xbc_snprint_cmdline() Greg Kroah-Hartman
` (43 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Breno Leitao,
Masami Hiramatsu (Google), Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Breno Leitao <leitao@debian.org>
[ Upstream commit 5a643e4623238e14b03d75ca0d4eda0645720cee ]
Move xbc_snprint_cmdline() from init/main.c to lib/bootconfig.c so the
function (and its xbc_namebuf scratch buffer) becomes part of the shared
parser library. tools/bootconfig already compiles lib/bootconfig.c
directly, which lets a follow-up patch reuse the same renderer in the
userspace tool to convert a bootconfig file into a flat cmdline string
at build time.
No functional change.
Link: https://lore.kernel.org/all/20260508-bootconfig_using_tools-v1-1-1132219aa773@debian.org/
Signed-off-by: Breno Leitao <leitao@debian.org>
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Stable-dep-of: dec4d8118c17 ("bootconfig: fix NULL-pointer arithmetic in xbc_snprint_cmdline()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/bootconfig.h | 3 ++
init/main.c | 45 ------------------------------------
lib/bootconfig.c | 56 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 59 insertions(+), 45 deletions(-)
--- a/include/linux/bootconfig.h
+++ b/include/linux/bootconfig.h
@@ -265,6 +265,9 @@ static inline struct xbc_node * __init x
int __init xbc_node_compose_key_after(struct xbc_node *root,
struct xbc_node *node, char *buf, size_t size);
+/* Render key/value pairs under @root as a flat cmdline string */
+int __init xbc_snprint_cmdline(char *buf, size_t size, struct xbc_node *root);
+
/**
* xbc_node_compose_key() - Compose full key string of the XBC node
* @node: An XBC node.
--- a/init/main.c
+++ b/init/main.c
@@ -318,51 +318,6 @@ static void * __init get_boot_config_fro
#ifdef CONFIG_BOOT_CONFIG
-static char xbc_namebuf[XBC_KEYLEN_MAX] __initdata;
-
-#define rest(dst, end) ((end) > (dst) ? (end) - (dst) : 0)
-
-static int __init xbc_snprint_cmdline(char *buf, size_t size,
- struct xbc_node *root)
-{
- struct xbc_node *knode, *vnode;
- char *end = buf + size;
- const char *val, *q;
- int ret;
-
- xbc_node_for_each_key_value(root, knode, val) {
- ret = xbc_node_compose_key_after(root, knode,
- xbc_namebuf, XBC_KEYLEN_MAX);
- if (ret < 0)
- return ret;
-
- vnode = xbc_node_get_child(knode);
- if (!vnode) {
- ret = snprintf(buf, rest(buf, end), "%s ", xbc_namebuf);
- if (ret < 0)
- return ret;
- buf += ret;
- continue;
- }
- xbc_array_for_each_value(vnode, val) {
- /*
- * For prettier and more readable /proc/cmdline, only
- * quote the value when necessary, i.e. when it contains
- * whitespace.
- */
- q = strpbrk(val, " \t\r\n") ? "\"" : "";
- ret = snprintf(buf, rest(buf, end), "%s=%s%s%s ",
- xbc_namebuf, q, val, q);
- if (ret < 0)
- return ret;
- buf += ret;
- }
- }
-
- return buf - (end - size);
-}
-#undef rest
-
/* Make an extra command line under given key word */
static char * __init xbc_make_cmdline(const char *key)
{
--- a/lib/bootconfig.c
+++ b/lib/bootconfig.c
@@ -405,6 +405,62 @@ const char * __init xbc_node_find_next_k
return ""; /* No value key */
}
+static char xbc_namebuf[XBC_KEYLEN_MAX] __initdata;
+
+#define rest(dst, end) ((end) > (dst) ? (end) - (dst) : 0)
+
+/**
+ * xbc_snprint_cmdline() - Render bootconfig keys under @root as a cmdline string
+ * @buf: Destination buffer (may be NULL when @size is 0 to query the length)
+ * @size: Size of @buf in bytes
+ * @root: Subtree root whose key=value pairs should be rendered
+ *
+ * Walk all key/value pairs under @root and emit them as a space-separated
+ * cmdline string into @buf. Values containing whitespace are quoted with
+ * double quotes. Returns the number of bytes that would be written if @buf
+ * were large enough (matching snprintf semantics), or a negative errno on
+ * failure.
+ */
+int __init xbc_snprint_cmdline(char *buf, size_t size, struct xbc_node *root)
+{
+ struct xbc_node *knode, *vnode;
+ char *end = buf + size;
+ const char *val, *q;
+ int ret;
+
+ xbc_node_for_each_key_value(root, knode, val) {
+ ret = xbc_node_compose_key_after(root, knode,
+ xbc_namebuf, XBC_KEYLEN_MAX);
+ if (ret < 0)
+ return ret;
+
+ vnode = xbc_node_get_child(knode);
+ if (!vnode) {
+ ret = snprintf(buf, rest(buf, end), "%s ", xbc_namebuf);
+ if (ret < 0)
+ return ret;
+ buf += ret;
+ continue;
+ }
+ xbc_array_for_each_value(vnode, val) {
+ /*
+ * For prettier and more readable /proc/cmdline, only
+ * quote the value when necessary, i.e. when it contains
+ * whitespace.
+ */
+ q = strpbrk(val, " \t\r\n") ? "\"" : "";
+ ret = snprintf(buf, rest(buf, end), "%s=%s%s%s ",
+ xbc_namebuf, q, val, q);
+ if (ret < 0)
+ return ret;
+ buf += ret;
+ }
+ }
+
+ return buf - (end - size);
+}
+#undef rest
+
/* XBC parse and tree build */
static int __init xbc_init_node(struct xbc_node *node, char *data, uint32_t flag)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 563/602] bootconfig: fix NULL-pointer arithmetic in xbc_snprint_cmdline()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (561 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 562/602] bootconfig: move xbc_snprint_cmdline() to lib/bootconfig.c Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 564/602] ipmi: fix refcount leak in i_ipmi_request() Greg Kroah-Hartman
` (42 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Breno Leitao,
Masami Hiramatsu (Google), Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Breno Leitao <leitao@debian.org>
[ Upstream commit dec4d8118c179b3d12bca7e609054c6011c4f2ce ]
xbc_snprint_cmdline() is meant to be called twice: first with
buf=NULL, size=0 to probe the rendered length, then with a real
buffer to fill it (the standard snprintf() two-pass pattern). The
probe call makes the function compute "buf + size" (NULL + 0) and,
on every iteration, advance "buf += ret" from that NULL base and
pass the result back into snprintf().
Pointer arithmetic on a NULL pointer is undefined behavior. It is
harmless in the in-kernel callers today, but the follow-up patches
run this same code in the userspace tools/bootconfig parser at kernel
build time, where host UBSan / FORTIFY_SOURCE abort the build.
Track a running written length (size_t) instead of mutating @buf, and
only form "buf + len" when @buf is non-NULL. snprintf(NULL, 0, ...)
is itself well defined and returns the would-be length, so the
two-pass "probe then fill" usage returns identical byte counts.
Link: https://lore.kernel.org/all/20260626-bootconfig_using_tools-v7-1-24ab72139c29@debian.org/
Fixes: 51887d03aca1 ("bootconfig: init: Allow admin to use bootconfig for kernel command line")
Cc: stable@vger.kernel.org
Signed-off-by: Breno Leitao <leitao@debian.org>
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
lib/bootconfig.c | 23 ++++++++++++++++-------
1 file changed, 16 insertions(+), 7 deletions(-)
--- a/lib/bootconfig.c
+++ b/lib/bootconfig.c
@@ -424,10 +424,18 @@ static char xbc_namebuf[XBC_KEYLEN_MAX]
int __init xbc_snprint_cmdline(char *buf, size_t size, struct xbc_node *root)
{
struct xbc_node *knode, *vnode;
- char *end = buf + size;
const char *val, *q;
+ size_t len = 0;
int ret;
+ /*
+ * Track the running written length rather than advancing @buf, so we
+ * never form "buf + size" or "buf += ret" while @buf is NULL (the
+ * size-probe call passes buf=NULL, size=0). NULL pointer arithmetic
+ * is undefined behavior and trips host UBSan / FORTIFY_SOURCE when
+ * this renderer runs at kernel build time. snprintf(NULL, 0, ...)
+ * itself is well defined and returns the would-be length.
+ */
xbc_node_for_each_key_value(root, knode, val) {
ret = xbc_node_compose_key_after(root, knode,
xbc_namebuf, XBC_KEYLEN_MAX);
@@ -436,10 +444,11 @@ int __init xbc_snprint_cmdline(char *buf
vnode = xbc_node_get_child(knode);
if (!vnode) {
- ret = snprintf(buf, rest(buf, end), "%s ", xbc_namebuf);
+ ret = snprintf(buf ? buf + len : NULL, rest(len, size),
+ "%s ", xbc_namebuf);
if (ret < 0)
return ret;
- buf += ret;
+ len += ret;
continue;
}
xbc_array_for_each_value(vnode, val) {
@@ -449,15 +458,15 @@ int __init xbc_snprint_cmdline(char *buf
* whitespace.
*/
q = strpbrk(val, " \t\r\n") ? "\"" : "";
- ret = snprintf(buf, rest(buf, end), "%s=%s%s%s ",
- xbc_namebuf, q, val, q);
+ ret = snprintf(buf ? buf + len : NULL, rest(len, size),
+ "%s=%s%s%s ", xbc_namebuf, q, val, q);
if (ret < 0)
return ret;
- buf += ret;
+ len += ret;
}
}
- return buf - (end - size);
+ return len;
}
#undef rest
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 564/602] ipmi: fix refcount leak in i_ipmi_request()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (562 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 563/602] bootconfig: fix NULL-pointer arithmetic in xbc_snprint_cmdline() Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 565/602] net/mlx5: HWS, Rearrange to prevent forward declaration Greg Kroah-Hartman
` (41 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Wentao Liang, Corey Minyard,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wentao Liang <vulab@iscas.ac.cn>
[ Upstream commit a3f3859cecacb64f18fd446271ece9a3b3f2d4de ]
When a caller provides a `supplied_recv` message to i_ipmi_request(),
the function increments the user's `nr_msgs` reference count. If an
error occurs later, the out_err cleanup path only frees the recv_msg
if the function allocated it itself (i.e., !supplied_recv). In the
supplied_recv case the cleanup is skipped, leaving the reference count
elevated. The caller ipmi_request_supply_msgs() does not release the
supplied_recv on error, so the reference is permanently leaked.
Fix this by explicitly reverting the reference count operations when a
supplied recv_msg with a valid user pointer is present in the error
path: decrement nr_msgs and drop the user's kref.
Cc: stable@vger.kernel.org
Fixes: b52da4054ee0 ("ipmi: Rework user message limit handling")
Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
Message-ID: <20260603120634.3758747-1-vulab@iscas.ac.cn>
Signed-off-by: Corey Minyard <corey@minyard.net>
[ changed `free_ipmi_user` to `free_user` in the two added `kref_put()` calls ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/char/ipmi/ipmi_msghandler.c | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -2331,6 +2331,10 @@ static int i_ipmi_request(struct ipmi_us
if (smi_msg == NULL) {
if (!supplied_recv)
ipmi_free_recv_msg(recv_msg);
+ else if (recv_msg->user) {
+ atomic_dec(&recv_msg->user->nr_msgs);
+ kref_put(&recv_msg->user->refcount, free_user);
+ }
return -ENOMEM;
}
}
@@ -2373,6 +2377,10 @@ out_err:
ipmi_free_smi_msg(smi_msg);
if (!supplied_recv)
ipmi_free_recv_msg(recv_msg);
+ else if (recv_msg->user) {
+ atomic_dec(&recv_msg->user->nr_msgs);
+ kref_put(&recv_msg->user->refcount, free_user);
+ }
} else {
dev_dbg(intf->si_dev, "Send: %*ph\n",
smi_msg->data_size, smi_msg->data);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 565/602] net/mlx5: HWS, Rearrange to prevent forward declaration
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (563 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 564/602] ipmi: fix refcount leak in i_ipmi_request() Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 566/602] net/mlx5: HWS, fix matcher leak on resize target setup failure Greg Kroah-Hartman
` (40 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yevgeny Kliteynik, Mark Bloch,
Simon Horman, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yevgeny Kliteynik <kliteyn@nvidia.com>
[ Upstream commit 29063103f864fb63f7f7c436e670c5804df1b55b ]
As a preparation for the following patch that will add support
for shrinking empty matchers, rearrange the code to prevent
forward declaration of functions.
Signed-off-by: Yevgeny Kliteynik <kliteyn@nvidia.com>
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20250703185431.445571-9-mbloch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: bb09d0e64eca ("net/mlx5: HWS, fix matcher leak on resize target setup failure")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_bwc.c | 354 +++++-----
1 file changed, 177 insertions(+), 177 deletions(-)
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_bwc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_bwc.c
@@ -63,6 +63,183 @@ static void hws_bwc_matcher_init_attr(st
attr->max_num_of_at_attach = MLX5HWS_BWC_MATCHER_ATTACH_AT_NUM;
}
+static int hws_bwc_queue_poll(struct mlx5hws_context *ctx,
+ u16 queue_id,
+ u32 *pending_rules,
+ bool drain)
+{
+ struct mlx5hws_flow_op_result comp[MLX5HWS_BWC_MATCHER_REHASH_BURST_TH];
+ u16 burst_th = hws_bwc_get_burst_th(ctx, queue_id);
+ bool got_comp = *pending_rules >= burst_th;
+ bool queue_full;
+ int err = 0;
+ int ret;
+ int i;
+
+ /* Check if there are any completions at all */
+ if (!got_comp && !drain)
+ return 0;
+
+ queue_full = mlx5hws_send_engine_full(&ctx->send_queue[queue_id]);
+ while (queue_full || ((got_comp || drain) && *pending_rules)) {
+ ret = mlx5hws_send_queue_poll(ctx, queue_id, comp, burst_th);
+ if (unlikely(ret < 0)) {
+ mlx5hws_err(ctx, "BWC poll error: polling queue %d returned %d\n",
+ queue_id, ret);
+ return -EINVAL;
+ }
+
+ if (ret) {
+ (*pending_rules) -= ret;
+ for (i = 0; i < ret; i++) {
+ if (unlikely(comp[i].status != MLX5HWS_FLOW_OP_SUCCESS)) {
+ mlx5hws_err(ctx,
+ "BWC poll error: polling queue %d returned completion with error\n",
+ queue_id);
+ err = -EINVAL;
+ }
+ }
+ queue_full = false;
+ }
+
+ got_comp = !!ret;
+ }
+
+ return err;
+}
+
+static int hws_bwc_matcher_move_all_simple(struct mlx5hws_bwc_matcher *bwc_matcher)
+{
+ struct mlx5hws_context *ctx = bwc_matcher->matcher->tbl->ctx;
+ u16 bwc_queues = mlx5hws_bwc_queues(ctx);
+ struct mlx5hws_bwc_rule **bwc_rules;
+ struct mlx5hws_rule_attr rule_attr;
+ u32 *pending_rules;
+ int i, j, ret = 0;
+ bool all_done;
+ u16 burst_th;
+
+ mlx5hws_bwc_rule_fill_attr(bwc_matcher, 0, 0, &rule_attr);
+
+ pending_rules = kcalloc(bwc_queues, sizeof(*pending_rules), GFP_KERNEL);
+ if (!pending_rules)
+ return -ENOMEM;
+
+ bwc_rules = kcalloc(bwc_queues, sizeof(*bwc_rules), GFP_KERNEL);
+ if (!bwc_rules) {
+ ret = -ENOMEM;
+ goto free_pending_rules;
+ }
+
+ for (i = 0; i < bwc_queues; i++) {
+ if (list_empty(&bwc_matcher->rules[i]))
+ bwc_rules[i] = NULL;
+ else
+ bwc_rules[i] = list_first_entry(&bwc_matcher->rules[i],
+ struct mlx5hws_bwc_rule,
+ list_node);
+ }
+
+ do {
+ all_done = true;
+
+ for (i = 0; i < bwc_queues; i++) {
+ rule_attr.queue_id = mlx5hws_bwc_get_queue_id(ctx, i);
+ burst_th = hws_bwc_get_burst_th(ctx, rule_attr.queue_id);
+
+ for (j = 0; j < burst_th && bwc_rules[i]; j++) {
+ rule_attr.burst = !!((j + 1) % burst_th);
+ ret = mlx5hws_matcher_resize_rule_move(bwc_matcher->matcher,
+ bwc_rules[i]->rule,
+ &rule_attr);
+ if (unlikely(ret)) {
+ mlx5hws_err(ctx,
+ "Moving BWC rule failed during rehash (%d)\n",
+ ret);
+ goto free_bwc_rules;
+ }
+
+ all_done = false;
+ pending_rules[i]++;
+ bwc_rules[i] = list_is_last(&bwc_rules[i]->list_node,
+ &bwc_matcher->rules[i]) ?
+ NULL : list_next_entry(bwc_rules[i], list_node);
+
+ ret = hws_bwc_queue_poll(ctx, rule_attr.queue_id,
+ &pending_rules[i], false);
+ if (unlikely(ret))
+ goto free_bwc_rules;
+ }
+ }
+ } while (!all_done);
+
+ /* drain all the bwc queues */
+ for (i = 0; i < bwc_queues; i++) {
+ if (pending_rules[i]) {
+ u16 queue_id = mlx5hws_bwc_get_queue_id(ctx, i);
+
+ mlx5hws_send_engine_flush_queue(&ctx->send_queue[queue_id]);
+ ret = hws_bwc_queue_poll(ctx, queue_id,
+ &pending_rules[i], true);
+ if (unlikely(ret))
+ goto free_bwc_rules;
+ }
+ }
+
+free_bwc_rules:
+ kfree(bwc_rules);
+free_pending_rules:
+ kfree(pending_rules);
+
+ return ret;
+}
+
+static int hws_bwc_matcher_move_all(struct mlx5hws_bwc_matcher *bwc_matcher)
+{
+ return hws_bwc_matcher_move_all_simple(bwc_matcher);
+}
+
+static int hws_bwc_matcher_move(struct mlx5hws_bwc_matcher *bwc_matcher)
+{
+ struct mlx5hws_context *ctx = bwc_matcher->matcher->tbl->ctx;
+ struct mlx5hws_matcher_attr matcher_attr = {0};
+ struct mlx5hws_matcher *old_matcher;
+ struct mlx5hws_matcher *new_matcher;
+ int ret;
+
+ hws_bwc_matcher_init_attr(&matcher_attr,
+ bwc_matcher->priority,
+ bwc_matcher->size_log);
+
+ old_matcher = bwc_matcher->matcher;
+ new_matcher = mlx5hws_matcher_create(old_matcher->tbl,
+ &bwc_matcher->mt, 1,
+ bwc_matcher->at,
+ bwc_matcher->num_of_at,
+ &matcher_attr);
+ if (!new_matcher) {
+ mlx5hws_err(ctx, "Rehash error: matcher creation failed\n");
+ return -ENOMEM;
+ }
+
+ ret = mlx5hws_matcher_resize_set_target(old_matcher, new_matcher);
+ if (ret) {
+ mlx5hws_err(ctx, "Rehash error: failed setting resize target\n");
+ return ret;
+ }
+
+ ret = hws_bwc_matcher_move_all(bwc_matcher);
+ if (ret) {
+ mlx5hws_err(ctx, "Rehash error: moving rules failed\n");
+ return -ENOMEM;
+ }
+
+ bwc_matcher->matcher = new_matcher;
+ mlx5hws_matcher_destroy(old_matcher);
+
+ return 0;
+}
+
int mlx5hws_bwc_matcher_create_simple(struct mlx5hws_bwc_matcher *bwc_matcher,
struct mlx5hws_table *table,
u32 priority,
@@ -210,51 +387,6 @@ int mlx5hws_bwc_matcher_destroy(struct m
return 0;
}
-static int hws_bwc_queue_poll(struct mlx5hws_context *ctx,
- u16 queue_id,
- u32 *pending_rules,
- bool drain)
-{
- struct mlx5hws_flow_op_result comp[MLX5HWS_BWC_MATCHER_REHASH_BURST_TH];
- u16 burst_th = hws_bwc_get_burst_th(ctx, queue_id);
- bool got_comp = *pending_rules >= burst_th;
- bool queue_full;
- int err = 0;
- int ret;
- int i;
-
- /* Check if there are any completions at all */
- if (!got_comp && !drain)
- return 0;
-
- queue_full = mlx5hws_send_engine_full(&ctx->send_queue[queue_id]);
- while (queue_full || ((got_comp || drain) && *pending_rules)) {
- ret = mlx5hws_send_queue_poll(ctx, queue_id, comp, burst_th);
- if (unlikely(ret < 0)) {
- mlx5hws_err(ctx, "BWC poll error: polling queue %d returned %d\n",
- queue_id, ret);
- return -EINVAL;
- }
-
- if (ret) {
- (*pending_rules) -= ret;
- for (i = 0; i < ret; i++) {
- if (unlikely(comp[i].status != MLX5HWS_FLOW_OP_SUCCESS)) {
- mlx5hws_err(ctx,
- "BWC poll error: polling queue %d returned completion with error\n",
- queue_id);
- err = -EINVAL;
- }
- }
- queue_full = false;
- }
-
- got_comp = !!ret;
- }
-
- return err;
-}
-
void
mlx5hws_bwc_rule_fill_attr(struct mlx5hws_bwc_matcher *bwc_matcher,
u16 bwc_queue_idx,
@@ -556,138 +688,6 @@ hws_bwc_matcher_find_at(struct mlx5hws_b
return -1;
}
-static int hws_bwc_matcher_move_all_simple(struct mlx5hws_bwc_matcher *bwc_matcher)
-{
- struct mlx5hws_context *ctx = bwc_matcher->matcher->tbl->ctx;
- u16 bwc_queues = mlx5hws_bwc_queues(ctx);
- struct mlx5hws_bwc_rule **bwc_rules;
- struct mlx5hws_rule_attr rule_attr;
- u32 *pending_rules;
- int i, j, ret = 0;
- bool all_done;
- u16 burst_th;
-
- mlx5hws_bwc_rule_fill_attr(bwc_matcher, 0, 0, &rule_attr);
-
- pending_rules = kcalloc(bwc_queues, sizeof(*pending_rules), GFP_KERNEL);
- if (!pending_rules)
- return -ENOMEM;
-
- bwc_rules = kcalloc(bwc_queues, sizeof(*bwc_rules), GFP_KERNEL);
- if (!bwc_rules) {
- ret = -ENOMEM;
- goto free_pending_rules;
- }
-
- for (i = 0; i < bwc_queues; i++) {
- if (list_empty(&bwc_matcher->rules[i]))
- bwc_rules[i] = NULL;
- else
- bwc_rules[i] = list_first_entry(&bwc_matcher->rules[i],
- struct mlx5hws_bwc_rule,
- list_node);
- }
-
- do {
- all_done = true;
-
- for (i = 0; i < bwc_queues; i++) {
- rule_attr.queue_id = mlx5hws_bwc_get_queue_id(ctx, i);
- burst_th = hws_bwc_get_burst_th(ctx, rule_attr.queue_id);
-
- for (j = 0; j < burst_th && bwc_rules[i]; j++) {
- rule_attr.burst = !!((j + 1) % burst_th);
- ret = mlx5hws_matcher_resize_rule_move(bwc_matcher->matcher,
- bwc_rules[i]->rule,
- &rule_attr);
- if (unlikely(ret)) {
- mlx5hws_err(ctx,
- "Moving BWC rule failed during rehash (%d)\n",
- ret);
- goto free_bwc_rules;
- }
-
- all_done = false;
- pending_rules[i]++;
- bwc_rules[i] = list_is_last(&bwc_rules[i]->list_node,
- &bwc_matcher->rules[i]) ?
- NULL : list_next_entry(bwc_rules[i], list_node);
-
- ret = hws_bwc_queue_poll(ctx, rule_attr.queue_id,
- &pending_rules[i], false);
- if (unlikely(ret))
- goto free_bwc_rules;
- }
- }
- } while (!all_done);
-
- /* drain all the bwc queues */
- for (i = 0; i < bwc_queues; i++) {
- if (pending_rules[i]) {
- u16 queue_id = mlx5hws_bwc_get_queue_id(ctx, i);
-
- mlx5hws_send_engine_flush_queue(&ctx->send_queue[queue_id]);
- ret = hws_bwc_queue_poll(ctx, queue_id,
- &pending_rules[i], true);
- if (unlikely(ret))
- goto free_bwc_rules;
- }
- }
-
-free_bwc_rules:
- kfree(bwc_rules);
-free_pending_rules:
- kfree(pending_rules);
-
- return ret;
-}
-
-static int hws_bwc_matcher_move_all(struct mlx5hws_bwc_matcher *bwc_matcher)
-{
- return hws_bwc_matcher_move_all_simple(bwc_matcher);
-}
-
-static int hws_bwc_matcher_move(struct mlx5hws_bwc_matcher *bwc_matcher)
-{
- struct mlx5hws_context *ctx = bwc_matcher->matcher->tbl->ctx;
- struct mlx5hws_matcher_attr matcher_attr = {0};
- struct mlx5hws_matcher *old_matcher;
- struct mlx5hws_matcher *new_matcher;
- int ret;
-
- hws_bwc_matcher_init_attr(&matcher_attr,
- bwc_matcher->priority,
- bwc_matcher->size_log);
-
- old_matcher = bwc_matcher->matcher;
- new_matcher = mlx5hws_matcher_create(old_matcher->tbl,
- &bwc_matcher->mt, 1,
- bwc_matcher->at,
- bwc_matcher->num_of_at,
- &matcher_attr);
- if (!new_matcher) {
- mlx5hws_err(ctx, "Rehash error: matcher creation failed\n");
- return -ENOMEM;
- }
-
- ret = mlx5hws_matcher_resize_set_target(old_matcher, new_matcher);
- if (ret) {
- mlx5hws_err(ctx, "Rehash error: failed setting resize target\n");
- return ret;
- }
-
- ret = hws_bwc_matcher_move_all(bwc_matcher);
- if (ret) {
- mlx5hws_err(ctx, "Rehash error: moving rules failed\n");
- return -ENOMEM;
- }
-
- bwc_matcher->matcher = new_matcher;
- mlx5hws_matcher_destroy(old_matcher);
-
- return 0;
-}
-
static int
hws_bwc_matcher_rehash_size(struct mlx5hws_bwc_matcher *bwc_matcher)
{
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 566/602] net/mlx5: HWS, fix matcher leak on resize target setup failure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (564 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 565/602] net/mlx5: HWS, Rearrange to prevent forward declaration Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 567/602] octeontx2-pf: fix SQB pointer leak on init failure Greg Kroah-Hartman
` (39 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Dawei Feng, Yevgeny Kliteynik,
Tariq Toukan, Paolo Abeni, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dawei Feng <dawei.feng@seu.edu.cn>
[ Upstream commit bb09d0e64ecaa0aa0f7d1133a1696ed74dead295 ]
hws_bwc_matcher_move() allocates a replacement matcher before setting it
as the resize target. If mlx5hws_matcher_resize_set_target() fails, the
replacement matcher is not attached anywhere and is leaked.
Fix the leak by destroying the replacement matcher before returning from
the resize-target failure path.
The bug was first flagged by an experimental analysis tool we are
developing for kernel memory-management bugs while analyzing
v6.13-rc1. The tool is still under development and is not yet publicly
available. Manual inspection confirms that the bug is still
present in v7.1.1.
An x86_64 allyesconfig build showed no new warnings. As we do not have a
mlx5 HWS-capable device to test with, no runtime testing was able to be
performed.
Fixes: 2111bb970c78 ("net/mlx5: HWS, added backward-compatible API handling")
Cc: stable@vger.kernel.org
Signed-off-by: Dawei Feng <dawei.feng@seu.edu.cn>
Reviewed-by: Yevgeny Kliteynik <kliteyn@nvidia.com>
Acked-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260629064049.3852759-1-dawei.feng@seu.edu.cn
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_bwc.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_bwc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws_bwc.c
@@ -225,6 +225,7 @@ static int hws_bwc_matcher_move(struct m
ret = mlx5hws_matcher_resize_set_target(old_matcher, new_matcher);
if (ret) {
mlx5hws_err(ctx, "Rehash error: failed setting resize target\n");
+ mlx5hws_matcher_destroy(new_matcher);
return ret;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 567/602] octeontx2-pf: fix SQB pointer leak on init failure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (565 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 566/602] net/mlx5: HWS, fix matcher leak on resize target setup failure Greg Kroah-Hartman
@ 2026-07-30 14:15 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 568/602] ata: libata-core: Reject an invalid concurrent positioning ranges count Greg Kroah-Hartman
` (38 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:15 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Ratheesh Kannoth, Dawei Feng,
Paolo Abeni, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dawei Feng <dawei.feng@seu.edu.cn>
[ Upstream commit 62e7df6d042aeebd5efb581074e28865c04477be ]
otx2_init_hw_resources() initializes SQ aura and pool resources before
several later setup steps. On failure, err_free_sq_ptrs only frees SQB
pages, leaving the per-SQ sqb_ptrs arrays behind.
Use otx2_free_sq_res() for the SQ unwind path and let it free sqb_ptrs
even when sq->sqe has not been allocated yet.
The bug was first flagged by an experimental analysis tool we are
developing for kernel memory-management bugs while analyzing
v6.13-rc1. The tool is still under development and is not yet publicly
available. Manual inspection confirms that the bug is still
present in v7.1.1.
An x86_64 allyesconfig build showed no new warnings. As we do not have an
OcteonTX2 PF device and the corresponding AF mailbox setup to test with,
no runtime testing was able to be performed.
Fixes: caa2da34fd25 ("octeontx2-pf: Initialize and config queues")
Cc: stable@vger.kernel.org
Reviewed-by: Ratheesh Kannoth <rkannoth@marvell.com>
Signed-off-by: Dawei Feng <dawei.feng@seu.edu.cn>
Link: https://patch.msgid.link/20260630071625.349996-1-dawei.feng@seu.edu.cn
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -1438,13 +1438,13 @@ static void otx2_free_sq_res(struct otx2
otx2_sq_free_sqbs(pf);
for (qidx = 0; qidx < otx2_get_total_tx_queues(pf); qidx++) {
sq = &qset->sq[qidx];
- /* Skip freeing Qos queues if they are not initialized */
- if (!sq->sqe)
- continue;
- qmem_free(pf->dev, sq->sqe);
- qmem_free(pf->dev, sq->tso_hdrs);
- qmem_free(pf->dev, sq->timestamps);
- kfree(sq->sg);
+ /* sq->sqe is not initialized for unused QoS queues */
+ if (sq->sqe) {
+ qmem_free(pf->dev, sq->sqe);
+ qmem_free(pf->dev, sq->tso_hdrs);
+ qmem_free(pf->dev, sq->timestamps);
+ kfree(sq->sg);
+ }
kfree(sq->sqb_ptrs);
}
}
@@ -1570,13 +1570,12 @@ static int otx2_init_hw_resources(struct
return err;
err_free_nix_queues:
- otx2_free_sq_res(pf);
otx2_free_cq_res(pf);
otx2_ctx_disable(mbox, NIX_AQ_CTYPE_RQ, false);
err_free_txsch:
otx2_txschq_stop(pf);
err_free_sq_ptrs:
- otx2_sq_free_sqbs(pf);
+ otx2_free_sq_res(pf);
err_free_rq_ptrs:
otx2_free_aura_ptr(pf, AURA_NIX_RQ);
otx2_ctx_disable(mbox, NPA_AQ_CTYPE_POOL, true);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 568/602] ata: libata-core: Reject an invalid concurrent positioning ranges count
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (566 preceding siblings ...)
2026-07-30 14:15 ` [PATCH 6.12 567/602] octeontx2-pf: fix SQB pointer leak on init failure Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 569/602] fs/resctrl: Fix double-add of pseudo-locked regions RMID to free list Greg Kroah-Hartman
` (37 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Damien Le Moal, Bryam Vargas,
Niklas Cassel, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <hexlabsecurity@proton.me>
[ Upstream commit 533a0b940f901c15e5cbbd4b5d66e871c209e8ce ]
ata_dev_config_cpr() takes the number of range descriptors from buf[0]
of the concurrent positioning ranges log (up to 255), which the device
reports independently of the log size in the GPL directory. The count is
then walked at a fixed 32-byte stride in two places with no bound: the
log read here, and the INQUIRY VPD page B9h emitter, which writes one
descriptor per range into the fixed 2048-byte ata_scsi_rbuf. A device
reporting a count larger than its own log overflows the read buffer (up
to 7704 bytes past a 512-byte slab), and a count above 62 overflows the
response buffer on the emit side.
Bound the count once, on probe, against both the log the device returned
and the number of descriptors the VPD B9h response buffer can hold
(ATA_DEV_MAX_CPR, derived from the rbuf size). Reject an out-of-range
count with a warning; this keeps the emitter in bounds with no separate
change there.
Suggested-by: Damien Le Moal <dlemoal@kernel.org>
Fixes: fe22e1c2f705 ("libata: support concurrent positioning ranges log")
Fixes: c745dfc541e7 ("libata: fix reading concurrent positioning ranges log")
Cc: stable@vger.kernel.org
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
Reviewed-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
[ adapted `kzalloc_flex()` allocation to `kzalloc(struct_size(...), GFP_KERNEL)` and adjusted context offsets. ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/ata/libata-core.c | 18 ++++++++++++++++++
drivers/ata/libata-scsi.c | 2 --
drivers/ata/libata.h | 9 +++++++++
3 files changed, 27 insertions(+), 2 deletions(-)
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2804,6 +2804,24 @@ static void ata_dev_config_cpr(struct at
if (!nr_cpr)
goto out;
+ /*
+ * The device reports the number of CPR descriptors independently of the
+ * log size, and that count is also used to emit VPD page B9h into the
+ * fixed-size rbuf. Reject a count larger than what that buffer can hold
+ * (ATA_DEV_MAX_CPR) or larger than the log the device actually returned.
+ */
+ if (nr_cpr > ATA_DEV_MAX_CPR) {
+ ata_dev_warn(dev,
+ "Too many concurrent positioning ranges\n");
+ goto out;
+ }
+
+ if (buf_len < 64 + (size_t)nr_cpr * 32) {
+ ata_dev_warn(dev,
+ "Invalid number of concurrent positioning ranges\n");
+ goto out;
+ }
+
cpr_log = kzalloc(struct_size(cpr_log, cpr, nr_cpr), GFP_KERNEL);
if (!cpr_log)
goto out;
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -37,8 +37,6 @@
#include "libata.h"
#include "libata-transport.h"
-#define ATA_SCSI_RBUF_SIZE 2048
-
static DEFINE_SPINLOCK(ata_scsi_rbuf_lock);
static u8 ata_scsi_rbuf[ATA_SCSI_RBUF_SIZE];
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -145,6 +145,15 @@ static inline void ata_acpi_bind_dev(str
#endif
/* libata-scsi.c */
+#define ATA_SCSI_RBUF_SIZE 2048
+
+/*
+ * Maximum number of concurrent positioning ranges (CPR) supported. The ACS
+ * specifications allow up to 255, but we limit this to the number of CPR
+ * descriptors that fit in the rbuf buffer used to emit VPD page B9h.
+ */
+#define ATA_DEV_MAX_CPR min(255, ((ATA_SCSI_RBUF_SIZE - 64) / 32))
+
extern struct ata_device *ata_scsi_find_dev(struct ata_port *ap,
const struct scsi_device *scsidev);
extern int ata_scsi_add_hosts(struct ata_host *host,
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 569/602] fs/resctrl: Fix double-add of pseudo-locked regions RMID to free list
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (567 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 568/602] ata: libata-core: Reject an invalid concurrent positioning ranges count Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 570/602] net: macb: drop in-flight Tx SKBs on close Greg Kroah-Hartman
` (36 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Reinette Chatre,
Borislav Petkov (AMD), stable, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Reinette Chatre <reinette.chatre@intel.com>
[ Upstream commit b9f089723aee892efc77c349ae47a6b452b293c4 ]
A pseudo-locked group's RMID is freed when it is created. On unmount
rmdir_all_sub() unconditionally frees all RMID of all groups, resulting
in a double-free of the pseudo-locked group's RMID. The consequence of this
is that the original free results in the pseudo-locked group's RMID being
added to the rmid_free_lru linked list and the second free then attempts
to add the same RMID entry to the rmid_free_lru again.
Do not double-free a pseudo-locked group's RMID.
Fixes: e0bdfe8e36f3 ("x86/intel_rdt: Support creation/removal of pseudo-locked region")
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Cc: <stable@kernel.org>
Link: https://patch.msgid.link/551432dd7e624a862b8e58314c38aaba0afff3e9.1783377598.git.reinette.chatre@intel.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/x86/kernel/cpu/resctrl/rdtgroup.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
--- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c
+++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
@@ -2922,10 +2922,6 @@ static void rmdir_all_sub(void)
if (rdtgrp == &rdtgroup_default)
continue;
- if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP ||
- rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED)
- rdtgroup_pseudo_lock_remove(rdtgrp);
-
/*
* Give any CPUs back to the default group. We cannot copy
* cpu_online_mask because a CPU might have executed the
@@ -2934,7 +2930,13 @@ static void rmdir_all_sub(void)
cpumask_or(&rdtgroup_default.cpu_mask,
&rdtgroup_default.cpu_mask, &rdtgrp->cpu_mask);
- free_rmid(rdtgrp->closid, rdtgrp->mon.rmid);
+ if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP ||
+ rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED) {
+ rdtgroup_pseudo_lock_remove(rdtgrp);
+ } else {
+ /* Pseudo-locked group's RMID is freed during setup. */
+ free_rmid(rdtgrp->closid, rdtgrp->mon.rmid);
+ }
kernfs_remove(rdtgrp->kn);
list_del(&rdtgrp->rdtgroup_list);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 570/602] net: macb: drop in-flight Tx SKBs on close
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (568 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 569/602] fs/resctrl: Fix double-add of pseudo-locked regions RMID to free list Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 571/602] net: ipa: fix SMEM state handle leaks in SMP2P init Greg Kroah-Hartman
` (35 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Nicolai Buchwitz, Théo Lebrun,
Paolo Abeni, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Théo Lebrun <theo.lebrun@bootlin.com>
[ Upstream commit 27f575836cfebbf872dec020428742b10650a955 ]
The MACB driver has since forever leaked the outgoing SKBs that
have not yet been marked as completed. They live in queue->tx_skb
which gets freed without remorse nor checking.
macb_free_consistent() gets called in a few codepaths, but only close will
trigger the added expressions. In macb_open() and macb_alloc_consistent()
failure cases, queues' tx_skb just got allocated and are empty.
Fixes: 89e5785fc8a6 ("[PATCH] Atmel MACB ethernet driver")
Cc: stable@vger.kernel.org
Reviewed-by: Nicolai Buchwitz <nb@tipi-net.de>
Signed-off-by: Théo Lebrun <theo.lebrun@bootlin.com>
Link: https://patch.msgid.link/20260702-macb-drop-tx-v4-1-1c833eebdbc8@bootlin.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
[ adjusted context to free each queue's Tx/Rx rings individually since 6.12 lacks the single-dma_alloc_coherent refactor ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/cadence/macb_main.c | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -2582,8 +2582,26 @@ static void macb_free_consistent(struct
bp->macbgem_ops.mog_free_rx_buffers(bp);
for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
- kfree(queue->tx_skb);
- queue->tx_skb = NULL;
+ if (queue->tx_skb) {
+ unsigned int dropped = 0, tail;
+
+ for (tail = queue->tx_tail; tail != queue->tx_head;
+ tail++) {
+ if (macb_tx_skb(queue, tail)->skb)
+ dropped++;
+ macb_tx_unmap(bp, macb_tx_skb(queue, tail), 0);
+ }
+
+ queue->stats.tx_dropped += dropped;
+ bp->dev->stats.tx_dropped += dropped;
+
+ kfree(queue->tx_skb);
+ queue->tx_skb = NULL;
+ }
+
+ queue->tx_head = 0;
+ queue->tx_tail = 0;
+
if (queue->tx_ring) {
size = TX_RING_BYTES(bp) + bp->tx_bd_rd_prefetch;
dma_free_coherent(&bp->pdev->dev, size,
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 571/602] net: ipa: fix SMEM state handle leaks in SMP2P init
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (569 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 570/602] net: macb: drop in-flight Tx SKBs on close Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 572/602] Bluetooth: Add PA_LINK to distinguish BIG sync and PA sync connections Greg Kroah-Hartman
` (34 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Haoxiang Li, Larysa Zaremba,
Alex Elder, Jakub Kicinski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haoxiang Li <haoxiang_li2024@163.com>
[ Upstream commit 96ca1e658ae459276292bd6d971ab5d8c7e0379a ]
ipa_smp2p_init() acquires two Qualcomm SMEM state handles with
qcom_smem_state_get(). However, neither the init error paths
nor ipa_smp2p_exit() release them.
Release both handles with qcom_smem_state_put() in the init
error paths and in ipa_smp2p_exit().
Fixes: 530f9216a953 ("soc: qcom: ipa: AP/modem communications")
Cc: stable@vger.kernel.org
Signed-off-by: Haoxiang Li <haoxiang_li2024@163.com>
Reviewed-by: Larysa Zaremba <larysa.zaremba@intel.com>
Reviewed-by: Alex Elder <elder@riscstar.com>
Link: https://patch.msgid.link/20260624065955.2822765-1-haoxiang_li2024@163.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
[ kzalloc_obj() context line kept as kzalloc(sizeof(*smp2p), GFP_KERNEL) since ipa_smp2p.c was not yet converted in this tree ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ipa/ipa_smp2p.c | 30 ++++++++++++++++++++++--------
1 file changed, 22 insertions(+), 8 deletions(-)
--- a/drivers/net/ipa/ipa_smp2p.c
+++ b/drivers/net/ipa/ipa_smp2p.c
@@ -234,19 +234,27 @@ ipa_smp2p_init(struct ipa *ipa, struct p
&valid_bit);
if (IS_ERR(valid_state))
return PTR_ERR(valid_state);
- if (valid_bit >= 32) /* BITS_PER_U32 */
- return -EINVAL;
+ if (valid_bit >= 32) { /* BITS_PER_U32 */
+ ret = -EINVAL;
+ goto err_valid_state_put;
+ }
enabled_state = qcom_smem_state_get(dev, "ipa-clock-enabled",
&enabled_bit);
- if (IS_ERR(enabled_state))
- return PTR_ERR(enabled_state);
- if (enabled_bit >= 32) /* BITS_PER_U32 */
- return -EINVAL;
+ if (IS_ERR(enabled_state)) {
+ ret = PTR_ERR(enabled_state);
+ goto err_valid_state_put;
+ }
+ if (enabled_bit >= 32) { /* BITS_PER_U32 */
+ ret = -EINVAL;
+ goto err_enabled_state_put;
+ }
smp2p = kzalloc(sizeof(*smp2p), GFP_KERNEL);
- if (!smp2p)
- return -ENOMEM;
+ if (!smp2p) {
+ ret = -ENOMEM;
+ goto err_enabled_state_put;
+ }
smp2p->ipa = ipa;
@@ -291,6 +299,10 @@ err_null_smp2p:
ipa->smp2p = NULL;
mutex_destroy(&smp2p->mutex);
kfree(smp2p);
+err_enabled_state_put:
+ qcom_smem_state_put(enabled_state);
+err_valid_state_put:
+ qcom_smem_state_put(valid_state);
return ret;
}
@@ -307,6 +319,8 @@ void ipa_smp2p_exit(struct ipa *ipa)
ipa_smp2p_power_release(ipa);
ipa->smp2p = NULL;
mutex_destroy(&smp2p->mutex);
+ qcom_smem_state_put(smp2p->enabled_state);
+ qcom_smem_state_put(smp2p->valid_state);
kfree(smp2p);
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 572/602] Bluetooth: Add PA_LINK to distinguish BIG sync and PA sync connections
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (570 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 571/602] net: ipa: fix SMEM state handle leaks in SMP2P init Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 573/602] Bluetooth: hci_core: Fix not accounting for BIS/CIS/PA links separately Greg Kroah-Hartman
` (33 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yang Li, Luiz Augusto von Dentz,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yang Li <yang.li@amlogic.com>
[ Upstream commit a7bcffc673de219af2698fbb90627016233de67b ]
Currently, BIS_LINK is used for both BIG sync and PA sync connections,
which makes it impossible to distinguish them when searching for a PA
sync connection.
Adding PA_LINK will make the distinction clearer and simplify future
extensions for PA-related features.
Signed-off-by: Yang Li <yang.li@amlogic.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Stable-dep-of: 9d4b01a0bf8d ("Bluetooth: hci_core: Fix not accounting for BIS/CIS/PA links separately")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/net/bluetooth/hci.h | 1 +
include/net/bluetooth/hci_core.h | 10 +++++++---
net/bluetooth/hci_conn.c | 13 ++++++++-----
net/bluetooth/hci_core.c | 27 +++++++++++++++------------
net/bluetooth/hci_event.c | 7 ++++---
net/bluetooth/hci_sync.c | 10 +++++-----
net/bluetooth/iso.c | 6 ++++--
net/bluetooth/mgmt.c | 1 +
8 files changed, 45 insertions(+), 30 deletions(-)
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -560,6 +560,7 @@ enum {
#define LE_LINK 0x80
#define CIS_LINK 0x82
#define BIS_LINK 0x83
+#define PA_LINK 0x84
#define INVALID_LINK 0xff
/* LMP features */
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1001,6 +1001,7 @@ static inline void hci_conn_hash_add(str
break;
case CIS_LINK:
case BIS_LINK:
+ case PA_LINK:
h->iso_num++;
break;
}
@@ -1028,6 +1029,7 @@ static inline void hci_conn_hash_del(str
break;
case CIS_LINK:
case BIS_LINK:
+ case PA_LINK:
h->iso_num--;
break;
}
@@ -1046,6 +1048,7 @@ static inline unsigned int hci_conn_num(
return h->sco_num;
case CIS_LINK:
case BIS_LINK:
+ case PA_LINK:
return h->iso_num;
default:
return 0;
@@ -1128,7 +1131,7 @@ hci_conn_hash_lookup_create_pa_sync(stru
rcu_read_lock();
list_for_each_entry_rcu(c, &h->list, list) {
- if (c->type != BIS_LINK)
+ if (c->type != PA_LINK)
continue;
if (!test_bit(HCI_CONN_CREATE_PA_SYNC, &c->flags))
@@ -1344,7 +1347,7 @@ hci_conn_hash_lookup_big_sync_pend(struc
rcu_read_lock();
list_for_each_entry_rcu(c, &h->list, list) {
- if (c->type != BIS_LINK)
+ if (c->type != PA_LINK)
continue;
if (handle == c->iso_qos.bcast.big && num_bis == c->num_bis) {
@@ -1413,7 +1416,7 @@ hci_conn_hash_lookup_pa_sync_handle(stru
rcu_read_lock();
list_for_each_entry_rcu(c, &h->list, list) {
- if (c->type != BIS_LINK)
+ if (c->type != PA_LINK)
continue;
/* Ignore the listen hcon, we are looking
@@ -2025,6 +2028,7 @@ static inline int hci_proto_connect_ind(
case CIS_LINK:
case BIS_LINK:
+ case PA_LINK:
return iso_connect_ind(hdev, bdaddr, flags);
default:
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -785,7 +785,7 @@ static int hci_le_big_terminate(struct h
d->sync_handle = conn->sync_handle;
if (test_and_clear_bit(HCI_CONN_PA_SYNC, &conn->flags)) {
- hci_conn_hash_list_flag(hdev, find_bis, BIS_LINK,
+ hci_conn_hash_list_flag(hdev, find_bis, PA_LINK,
HCI_CONN_PA_SYNC, d);
if (!d->count)
@@ -914,6 +914,7 @@ static struct hci_conn *__hci_conn_add(s
break;
case CIS_LINK:
case BIS_LINK:
+ case PA_LINK:
if (hdev->iso_mtu)
/* Dedicated ISO Buffer exists */
break;
@@ -980,6 +981,7 @@ static struct hci_conn *__hci_conn_add(s
break;
case CIS_LINK:
case BIS_LINK:
+ case PA_LINK:
/* conn->src should reflect the local identity address */
hci_copy_identity_address(hdev, &conn->src, &conn->src_type);
@@ -1033,7 +1035,6 @@ static struct hci_conn *__hci_conn_add(s
}
hci_conn_init_sysfs(conn);
-
return conn;
}
@@ -1077,6 +1078,7 @@ static void hci_conn_cleanup_child(struc
break;
case CIS_LINK:
case BIS_LINK:
+ case PA_LINK:
if ((conn->state != BT_CONNECTED &&
!test_bit(HCI_CONN_CREATE_CIS, &conn->flags)) ||
test_bit(HCI_CONN_BIG_CREATED, &conn->flags))
@@ -1152,7 +1154,8 @@ void hci_conn_del(struct hci_conn *conn)
} else {
/* Unacked ISO frames */
if (conn->type == CIS_LINK ||
- conn->type == BIS_LINK) {
+ conn->type == BIS_LINK ||
+ conn->type == PA_LINK) {
if (hdev->iso_pkts)
hdev->iso_cnt += conn->sent;
else if (hdev->le_pkts)
@@ -2089,7 +2092,7 @@ struct hci_conn *hci_pa_create_sync(stru
bt_dev_dbg(hdev, "dst %pMR type %d sid %d", dst, dst_type, sid);
- conn = hci_conn_add_unset(hdev, BIS_LINK, dst, HCI_ROLE_SLAVE);
+ conn = hci_conn_add_unset(hdev, PA_LINK, dst, HCI_ROLE_SLAVE);
if (IS_ERR(conn))
return conn;
@@ -2266,7 +2269,7 @@ struct hci_conn *hci_connect_bis(struct
* the start periodic advertising and create BIG commands have
* been queued
*/
- hci_conn_hash_list_state(hdev, bis_mark_per_adv, BIS_LINK,
+ hci_conn_hash_list_state(hdev, bis_mark_per_adv, PA_LINK,
BT_BOUND, &data);
/* Queue start periodic advertising and create BIG */
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2960,12 +2960,14 @@ int hci_recv_frame(struct hci_dev *hdev,
case HCI_ACLDATA_PKT:
/* Detect if ISO packet has been sent as ACL */
if (hci_conn_num(hdev, CIS_LINK) ||
- hci_conn_num(hdev, BIS_LINK)) {
+ hci_conn_num(hdev, BIS_LINK) ||
+ hci_conn_num(hdev, PA_LINK)) {
__u16 handle = __le16_to_cpu(hci_acl_hdr(skb)->handle);
__u8 type;
type = hci_conn_lookup_type(hdev, hci_handle(handle));
- if (type == CIS_LINK || type == BIS_LINK)
+ if (type == CIS_LINK || type == BIS_LINK ||
+ type == PA_LINK)
hci_skb_pkt_type(skb) = HCI_ISODATA_PKT;
}
break;
@@ -3402,6 +3404,7 @@ static inline void hci_quote_sent(struct
break;
case CIS_LINK:
case BIS_LINK:
+ case PA_LINK:
cnt = hdev->iso_mtu ? hdev->iso_cnt :
hdev->le_mtu ? hdev->le_cnt : hdev->acl_cnt;
break;
@@ -3415,7 +3418,7 @@ static inline void hci_quote_sent(struct
}
static struct hci_conn *hci_low_sent(struct hci_dev *hdev, __u8 type,
- __u8 type2, int *quote)
+ int *quote)
{
struct hci_conn_hash *h = &hdev->conn_hash;
struct hci_conn *conn = NULL, *c;
@@ -3427,7 +3430,7 @@ static struct hci_conn *hci_low_sent(str
rcu_read_lock();
list_for_each_entry_rcu(c, &h->list, list) {
- if ((c->type != type && c->type != type2) ||
+ if (c->type != type ||
skb_queue_empty(&c->data_q))
continue;
@@ -3631,7 +3634,7 @@ static void hci_sched_sco(struct hci_dev
else
cnt = &hdev->sco_cnt;
- while (*cnt && (conn = hci_low_sent(hdev, type, type, "e))) {
+ while (*cnt && (conn = hci_low_sent(hdev, type, "e))) {
while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
BT_DBG("skb %p len %d", skb, skb->len);
hci_send_frame(hdev, skb);
@@ -3750,8 +3753,8 @@ static void hci_sched_le(struct hci_dev
hci_prio_recalculate(hdev, LE_LINK);
}
-/* Schedule CIS */
-static void hci_sched_iso(struct hci_dev *hdev)
+/* Schedule iso */
+static void hci_sched_iso(struct hci_dev *hdev, __u8 type)
{
struct hci_conn *conn;
struct sk_buff *skb;
@@ -3759,14 +3762,12 @@ static void hci_sched_iso(struct hci_dev
BT_DBG("%s", hdev->name);
- if (!hci_conn_num(hdev, CIS_LINK) &&
- !hci_conn_num(hdev, BIS_LINK))
+ if (!hci_conn_num(hdev, type))
return;
cnt = hdev->iso_pkts ? &hdev->iso_cnt :
hdev->le_pkts ? &hdev->le_cnt : &hdev->acl_cnt;
- while (*cnt && (conn = hci_low_sent(hdev, CIS_LINK, BIS_LINK,
- "e))) {
+ while (*cnt && (conn = hci_low_sent(hdev, type, "e))) {
while (quote-- && (skb = skb_dequeue(&conn->data_q))) {
BT_DBG("skb %p len %d", skb, skb->len);
hci_send_frame(hdev, skb);
@@ -3791,7 +3792,9 @@ static void hci_tx_work(struct work_stru
/* Schedule queues and send stuff to HCI driver */
hci_sched_sco(hdev, SCO_LINK);
hci_sched_sco(hdev, ESCO_LINK);
- hci_sched_iso(hdev);
+ hci_sched_iso(hdev, CIS_LINK);
+ hci_sched_iso(hdev, BIS_LINK);
+ hci_sched_iso(hdev, PA_LINK);
hci_sched_acl(hdev);
hci_sched_le(hdev);
}
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -4455,6 +4455,7 @@ static void hci_num_comp_pkts_evt(struct
case CIS_LINK:
case BIS_LINK:
+ case PA_LINK:
if (hdev->iso_pkts) {
hdev->iso_cnt += count;
if (hdev->iso_cnt > hdev->iso_pkts)
@@ -6421,7 +6422,7 @@ static void hci_le_pa_sync_estabilished_
conn->sync_handle = le16_to_cpu(ev->handle);
conn->sid = HCI_SID_INVALID;
- mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, BIS_LINK,
+ mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, PA_LINK,
&flags);
if (!(mask & HCI_LM_ACCEPT)) {
hci_le_pa_term_sync(hdev, ev->handle);
@@ -6432,7 +6433,7 @@ static void hci_le_pa_sync_estabilished_
goto unlock;
/* Add connection to indicate PA sync event */
- pa_sync = hci_conn_add_unset(hdev, BIS_LINK, BDADDR_ANY,
+ pa_sync = hci_conn_add_unset(hdev, PA_LINK, BDADDR_ANY,
HCI_ROLE_SLAVE);
if (IS_ERR(pa_sync))
@@ -6463,7 +6464,7 @@ static void hci_le_per_adv_report_evt(st
hci_dev_lock(hdev);
- mask |= hci_proto_connect_ind(hdev, BDADDR_ANY, BIS_LINK, &flags);
+ mask |= hci_proto_connect_ind(hdev, BDADDR_ANY, PA_LINK, &flags);
if (!(mask & HCI_LM_ACCEPT))
goto unlock;
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -2988,7 +2988,7 @@ static int hci_le_set_ext_scan_param_syn
if (sent) {
struct hci_conn *conn;
- conn = hci_conn_hash_lookup_ba(hdev, BIS_LINK,
+ conn = hci_conn_hash_lookup_ba(hdev, PA_LINK,
&sent->bdaddr);
if (conn) {
struct bt_iso_qos *qos = &conn->iso_qos;
@@ -5552,7 +5552,7 @@ static int hci_disconnect_sync(struct hc
{
struct hci_cp_disconnect cp;
- if (conn->type == BIS_LINK) {
+ if (conn->type == BIS_LINK || conn->type == PA_LINK) {
/* This is a BIS connection, hci_conn_del will
* do the necessary cleanup.
*/
@@ -5621,7 +5621,7 @@ static int hci_connect_cancel_sync(struc
return HCI_ERROR_LOCAL_HOST_TERM;
}
- if (conn->type == BIS_LINK) {
+ if (conn->type == BIS_LINK || conn->type == PA_LINK) {
/* There is no way to cancel a BIS without terminating the BIG
* which is done later on connection cleanup.
*/
@@ -5686,7 +5686,7 @@ static int hci_reject_conn_sync(struct h
if (conn->type == CIS_LINK)
return hci_le_reject_cis_sync(hdev, conn, reason);
- if (conn->type == BIS_LINK)
+ if (conn->type == BIS_LINK || conn->type == PA_LINK)
return -EINVAL;
if (conn->type == SCO_LINK || conn->type == ESCO_LINK)
@@ -7157,7 +7157,7 @@ static void create_pa_complete(struct hc
goto unlock;
/* Add connection to indicate PA sync error */
- pa_sync = hci_conn_add_unset(hdev, BIS_LINK, BDADDR_ANY,
+ pa_sync = hci_conn_add_unset(hdev, PA_LINK, BDADDR_ANY,
HCI_ROLE_SLAVE);
if (IS_ERR(pa_sync))
--- a/net/bluetooth/iso.c
+++ b/net/bluetooth/iso.c
@@ -2211,7 +2211,8 @@ done:
static void iso_connect_cfm(struct hci_conn *hcon, __u8 status)
{
- if (hcon->type != CIS_LINK && hcon->type != BIS_LINK) {
+ if (hcon->type != CIS_LINK && hcon->type != BIS_LINK &&
+ hcon->type != PA_LINK) {
if (hcon->type != LE_LINK)
return;
@@ -2252,7 +2253,8 @@ static void iso_connect_cfm(struct hci_c
static void iso_disconn_cfm(struct hci_conn *hcon, __u8 reason)
{
- if (hcon->type != CIS_LINK && hcon->type != BIS_LINK)
+ if (hcon->type != CIS_LINK && hcon->type != BIS_LINK &&
+ hcon->type != PA_LINK)
return;
BT_DBG("hcon %p reason %d", hcon, reason);
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -3258,6 +3258,7 @@ static u8 link_to_bdaddr(u8 link_type, u
switch (link_type) {
case CIS_LINK:
case BIS_LINK:
+ case PA_LINK:
case LE_LINK:
switch (addr_type) {
case ADDR_LE_DEV_PUBLIC:
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 573/602] Bluetooth: hci_core: Fix not accounting for BIS/CIS/PA links separately
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (571 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 572/602] Bluetooth: Add PA_LINK to distinguish BIG sync and PA sync connections Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 574/602] afs: Improve server refcount/active count tracing Greg Kroah-Hartman
` (32 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Luiz Augusto von Dentz, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
[ Upstream commit 9d4b01a0bf8d2163ae129c9c537cb0753ad5a2aa ]
This fixes the likes of hci_conn_num(CIS_LINK) returning the total of
ISO connection which includes BIS_LINK as well, so this splits the
iso_num into each link type and introduces hci_iso_num that can be used
in places where the total number of ISO connection still needs to be
used.
Fixes: 23205562ffc8 ("Bluetooth: separate CIS_LINK and BIS_LINK link types")
Fixes: a7bcffc673de ("Bluetooth: Add PA_LINK to distinguish BIG sync and PA sync connections")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/net/bluetooth/hci_core.h | 30 +++++++++++++++++++++++++-----
1 file changed, 25 insertions(+), 5 deletions(-)
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -128,7 +128,9 @@ struct hci_conn_hash {
struct list_head list;
unsigned int acl_num;
unsigned int sco_num;
- unsigned int iso_num;
+ unsigned int cis_num;
+ unsigned int bis_num;
+ unsigned int pa_num;
unsigned int le_num;
unsigned int le_num_peripheral;
};
@@ -1000,9 +1002,13 @@ static inline void hci_conn_hash_add(str
h->sco_num++;
break;
case CIS_LINK:
+ h->cis_num++;
+ break;
case BIS_LINK:
+ h->bis_num++;
+ break;
case PA_LINK:
- h->iso_num++;
+ h->pa_num++;
break;
}
}
@@ -1028,9 +1034,13 @@ static inline void hci_conn_hash_del(str
h->sco_num--;
break;
case CIS_LINK:
+ h->cis_num--;
+ break;
case BIS_LINK:
+ h->bis_num--;
+ break;
case PA_LINK:
- h->iso_num--;
+ h->pa_num--;
break;
}
}
@@ -1047,9 +1057,11 @@ static inline unsigned int hci_conn_num(
case ESCO_LINK:
return h->sco_num;
case CIS_LINK:
+ return h->cis_num;
case BIS_LINK:
+ return h->bis_num;
case PA_LINK:
- return h->iso_num;
+ return h->pa_num;
default:
return 0;
}
@@ -1059,7 +1071,15 @@ static inline unsigned int hci_conn_coun
{
struct hci_conn_hash *c = &hdev->conn_hash;
- return c->acl_num + c->sco_num + c->le_num + c->iso_num;
+ return c->acl_num + c->sco_num + c->le_num + c->cis_num + c->bis_num +
+ c->pa_num;
+}
+
+static inline unsigned int hci_iso_count(struct hci_dev *hdev)
+{
+ struct hci_conn_hash *c = &hdev->conn_hash;
+
+ return c->cis_num + c->bis_num;
}
static inline bool hci_conn_valid(struct hci_dev *hdev, struct hci_conn *conn)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 574/602] afs: Improve server refcount/active count tracing
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (572 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 573/602] Bluetooth: hci_core: Fix not accounting for BIS/CIS/PA links separately Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 575/602] afs: Make afs_lookup_cell() take a trace note Greg Kroah-Hartman
` (31 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Howells, Marc Dionne,
linux-afs, linux-fsdevel, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <dhowells@redhat.com>
[ Upstream commit 76daa300d41acc1180f8a46eead36905054beafb ]
Improve server refcount/active count tracing to distinguish between simply
getting/putting a ref and using/unusing the server record (which changes
the activity count as well as the refcount). This makes it a bit easier to
work out what's going on.
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
cc: linux-fsdevel@vger.kernel.org
Link: https://lore.kernel.org/r/20250224234154.2014840-10-dhowells@redhat.com/ # v1
Link: https://lore.kernel.org/r/20250310094206.801057-6-dhowells@redhat.com/ # v4
Stable-dep-of: 330e2c514823 ("afs: Fix dynamic lookup to fail on cell lookup failure")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/afs/fsclient.c | 4 ++--
fs/afs/rxrpc.c | 2 +-
fs/afs/server.c | 11 ++++++-----
fs/afs/server_list.c | 4 ++--
include/trace/events/afs.h | 27 +++++++++++++++------------
5 files changed, 26 insertions(+), 22 deletions(-)
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -1650,7 +1650,7 @@ int afs_fs_give_up_all_callbacks(struct
bp = call->request;
*bp++ = htonl(FSGIVEUPALLCALLBACKS);
- call->server = afs_use_server(server, afs_server_trace_give_up_cb);
+ call->server = afs_use_server(server, afs_server_trace_use_give_up_cb);
afs_make_call(call, GFP_NOFS);
afs_wait_for_call_to_complete(call);
ret = call->error;
@@ -1756,7 +1756,7 @@ bool afs_fs_get_capabilities(struct afs_
return false;
call->key = key;
- call->server = afs_use_server(server, afs_server_trace_get_caps);
+ call->server = afs_use_server(server, afs_server_trace_use_get_caps);
call->peer = rxrpc_kernel_get_peer(estate->addresses->addrs[addr_index].peer);
call->probe = afs_get_endpoint_state(estate, afs_estate_trace_get_getcaps);
call->probe_index = addr_index;
--- a/fs/afs/rxrpc.c
+++ b/fs/afs/rxrpc.c
@@ -190,7 +190,7 @@ static void afs_free_call(struct afs_cal
if (call->type->destructor)
call->type->destructor(call);
- afs_unuse_server_notime(call->net, call->server, afs_server_trace_put_call);
+ afs_unuse_server_notime(call->net, call->server, afs_server_trace_unuse_call);
kfree(call->request);
o = atomic_read(&net->nr_outstanding_calls);
--- a/fs/afs/server.c
+++ b/fs/afs/server.c
@@ -33,7 +33,7 @@ struct afs_server *afs_find_server(struc
do {
if (server)
- afs_unuse_server_notime(net, server, afs_server_trace_put_find_rsq);
+ afs_unuse_server_notime(net, server, afs_server_trace_unuse_find_rsq);
server = NULL;
seq++; /* 2 on the 1st/lockless path, otherwise odd */
read_seqbegin_or_lock(&net->fs_addr_lock, &seq);
@@ -49,7 +49,7 @@ struct afs_server *afs_find_server(struc
server = NULL;
continue;
found:
- server = afs_maybe_use_server(server, afs_server_trace_get_by_addr);
+ server = afs_maybe_use_server(server, afs_server_trace_use_by_addr);
} while (need_seqretry(&net->fs_addr_lock, seq));
@@ -76,7 +76,7 @@ struct afs_server *afs_find_server_by_uu
* changes.
*/
if (server)
- afs_unuse_server(net, server, afs_server_trace_put_uuid_rsq);
+ afs_unuse_server(net, server, afs_server_trace_unuse_uuid_rsq);
server = NULL;
seq++; /* 2 on the 1st/lockless path, otherwise odd */
read_seqbegin_or_lock(&net->fs_lock, &seq);
@@ -91,7 +91,7 @@ struct afs_server *afs_find_server_by_uu
} else if (diff > 0) {
p = p->rb_right;
} else {
- afs_use_server(server, afs_server_trace_get_by_uuid);
+ afs_use_server(server, afs_server_trace_use_by_uuid);
break;
}
@@ -273,7 +273,8 @@ static struct afs_addr_list *afs_vl_look
}
/*
- * Get or create a fileserver record.
+ * Get or create a fileserver record and return it with an active-use count on
+ * it.
*/
struct afs_server *afs_lookup_server(struct afs_cell *cell, struct key *key,
const uuid_t *uuid, u32 addr_version)
--- a/fs/afs/server_list.c
+++ b/fs/afs/server_list.c
@@ -16,7 +16,7 @@ void afs_put_serverlist(struct afs_net *
if (slist && refcount_dec_and_test(&slist->usage)) {
for (i = 0; i < slist->nr_servers; i++)
afs_unuse_server(net, slist->servers[i].server,
- afs_server_trace_put_slist);
+ afs_server_trace_unuse_slist);
kfree_rcu(slist, rcu);
}
}
@@ -98,7 +98,7 @@ struct afs_server_list *afs_alloc_server
if (j < slist->nr_servers) {
if (slist->servers[j].server == server) {
afs_unuse_server(volume->cell->net, server,
- afs_server_trace_put_slist_isort);
+ afs_server_trace_unuse_slist_isort);
continue;
}
--- a/include/trace/events/afs.h
+++ b/include/trace/events/afs.h
@@ -132,22 +132,25 @@ enum yfs_cm_operation {
EM(afs_server_trace_destroy, "DESTROY ") \
EM(afs_server_trace_free, "FREE ") \
EM(afs_server_trace_gc, "GC ") \
- EM(afs_server_trace_get_by_addr, "GET addr ") \
- EM(afs_server_trace_get_by_uuid, "GET uuid ") \
- EM(afs_server_trace_get_caps, "GET caps ") \
EM(afs_server_trace_get_install, "GET inst ") \
- EM(afs_server_trace_get_new_cbi, "GET cbi ") \
EM(afs_server_trace_get_probe, "GET probe") \
- EM(afs_server_trace_give_up_cb, "giveup-cb") \
EM(afs_server_trace_purging, "PURGE ") \
- EM(afs_server_trace_put_call, "PUT call ") \
EM(afs_server_trace_put_cbi, "PUT cbi ") \
- EM(afs_server_trace_put_find_rsq, "PUT f-rsq") \
EM(afs_server_trace_put_probe, "PUT probe") \
- EM(afs_server_trace_put_slist, "PUT slist") \
- EM(afs_server_trace_put_slist_isort, "PUT isort") \
- EM(afs_server_trace_put_uuid_rsq, "PUT u-req") \
- E_(afs_server_trace_update, "UPDATE")
+ EM(afs_server_trace_see_expired, "SEE expd ") \
+ EM(afs_server_trace_unuse_call, "UNU call ") \
+ EM(afs_server_trace_unuse_create_fail, "UNU cfail") \
+ EM(afs_server_trace_unuse_find_rsq, "UNU f-rsq") \
+ EM(afs_server_trace_unuse_slist, "UNU slist") \
+ EM(afs_server_trace_unuse_slist_isort, "UNU isort") \
+ EM(afs_server_trace_unuse_uuid_rsq, "PUT u-req") \
+ EM(afs_server_trace_update, "UPDATE ") \
+ EM(afs_server_trace_use_by_addr, "USE addr ") \
+ EM(afs_server_trace_use_by_uuid, "USE uuid ") \
+ EM(afs_server_trace_use_cm_call, "USE cm-cl") \
+ EM(afs_server_trace_use_get_caps, "USE gcaps") \
+ EM(afs_server_trace_use_give_up_cb, "USE gvupc") \
+ E_(afs_server_trace_wait_create, "WAIT crt ")
#define afs_volume_traces \
EM(afs_volume_trace_alloc, "ALLOC ") \
@@ -1369,7 +1372,7 @@ TRACE_EVENT(afs_server,
__entry->reason = reason;
),
- TP_printk("s=%08x %s u=%d a=%d",
+ TP_printk("s=%08x %s r=%d a=%d",
__entry->server,
__print_symbolic(__entry->reason, afs_server_traces),
__entry->ref,
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 575/602] afs: Make afs_lookup_cell() take a trace note
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (573 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 574/602] afs: Improve server refcount/active count tracing Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 576/602] afs: Drop the net parameter from afs_unuse_cell() Greg Kroah-Hartman
` (30 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Howells, Marc Dionne,
linux-afs, linux-fsdevel, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <dhowells@redhat.com>
[ Upstream commit 92c48157ade88e7a543a64af4a806613fbde2ef3 ]
Pass a note to be added to the afs_cell tracepoint to afs_lookup_cell() so
that different callers can be distinguished.
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
cc: linux-fsdevel@vger.kernel.org
Link: https://lore.kernel.org/r/20250224234154.2014840-11-dhowells@redhat.com/ # v1
Link: https://lore.kernel.org/r/20250310094206.801057-7-dhowells@redhat.com/ # v4
Stable-dep-of: 330e2c514823 ("afs: Fix dynamic lookup to fail on cell lookup failure")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/afs/cell.c | 13 ++++++++-----
fs/afs/dynroot.c | 3 ++-
fs/afs/internal.h | 6 ++++--
fs/afs/mntpt.c | 3 ++-
fs/afs/proc.c | 3 ++-
fs/afs/super.c | 3 ++-
fs/afs/vl_alias.c | 3 ++-
include/trace/events/afs.h | 7 ++++++-
8 files changed, 28 insertions(+), 13 deletions(-)
--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -233,6 +233,7 @@ error:
* @namesz: The strlen of the cell name.
* @vllist: A colon/comma separated list of numeric IP addresses or NULL.
* @excl: T if an error should be given if the cell name already exists.
+ * @trace: The reason to be logged if the lookup is successful.
*
* Look up a cell record by name and query the DNS for VL server addresses if
* needed. Note that that actual DNS query is punted off to the manager thread
@@ -241,7 +242,8 @@ error:
*/
struct afs_cell *afs_lookup_cell(struct afs_net *net,
const char *name, unsigned int namesz,
- const char *vllist, bool excl)
+ const char *vllist, bool excl,
+ enum afs_cell_trace trace)
{
struct afs_cell *cell, *candidate, *cursor;
struct rb_node *parent, **pp;
@@ -251,7 +253,7 @@ struct afs_cell *afs_lookup_cell(struct
_enter("%s,%s", name, vllist);
if (!excl) {
- cell = afs_find_cell(net, name, namesz, afs_cell_trace_use_lookup);
+ cell = afs_find_cell(net, name, namesz, trace);
if (!IS_ERR(cell))
goto wait_for_cell;
}
@@ -327,7 +329,7 @@ cell_already_exists:
if (excl) {
ret = -EEXIST;
} else {
- afs_use_cell(cursor, afs_cell_trace_use_lookup);
+ afs_use_cell(cursor, trace);
ret = 0;
}
up_write(&net->cells_lock);
@@ -382,8 +384,9 @@ int afs_cell_init(struct afs_net *net, c
if (cp && cp < rootcell + len)
return -EINVAL;
- /* allocate a cell record for the root cell */
- new_root = afs_lookup_cell(net, rootcell, len, vllist, false);
+ /* allocate a cell record for the root/workstation cell */
+ new_root = afs_lookup_cell(net, rootcell, len, vllist, false,
+ afs_cell_trace_use_lookup_ws);
if (IS_ERR(new_root)) {
_leave(" = %ld", PTR_ERR(new_root));
return PTR_ERR(new_root);
--- a/fs/afs/dynroot.c
+++ b/fs/afs/dynroot.c
@@ -108,7 +108,8 @@ static struct dentry *afs_dynroot_lookup
dotted = true;
}
- cell = afs_lookup_cell(net, name, len, NULL, false);
+ cell = afs_lookup_cell(net, name, len, NULL, false,
+ afs_cell_trace_use_lookup_dynroot);
if (IS_ERR(cell)) {
ret = PTR_ERR(cell);
goto out_no_cell;
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -1040,8 +1040,10 @@ static inline bool afs_cb_is_broken(unsi
extern int afs_cell_init(struct afs_net *, const char *);
extern struct afs_cell *afs_find_cell(struct afs_net *, const char *, unsigned,
enum afs_cell_trace);
-extern struct afs_cell *afs_lookup_cell(struct afs_net *, const char *, unsigned,
- const char *, bool);
+struct afs_cell *afs_lookup_cell(struct afs_net *net,
+ const char *name, unsigned int namesz,
+ const char *vllist, bool excl,
+ enum afs_cell_trace trace);
extern struct afs_cell *afs_use_cell(struct afs_cell *, enum afs_cell_trace);
extern void afs_unuse_cell(struct afs_net *, struct afs_cell *, enum afs_cell_trace);
extern struct afs_cell *afs_get_cell(struct afs_cell *, enum afs_cell_trace);
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -107,7 +107,8 @@ static int afs_mntpt_set_params(struct f
if (size > AFS_MAXCELLNAME)
return -ENAMETOOLONG;
- cell = afs_lookup_cell(ctx->net, p, size, NULL, false);
+ cell = afs_lookup_cell(ctx->net, p, size, NULL, false,
+ afs_cell_trace_use_lookup_mntpt);
if (IS_ERR(cell)) {
pr_err("kAFS: unable to lookup cell '%pd'\n", mntpt);
return PTR_ERR(cell);
--- a/fs/afs/proc.c
+++ b/fs/afs/proc.c
@@ -122,7 +122,8 @@ static int afs_proc_cells_write(struct f
if (strcmp(buf, "add") == 0) {
struct afs_cell *cell;
- cell = afs_lookup_cell(net, name, strlen(name), args, true);
+ cell = afs_lookup_cell(net, name, strlen(name), args, true,
+ afs_cell_trace_use_lookup_add);
if (IS_ERR(cell)) {
ret = PTR_ERR(cell);
goto done;
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -290,7 +290,8 @@ static int afs_parse_source(struct fs_co
/* lookup the cell record */
if (cellname) {
cell = afs_lookup_cell(ctx->net, cellname, cellnamesz,
- NULL, false);
+ NULL, false,
+ afs_cell_trace_use_lookup_mount);
if (IS_ERR(cell)) {
pr_err("kAFS: unable to lookup cell '%*.*s'\n",
cellnamesz, cellnamesz, cellname ?: "");
--- a/fs/afs/vl_alias.c
+++ b/fs/afs/vl_alias.c
@@ -269,7 +269,8 @@ static int yfs_check_canonical_cell_name
if (!name_len || name_len > AFS_MAXCELLNAME)
master = ERR_PTR(-EOPNOTSUPP);
else
- master = afs_lookup_cell(cell->net, cell_name, name_len, NULL, false);
+ master = afs_lookup_cell(cell->net, cell_name, name_len, NULL, false,
+ afs_cell_trace_use_lookup_canonical);
kfree(cell_name);
if (IS_ERR(master))
return PTR_ERR(master);
--- a/include/trace/events/afs.h
+++ b/include/trace/events/afs.h
@@ -208,7 +208,12 @@ enum yfs_cm_operation {
EM(afs_cell_trace_use_check_alias, "USE chk-al") \
EM(afs_cell_trace_use_fc, "USE fc ") \
EM(afs_cell_trace_use_fc_alias, "USE fc-al ") \
- EM(afs_cell_trace_use_lookup, "USE lookup") \
+ EM(afs_cell_trace_use_lookup_add, "USE lu-add") \
+ EM(afs_cell_trace_use_lookup_canonical, "USE lu-can") \
+ EM(afs_cell_trace_use_lookup_dynroot, "USE lu-dyn") \
+ EM(afs_cell_trace_use_lookup_mntpt, "USE lu-mpt") \
+ EM(afs_cell_trace_use_lookup_mount, "USE lu-mnt") \
+ EM(afs_cell_trace_use_lookup_ws, "USE lu-ws ") \
EM(afs_cell_trace_use_mntpt, "USE mntpt ") \
EM(afs_cell_trace_use_pin, "USE pin ") \
EM(afs_cell_trace_use_probe, "USE probe ") \
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 576/602] afs: Drop the net parameter from afs_unuse_cell()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (574 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 575/602] afs: Make afs_lookup_cell() take a trace note Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 577/602] rxrpc: Allow the app to store private data on peer structs Greg Kroah-Hartman
` (29 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Howells, Marc Dionne,
linux-afs, linux-fsdevel, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <dhowells@redhat.com>
[ Upstream commit 469c82b558628482002e4819d35b7670f0a989fd ]
Remove the redundant net parameter to afs_unuse_cell() as cell->net can be
used instead.
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
cc: linux-fsdevel@vger.kernel.org
Link: https://lore.kernel.org/r/20250224234154.2014840-12-dhowells@redhat.com/ # v1
Link: https://lore.kernel.org/r/20250310094206.801057-8-dhowells@redhat.com/ # v4
Stable-dep-of: 330e2c514823 ("afs: Fix dynamic lookup to fail on cell lookup failure")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/afs/cell.c | 12 ++++++------
fs/afs/dynroot.c | 4 ++--
fs/afs/internal.h | 2 +-
fs/afs/mntpt.c | 2 +-
fs/afs/proc.c | 2 +-
fs/afs/super.c | 9 ++++-----
fs/afs/vl_alias.c | 4 ++--
include/trace/events/afs.h | 1 +
8 files changed, 18 insertions(+), 18 deletions(-)
--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -339,7 +339,7 @@ cell_already_exists:
goto wait_for_cell;
goto error_noput;
error:
- afs_unuse_cell(net, cell, afs_cell_trace_unuse_lookup);
+ afs_unuse_cell(cell, afs_cell_trace_unuse_lookup_error);
error_noput:
_leave(" = %d [error]", ret);
return ERR_PTR(ret);
@@ -402,7 +402,7 @@ int afs_cell_init(struct afs_net *net, c
lockdep_is_held(&net->cells_lock));
up_write(&net->cells_lock);
- afs_unuse_cell(net, old_root, afs_cell_trace_unuse_ws);
+ afs_unuse_cell(old_root, afs_cell_trace_unuse_ws);
_leave(" = 0");
return 0;
}
@@ -522,7 +522,7 @@ static void afs_cell_destroy(struct rcu_
trace_afs_cell(cell->debug_id, r, atomic_read(&cell->active), afs_cell_trace_free);
afs_put_vlserverlist(net, rcu_access_pointer(cell->vl_servers));
- afs_unuse_cell(net, cell->alias_of, afs_cell_trace_unuse_alias);
+ afs_unuse_cell(cell->alias_of, afs_cell_trace_unuse_alias);
key_put(cell->anonymous_key);
idr_remove(&net->cells_dyn_ino, cell->dynroot_ino);
kfree(cell->name - 1);
@@ -610,7 +610,7 @@ struct afs_cell *afs_use_cell(struct afs
* Record a cell becoming less active. When the active counter reaches 1, it
* is scheduled for destruction, but may get reactivated.
*/
-void afs_unuse_cell(struct afs_net *net, struct afs_cell *cell, enum afs_cell_trace reason)
+void afs_unuse_cell(struct afs_cell *cell, enum afs_cell_trace reason)
{
unsigned int debug_id;
time64_t now, expire_delay;
@@ -634,7 +634,7 @@ void afs_unuse_cell(struct afs_net *net,
WARN_ON(a == 0);
if (a == 1)
/* 'cell' may now be garbage collected. */
- afs_set_cell_timer(net, expire_delay);
+ afs_set_cell_timer(cell->net, expire_delay);
}
/*
@@ -959,7 +959,7 @@ void afs_cell_purge(struct afs_net *net)
ws = rcu_replace_pointer(net->ws_cell, NULL,
lockdep_is_held(&net->cells_lock));
up_write(&net->cells_lock);
- afs_unuse_cell(net, ws, afs_cell_trace_unuse_ws);
+ afs_unuse_cell(ws, afs_cell_trace_unuse_ws);
_debug("del timer");
if (del_timer_sync(&net->cells_timer))
--- a/fs/afs/dynroot.c
+++ b/fs/afs/dynroot.c
@@ -125,7 +125,7 @@ static struct dentry *afs_dynroot_lookup
return d_splice_alias(inode, dentry);
out:
- afs_unuse_cell(cell->net, cell, afs_cell_trace_unuse_lookup_dynroot);
+ afs_unuse_cell(cell, afs_cell_trace_unuse_lookup_dynroot);
out_no_cell:
if (!inode)
return d_splice_alias(inode, dentry);
@@ -167,7 +167,7 @@ static void afs_dynroot_d_release(struct
{
struct afs_cell *cell = dentry->d_fsdata;
- afs_unuse_cell(cell->net, cell, afs_cell_trace_unuse_dynroot_mntpt);
+ afs_unuse_cell(cell, afs_cell_trace_unuse_dynroot_mntpt);
}
/*
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -1045,7 +1045,7 @@ struct afs_cell *afs_lookup_cell(struct
const char *vllist, bool excl,
enum afs_cell_trace trace);
extern struct afs_cell *afs_use_cell(struct afs_cell *, enum afs_cell_trace);
-extern void afs_unuse_cell(struct afs_net *, struct afs_cell *, enum afs_cell_trace);
+void afs_unuse_cell(struct afs_cell *cell, enum afs_cell_trace reason);
extern struct afs_cell *afs_get_cell(struct afs_cell *, enum afs_cell_trace);
extern void afs_see_cell(struct afs_cell *, enum afs_cell_trace);
extern void afs_put_cell(struct afs_cell *, enum afs_cell_trace);
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -87,7 +87,7 @@ static int afs_mntpt_set_params(struct f
ctx->force = true;
}
if (ctx->cell) {
- afs_unuse_cell(ctx->net, ctx->cell, afs_cell_trace_unuse_mntpt);
+ afs_unuse_cell(ctx->cell, afs_cell_trace_unuse_mntpt);
ctx->cell = NULL;
}
if (test_bit(AFS_VNODE_PSEUDODIR, &vnode->flags)) {
--- a/fs/afs/proc.c
+++ b/fs/afs/proc.c
@@ -130,7 +130,7 @@ static int afs_proc_cells_write(struct f
}
if (test_and_set_bit(AFS_CELL_FL_NO_GC, &cell->flags))
- afs_unuse_cell(net, cell, afs_cell_trace_unuse_no_pin);
+ afs_unuse_cell(cell, afs_cell_trace_unuse_no_pin);
} else {
goto inval;
}
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -297,7 +297,7 @@ static int afs_parse_source(struct fs_co
cellnamesz, cellnamesz, cellname ?: "");
return PTR_ERR(cell);
}
- afs_unuse_cell(ctx->net, ctx->cell, afs_cell_trace_unuse_parse);
+ afs_unuse_cell(ctx->cell, afs_cell_trace_unuse_parse);
afs_see_cell(cell, afs_cell_trace_see_source);
ctx->cell = cell;
}
@@ -394,7 +394,7 @@ static int afs_validate_fc(struct fs_con
ctx->key = NULL;
cell = afs_use_cell(ctx->cell->alias_of,
afs_cell_trace_use_fc_alias);
- afs_unuse_cell(ctx->net, ctx->cell, afs_cell_trace_unuse_fc);
+ afs_unuse_cell(ctx->cell, afs_cell_trace_unuse_fc);
ctx->cell = cell;
goto reget_key;
}
@@ -520,9 +520,8 @@ static struct afs_super_info *afs_alloc_
static void afs_destroy_sbi(struct afs_super_info *as)
{
if (as) {
- struct afs_net *net = afs_net(as->net_ns);
afs_put_volume(as->volume, afs_volume_trace_put_destroy_sbi);
- afs_unuse_cell(net, as->cell, afs_cell_trace_unuse_sbi);
+ afs_unuse_cell(as->cell, afs_cell_trace_unuse_sbi);
put_net(as->net_ns);
kfree(as);
}
@@ -606,7 +605,7 @@ static void afs_free_fc(struct fs_contex
afs_destroy_sbi(fc->s_fs_info);
afs_put_volume(ctx->volume, afs_volume_trace_put_free_fc);
- afs_unuse_cell(ctx->net, ctx->cell, afs_cell_trace_unuse_fc);
+ afs_unuse_cell(ctx->cell, afs_cell_trace_unuse_fc);
key_put(ctx->key);
kfree(ctx);
}
--- a/fs/afs/vl_alias.c
+++ b/fs/afs/vl_alias.c
@@ -205,11 +205,11 @@ static int afs_query_for_alias(struct af
goto is_alias;
if (mutex_lock_interruptible(&cell->net->proc_cells_lock) < 0) {
- afs_unuse_cell(cell->net, p, afs_cell_trace_unuse_check_alias);
+ afs_unuse_cell(p, afs_cell_trace_unuse_check_alias);
return -ERESTARTSYS;
}
- afs_unuse_cell(cell->net, p, afs_cell_trace_unuse_check_alias);
+ afs_unuse_cell(p, afs_cell_trace_unuse_check_alias);
}
mutex_unlock(&cell->net->proc_cells_lock);
--- a/include/trace/events/afs.h
+++ b/include/trace/events/afs.h
@@ -197,6 +197,7 @@ enum yfs_cm_operation {
EM(afs_cell_trace_unuse_fc, "UNU fc ") \
EM(afs_cell_trace_unuse_lookup, "UNU lookup") \
EM(afs_cell_trace_unuse_lookup_dynroot, "UNU lu-dyn") \
+ EM(afs_cell_trace_unuse_lookup_error, "UNU lu-err") \
EM(afs_cell_trace_unuse_mntpt, "UNU mntpt ") \
EM(afs_cell_trace_unuse_no_pin, "UNU no-pin") \
EM(afs_cell_trace_unuse_parse, "UNU parse ") \
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 577/602] rxrpc: Allow the app to store private data on peer structs
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (575 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 576/602] afs: Drop the net parameter from afs_unuse_cell() Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 578/602] afs: Use the per-peer app data provided by rxrpc Greg Kroah-Hartman
` (28 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Howells, Marc Dionne,
Jakub Kicinski, David S. Miller, Eric Dumazet, Paolo Abeni,
Simon Horman, linux-afs, linux-fsdevel, netdev, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <dhowells@redhat.com>
[ Upstream commit f3a123b25429dc03508e3bf598373005220b7203 ]
Provide a way for the application (e.g. the afs filesystem) to store
private data on the rxrpc_peer structs for later retrieval via the call
object.
This will allow afs to store a pointer to the afs_server object on the
rxrpc_peer struct, thereby obviating the need for afs to keep lookup tables
by which it can associate an incoming call with server that transmitted it.
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Jakub Kicinski <kuba@kernel.org>
cc: "David S. Miller" <davem@davemloft.net>
cc: Eric Dumazet <edumazet@google.com>
cc: Paolo Abeni <pabeni@redhat.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
cc: linux-fsdevel@vger.kernel.org
cc: netdev@vger.kernel.org
Link: https://lore.kernel.org/r/20250224234154.2014840-13-dhowells@redhat.com/ # v1
Link: https://lore.kernel.org/r/20250310094206.801057-9-dhowells@redhat.com/ # v4
Stable-dep-of: 330e2c514823 ("afs: Fix dynamic lookup to fail on cell lookup failure")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/net/af_rxrpc.h | 2 ++
net/rxrpc/ar-internal.h | 1 +
net/rxrpc/peer_object.c | 26 ++++++++++++++++++++++++++
3 files changed, 29 insertions(+)
--- a/include/net/af_rxrpc.h
+++ b/include/net/af_rxrpc.h
@@ -74,6 +74,8 @@ struct rxrpc_peer *rxrpc_kernel_get_peer
struct rxrpc_peer *rxrpc_kernel_get_call_peer(struct socket *sock, struct rxrpc_call *call);
const struct sockaddr_rxrpc *rxrpc_kernel_remote_srx(const struct rxrpc_peer *peer);
const struct sockaddr *rxrpc_kernel_remote_addr(const struct rxrpc_peer *peer);
+unsigned long rxrpc_kernel_set_peer_data(struct rxrpc_peer *peer, unsigned long app_data);
+unsigned long rxrpc_kernel_get_peer_data(const struct rxrpc_peer *peer);
unsigned int rxrpc_kernel_get_srtt(const struct rxrpc_peer *);
int rxrpc_kernel_charge_accept(struct socket *sock, rxrpc_notify_rx_t notify_rx,
unsigned long user_call_ID, gfp_t gfp,
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -333,6 +333,7 @@ struct rxrpc_peer {
struct hlist_head error_targets; /* targets for net error distribution */
struct rb_root service_conns; /* Service connections */
struct list_head keepalive_link; /* Link in net->peer_keepalive[] */
+ unsigned long app_data; /* Application data (e.g. afs_server) */
unsigned int last_tx_at; /* Last time packet sent here (time64_t LSW) */
seqlock_t service_conn_lock;
spinlock_t lock; /* access lock */
--- a/net/rxrpc/peer_object.c
+++ b/net/rxrpc/peer_object.c
@@ -510,3 +510,29 @@ const struct sockaddr *rxrpc_kernel_remo
(peer ? &peer->srx.transport : &rxrpc_null_addr.transport);
}
EXPORT_SYMBOL(rxrpc_kernel_remote_addr);
+
+/**
+ * rxrpc_kernel_set_peer_data - Set app-specific data on a peer.
+ * @peer: The peer to alter
+ * @app_data: The data to set
+ *
+ * Set the app-specific data on a peer. AF_RXRPC makes no effort to retain
+ * anything the data might refer to. The previous app_data is returned.
+ */
+unsigned long rxrpc_kernel_set_peer_data(struct rxrpc_peer *peer, unsigned long app_data)
+{
+ return xchg(&peer->app_data, app_data);
+}
+EXPORT_SYMBOL(rxrpc_kernel_set_peer_data);
+
+/**
+ * rxrpc_kernel_get_peer_data - Get app-specific data from a peer.
+ * @peer: The peer to query
+ *
+ * Retrieve the app-specific data from a peer.
+ */
+unsigned long rxrpc_kernel_get_peer_data(const struct rxrpc_peer *peer)
+{
+ return peer->app_data;
+}
+EXPORT_SYMBOL(rxrpc_kernel_get_peer_data);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 578/602] afs: Use the per-peer app data provided by rxrpc
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (576 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 577/602] rxrpc: Allow the app to store private data on peer structs Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 579/602] afs: Fix afs_server ref accounting Greg Kroah-Hartman
` (27 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Howells, Marc Dionne,
linux-afs, linux-fsdevel, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <dhowells@redhat.com>
[ Upstream commit 40e8b52fe8c8ab6920ea5f59c5469b6918cce624 ]
Make use of the per-peer application data that rxrpc now allows the
application to store on the rxrpc_peer struct to hold a back pointer to the
afs_server record that peer represents an endpoint for.
Then, when a call comes in to the AFS cache manager, this can be used to
map it to the correct server record rather than having to use a
UUID-to-server mapping table and having to do an additional lookup.
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
cc: linux-fsdevel@vger.kernel.org
Link: https://lore.kernel.org/r/20250224234154.2014840-14-dhowells@redhat.com/ # v1
Link: https://lore.kernel.org/r/20250310094206.801057-10-dhowells@redhat.com/ # v4
Stable-dep-of: 330e2c514823 ("afs: Fix dynamic lookup to fail on cell lookup failure")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/afs/addr_list.c | 50 +++++++++++++++++++++++++
fs/afs/cmservice.c | 87 +++++++++------------------------------------
fs/afs/fs_probe.c | 32 +++++++++++-----
fs/afs/internal.h | 9 +++-
fs/afs/proc.c | 10 ++++-
fs/afs/rxrpc.c | 6 +++
fs/afs/server.c | 46 ++++++-----------------
include/trace/events/afs.h | 4 --
net/rxrpc/peer_object.c | 4 +-
9 files changed, 125 insertions(+), 123 deletions(-)
--- a/fs/afs/addr_list.c
+++ b/fs/afs/addr_list.c
@@ -362,3 +362,53 @@ int afs_merge_fs_addr6(struct afs_net *n
alist->nr_addrs++;
return 0;
}
+
+/*
+ * Set the app data on the rxrpc peers an address list points to
+ */
+void afs_set_peer_appdata(struct afs_server *server,
+ struct afs_addr_list *old_alist,
+ struct afs_addr_list *new_alist)
+{
+ unsigned long data = (unsigned long)server;
+ int n = 0, o = 0;
+
+ if (!old_alist) {
+ /* New server. Just set all. */
+ for (; n < new_alist->nr_addrs; n++)
+ rxrpc_kernel_set_peer_data(new_alist->addrs[n].peer, data);
+ return;
+ }
+ if (!new_alist) {
+ /* Dead server. Just remove all. */
+ for (; o < old_alist->nr_addrs; o++)
+ rxrpc_kernel_set_peer_data(old_alist->addrs[o].peer, 0);
+ return;
+ }
+
+ /* Walk through the two lists simultaneously, setting new peers and
+ * clearing old ones. The two lists are ordered by pointer to peer
+ * record.
+ */
+ while (n < new_alist->nr_addrs && o < old_alist->nr_addrs) {
+ struct rxrpc_peer *pn = new_alist->addrs[n].peer;
+ struct rxrpc_peer *po = old_alist->addrs[o].peer;
+
+ if (pn == po)
+ continue;
+ if (pn < po) {
+ rxrpc_kernel_set_peer_data(pn, data);
+ n++;
+ } else {
+ rxrpc_kernel_set_peer_data(po, 0);
+ o++;
+ }
+ }
+
+ if (n < new_alist->nr_addrs)
+ for (; n < new_alist->nr_addrs; n++)
+ rxrpc_kernel_set_peer_data(new_alist->addrs[n].peer, data);
+ if (o < old_alist->nr_addrs)
+ for (; o < old_alist->nr_addrs; o++)
+ rxrpc_kernel_set_peer_data(old_alist->addrs[o].peer, 0);
+}
--- a/fs/afs/cmservice.c
+++ b/fs/afs/cmservice.c
@@ -139,49 +139,6 @@ bool afs_cm_incoming_call(struct afs_cal
}
/*
- * Find the server record by peer address and record a probe to the cache
- * manager from a server.
- */
-static int afs_find_cm_server_by_peer(struct afs_call *call)
-{
- struct sockaddr_rxrpc srx;
- struct afs_server *server;
- struct rxrpc_peer *peer;
-
- peer = rxrpc_kernel_get_call_peer(call->net->socket, call->rxcall);
-
- server = afs_find_server(call->net, peer);
- if (!server) {
- trace_afs_cm_no_server(call, &srx);
- return 0;
- }
-
- call->server = server;
- return 0;
-}
-
-/*
- * Find the server record by server UUID and record a probe to the cache
- * manager from a server.
- */
-static int afs_find_cm_server_by_uuid(struct afs_call *call,
- struct afs_uuid *uuid)
-{
- struct afs_server *server;
-
- rcu_read_lock();
- server = afs_find_server_by_uuid(call->net, call->request);
- rcu_read_unlock();
- if (!server) {
- trace_afs_cm_no_server_u(call, call->request);
- return 0;
- }
-
- call->server = server;
- return 0;
-}
-
-/*
* Clean up a cache manager call.
*/
static void afs_cm_destructor(struct afs_call *call)
@@ -322,10 +279,7 @@ static int afs_deliver_cb_callback(struc
if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
return afs_io_error(call, afs_io_error_cm_reply);
-
- /* we'll need the file server record as that tells us which set of
- * vnodes to operate upon */
- return afs_find_cm_server_by_peer(call);
+ return 0;
}
/*
@@ -349,18 +303,10 @@ static void SRXAFSCB_InitCallBackState(s
*/
static int afs_deliver_cb_init_call_back_state(struct afs_call *call)
{
- int ret;
-
_enter("");
afs_extract_discard(call, 0);
- ret = afs_extract_data(call, false);
- if (ret < 0)
- return ret;
-
- /* we'll need the file server record as that tells us which set of
- * vnodes to operate upon */
- return afs_find_cm_server_by_peer(call);
+ return afs_extract_data(call, false);
}
/*
@@ -373,8 +319,6 @@ static int afs_deliver_cb_init_call_back
__be32 *b;
int ret;
- _enter("");
-
_enter("{%u}", call->unmarshall);
switch (call->unmarshall) {
@@ -420,9 +364,18 @@ static int afs_deliver_cb_init_call_back
if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
return afs_io_error(call, afs_io_error_cm_reply);
- /* we'll need the file server record as that tells us which set of
- * vnodes to operate upon */
- return afs_find_cm_server_by_uuid(call, call->request);
+ if (!call->server) {
+ trace_afs_cm_no_server_u(call, call->request);
+ return 0;
+ }
+
+ if (memcmp(call->request, &call->server->_uuid, sizeof(call->server->_uuid)) != 0) {
+ pr_notice("Callback UUID does not match fileserver UUID\n");
+ trace_afs_cm_no_server_u(call, call->request);
+ return 0;
+ }
+
+ return 0;
}
/*
@@ -454,7 +407,7 @@ static int afs_deliver_cb_probe(struct a
if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
return afs_io_error(call, afs_io_error_cm_reply);
- return afs_find_cm_server_by_peer(call);
+ return 0;
}
/*
@@ -531,7 +484,7 @@ static int afs_deliver_cb_probe_uuid(str
if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
return afs_io_error(call, afs_io_error_cm_reply);
- return afs_find_cm_server_by_peer(call);
+ return 0;
}
/*
@@ -591,7 +544,7 @@ static int afs_deliver_cb_tell_me_about_
if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
return afs_io_error(call, afs_io_error_cm_reply);
- return afs_find_cm_server_by_peer(call);
+ return 0;
}
/*
@@ -665,9 +618,5 @@ static int afs_deliver_yfs_cb_callback(s
if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
return afs_io_error(call, afs_io_error_cm_reply);
-
- /* We'll need the file server record as that tells us which set of
- * vnodes to operate upon.
- */
- return afs_find_cm_server_by_peer(call);
+ return 0;
}
--- a/fs/afs/fs_probe.c
+++ b/fs/afs/fs_probe.c
@@ -235,20 +235,20 @@ out:
* Probe all of a fileserver's addresses to find out the best route and to
* query its capabilities.
*/
-void afs_fs_probe_fileserver(struct afs_net *net, struct afs_server *server,
- struct afs_addr_list *new_alist, struct key *key)
+int afs_fs_probe_fileserver(struct afs_net *net, struct afs_server *server,
+ struct afs_addr_list *new_alist, struct key *key)
{
struct afs_endpoint_state *estate, *old;
- struct afs_addr_list *alist;
+ struct afs_addr_list *old_alist = NULL, *alist;
unsigned long unprobed;
_enter("%pU", &server->uuid);
estate = kzalloc(sizeof(*estate), GFP_KERNEL);
if (!estate)
- return;
+ return -ENOMEM;
- refcount_set(&estate->ref, 1);
+ refcount_set(&estate->ref, 2);
estate->server_id = server->debug_id;
estate->rtt = UINT_MAX;
@@ -256,21 +256,31 @@ void afs_fs_probe_fileserver(struct afs_
old = rcu_dereference_protected(server->endpoint_state,
lockdep_is_held(&server->fs_lock));
- estate->responsive_set = old->responsive_set;
- estate->addresses = afs_get_addrlist(new_alist ?: old->addresses,
- afs_alist_trace_get_estate);
+ if (old) {
+ estate->responsive_set = old->responsive_set;
+ if (!new_alist)
+ new_alist = old->addresses;
+ }
+
+ if (old_alist != new_alist)
+ afs_set_peer_appdata(server, old_alist, new_alist);
+
+ estate->addresses = afs_get_addrlist(new_alist, afs_alist_trace_get_estate);
alist = estate->addresses;
estate->probe_seq = ++server->probe_counter;
atomic_set(&estate->nr_probing, alist->nr_addrs);
+ if (new_alist)
+ server->addr_version = new_alist->version;
rcu_assign_pointer(server->endpoint_state, estate);
- set_bit(AFS_ESTATE_SUPERSEDED, &old->flags);
write_unlock(&server->fs_lock);
+ if (old)
+ set_bit(AFS_ESTATE_SUPERSEDED, &old->flags);
trace_afs_estate(estate->server_id, estate->probe_seq, refcount_read(&estate->ref),
afs_estate_trace_alloc_probe);
- afs_get_address_preferences(net, alist);
+ afs_get_address_preferences(net, new_alist);
server->probed_at = jiffies;
unprobed = (1UL << alist->nr_addrs) - 1;
@@ -293,6 +303,8 @@ void afs_fs_probe_fileserver(struct afs_
}
afs_put_endpoint_state(old, afs_estate_trace_put_probe);
+ afs_put_endpoint_state(estate, afs_estate_trace_put_probe);
+ return 0;
}
/*
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -1004,6 +1004,9 @@ extern int afs_merge_fs_addr4(struct afs
__be32 xdr, u16 port);
extern int afs_merge_fs_addr6(struct afs_net *net, struct afs_addr_list *addr,
__be32 *xdr, u16 port);
+void afs_set_peer_appdata(struct afs_server *server,
+ struct afs_addr_list *old_alist,
+ struct afs_addr_list *new_alist);
/*
* addr_prefs.c
@@ -1190,8 +1193,8 @@ struct afs_endpoint_state *afs_get_endpo
enum afs_estate_trace where);
void afs_put_endpoint_state(struct afs_endpoint_state *estate, enum afs_estate_trace where);
extern void afs_fileserver_probe_result(struct afs_call *);
-void afs_fs_probe_fileserver(struct afs_net *net, struct afs_server *server,
- struct afs_addr_list *new_addrs, struct key *key);
+int afs_fs_probe_fileserver(struct afs_net *net, struct afs_server *server,
+ struct afs_addr_list *new_alist, struct key *key);
int afs_wait_for_fs_probes(struct afs_operation *op, struct afs_server_state *states, bool intr);
extern void afs_probe_fileserver(struct afs_net *, struct afs_server *);
extern void afs_fs_probe_dispatcher(struct work_struct *);
@@ -1474,7 +1477,7 @@ extern void __exit afs_clean_up_permit_c
*/
extern spinlock_t afs_server_peer_lock;
-extern struct afs_server *afs_find_server(struct afs_net *, const struct rxrpc_peer *);
+struct afs_server *afs_find_server(const struct rxrpc_peer *peer);
extern struct afs_server *afs_find_server_by_uuid(struct afs_net *, const uuid_t *);
extern struct afs_server *afs_lookup_server(struct afs_cell *, struct key *, const uuid_t *, u32);
extern struct afs_server *afs_get_server(struct afs_server *, enum afs_server_trace);
--- a/fs/afs/proc.c
+++ b/fs/afs/proc.c
@@ -444,8 +444,6 @@ static int afs_proc_servers_show(struct
}
server = list_entry(v, struct afs_server, proc_link);
- estate = rcu_dereference(server->endpoint_state);
- alist = estate->addresses;
seq_printf(m, "%pU %3d %3d %s\n",
&server->uuid,
refcount_read(&server->ref),
@@ -455,10 +453,16 @@ static int afs_proc_servers_show(struct
server->flags, server->rtt);
seq_printf(m, " - probe: last=%d\n",
(int)(jiffies - server->probed_at) / HZ);
+
+ estate = rcu_dereference(server->endpoint_state);
+ if (!estate)
+ goto out;
failed = estate->failed_set;
seq_printf(m, " - ESTATE pq=%x np=%u rsp=%lx f=%lx\n",
estate->probe_seq, atomic_read(&estate->nr_probing),
estate->responsive_set, estate->failed_set);
+
+ alist = estate->addresses;
seq_printf(m, " - ALIST v=%u ap=%u\n",
alist->version, alist->addr_pref_version);
for (i = 0; i < alist->nr_addrs; i++) {
@@ -471,6 +475,8 @@ static int afs_proc_servers_show(struct
rxrpc_kernel_get_srtt(addr->peer),
addr->last_error, addr->prio);
}
+
+out:
return 0;
}
--- a/fs/afs/rxrpc.c
+++ b/fs/afs/rxrpc.c
@@ -791,8 +791,14 @@ static void afs_rx_discard_new_call(stru
static void afs_rx_new_call(struct sock *sk, struct rxrpc_call *rxcall,
unsigned long user_call_ID)
{
+ struct afs_call *call = (struct afs_call *)user_call_ID;
struct afs_net *net = afs_sock2net(sk);
+ call->peer = rxrpc_kernel_get_call_peer(sk->sk_socket, call->rxcall);
+ call->server = afs_find_server(call->peer);
+ if (!call->server)
+ trace_afs_cm_no_server(call, rxrpc_kernel_remote_srx(call->peer));
+
if (net->live)
queue_work(afs_wq, &net->charge_preallocation_work);
}
--- a/fs/afs/server.c
+++ b/fs/afs/server.c
@@ -21,42 +21,13 @@ static void __afs_put_server(struct afs_
/*
* Find a server by one of its addresses.
*/
-struct afs_server *afs_find_server(struct afs_net *net, const struct rxrpc_peer *peer)
+struct afs_server *afs_find_server(const struct rxrpc_peer *peer)
{
- const struct afs_endpoint_state *estate;
- const struct afs_addr_list *alist;
- struct afs_server *server = NULL;
- unsigned int i;
- int seq = 1;
-
- rcu_read_lock();
-
- do {
- if (server)
- afs_unuse_server_notime(net, server, afs_server_trace_unuse_find_rsq);
- server = NULL;
- seq++; /* 2 on the 1st/lockless path, otherwise odd */
- read_seqbegin_or_lock(&net->fs_addr_lock, &seq);
-
- hlist_for_each_entry_rcu(server, &net->fs_addresses, addr_link) {
- estate = rcu_dereference(server->endpoint_state);
- alist = estate->addresses;
- for (i = 0; i < alist->nr_addrs; i++)
- if (alist->addrs[i].peer == peer)
- goto found;
- }
+ struct afs_server *server = (struct afs_server *)rxrpc_kernel_get_peer_data(peer);
- server = NULL;
- continue;
- found:
- server = afs_maybe_use_server(server, afs_server_trace_use_by_addr);
-
- } while (need_seqretry(&net->fs_addr_lock, seq));
-
- done_seqretry(&net->fs_addr_lock, seq);
-
- rcu_read_unlock();
- return server;
+ if (!server)
+ return NULL;
+ return afs_maybe_use_server(server, afs_server_trace_use_cm_call);
}
/*
@@ -469,9 +440,16 @@ static void afs_give_up_callbacks(struct
*/
static void afs_destroy_server(struct afs_net *net, struct afs_server *server)
{
+ struct afs_endpoint_state *estate;
+
if (test_bit(AFS_SERVER_FL_MAY_HAVE_CB, &server->flags))
afs_give_up_callbacks(net, server);
+ /* Unbind the rxrpc_peer records from the server. */
+ estate = rcu_access_pointer(server->endpoint_state);
+ if (estate)
+ afs_set_peer_appdata(server, estate->addresses, NULL);
+
afs_put_server(net, server, afs_server_trace_destroy);
}
--- a/include/trace/events/afs.h
+++ b/include/trace/events/afs.h
@@ -140,12 +140,10 @@ enum yfs_cm_operation {
EM(afs_server_trace_see_expired, "SEE expd ") \
EM(afs_server_trace_unuse_call, "UNU call ") \
EM(afs_server_trace_unuse_create_fail, "UNU cfail") \
- EM(afs_server_trace_unuse_find_rsq, "UNU f-rsq") \
EM(afs_server_trace_unuse_slist, "UNU slist") \
EM(afs_server_trace_unuse_slist_isort, "UNU isort") \
EM(afs_server_trace_unuse_uuid_rsq, "PUT u-req") \
EM(afs_server_trace_update, "UPDATE ") \
- EM(afs_server_trace_use_by_addr, "USE addr ") \
EM(afs_server_trace_use_by_uuid, "USE uuid ") \
EM(afs_server_trace_use_cm_call, "USE cm-cl") \
EM(afs_server_trace_use_get_caps, "USE gcaps") \
@@ -1119,7 +1117,7 @@ TRACE_EVENT(afs_bulkstat_error,
);
TRACE_EVENT(afs_cm_no_server,
- TP_PROTO(struct afs_call *call, struct sockaddr_rxrpc *srx),
+ TP_PROTO(struct afs_call *call, const struct sockaddr_rxrpc *srx),
TP_ARGS(call, srx),
--- a/net/rxrpc/peer_object.c
+++ b/net/rxrpc/peer_object.c
@@ -451,7 +451,7 @@ void rxrpc_destroy_all_peers(struct rxrp
continue;
hlist_for_each_entry(peer, &rxnet->peer_hash[i], hash_link) {
- pr_err("Leaked peer %u {%u} %pISp\n",
+ pr_err("Leaked peer %x {%u} %pISp\n",
peer->debug_id,
refcount_read(&peer->ref),
&peer->srx.transport);
@@ -468,7 +468,7 @@ void rxrpc_destroy_all_peers(struct rxrp
*/
struct rxrpc_peer *rxrpc_kernel_get_call_peer(struct socket *sock, struct rxrpc_call *call)
{
- return call->peer;
+ return rxrpc_get_peer(call->peer, rxrpc_peer_get_application);
}
EXPORT_SYMBOL(rxrpc_kernel_get_call_peer);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 579/602] afs: Fix afs_server ref accounting
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (577 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 578/602] afs: Use the per-peer app data provided by rxrpc Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 580/602] afs: Simplify cell record handling Greg Kroah-Hartman
` (26 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Howells, Marc Dionne,
linux-afs, linux-fsdevel, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <dhowells@redhat.com>
[ Upstream commit 4882ba78574e2d8c579658f65f6784b0d139d173 ]
The current way that afs_server refs are accounted and cleaned up sometimes
cause rmmod to hang when it is waiting for cell records to be removed. The
problem is that the cell cleanup might occasionally happen before the
server cleanup and then there's nothing that causes the cell to
garbage-collect the remaining servers as they become inactive.
Partially fix this by:
(1) Give each afs_server record its own management timer that rather than
relying on the cell manager's central timer to drive each individual
cell's maintenance work item to garbage collect servers.
This timer is set when afs_unuse_server() reduces a server's activity
count to zero and will schedule the server's destroyer work item upon
firing.
(2) Give each afs_server record its own destroyer work item that removes
the record from the cell's database, shuts down the timer, cancels any
pending work for itself, sends an RPC to the server to cancel
outstanding callbacks.
This change, in combination with the timer, obviates the need to try
and coordinate so closely between the cell record and a bunch of other
server records to try and tear everything down in a coordinated
fashion. With this, the cell record is pinned until the server RCU is
complete and namespace/module removal will wait until all the cell
records are removed.
(3) Now that incoming calls are mapped to servers (and thus cells) using
data attached to an rxrpc_peer, the UUID-to-server mapping tree is
moved from the namespace to the cell (cell->fs_servers). This means
there can no longer be duplicates therein - and that allows the
mapping tree to be simpler as there doesn't need to be a chain of
same-UUID servers that are in different cells.
(4) The lock protecting the UUID mapping tree is switched to an
rw_semaphore on the cell rather than a seqlock on the namespace as
it's now only used during mounting in contexts in which we're allowed
to sleep.
(5) When it comes time for a cell that is being removed to purge its set
of servers, it just needs to iterate over them and wake them up. Once
a server becomes inactive, its destroyer work item will observe the
state of the cell and immediately remove that record.
(6) When a server record is removed, it is marked AFS_SERVER_FL_EXPIRED to
prevent reattempts at removal. The record will be dispatched to RCU
for destruction once its refcount reaches 0.
(7) The AFS_SERVER_FL_UNCREATED/CREATING flags are used to synchronise
simultaneous creation attempts. If one attempt fails, it will abandon
the attempt and allow another to try again.
Note that the record can't just be abandoned when dead as it's bound
into a server list attached to a volume and only subject to
replacement if the server list obtained for the volume from the VLDB
changes.
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
cc: linux-fsdevel@vger.kernel.org
Link: https://lore.kernel.org/r/20250224234154.2014840-15-dhowells@redhat.com/ # v1
Link: https://lore.kernel.org/r/20250310094206.801057-11-dhowells@redhat.com/ # v4
Stable-dep-of: 330e2c514823 ("afs: Fix dynamic lookup to fail on cell lookup failure")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/afs/cell.c | 3
fs/afs/fsclient.c | 4
fs/afs/internal.h | 54 ++--
fs/afs/main.c | 10
fs/afs/server.c | 560 +++++++++++++++++++--------------------------
fs/afs/server_list.c | 4
include/trace/events/afs.h | 7
7 files changed, 287 insertions(+), 355 deletions(-)
--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -169,7 +169,7 @@ static struct afs_cell *afs_alloc_cell(s
INIT_HLIST_HEAD(&cell->proc_volumes);
seqlock_init(&cell->volume_lock);
cell->fs_servers = RB_ROOT;
- seqlock_init(&cell->fs_lock);
+ init_rwsem(&cell->fs_lock);
rwlock_init(&cell->vl_servers_lock);
cell->flags = (1 << AFS_CELL_FL_CHECK_ALIAS);
@@ -840,6 +840,7 @@ final_destruction:
/* The root volume is pinning the cell */
afs_put_volume(cell->root_volume, afs_volume_trace_put_cell_root);
cell->root_volume = NULL;
+ afs_purge_servers(cell);
afs_put_cell(cell, afs_cell_trace_put_destroy);
}
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -1650,7 +1650,7 @@ int afs_fs_give_up_all_callbacks(struct
bp = call->request;
*bp++ = htonl(FSGIVEUPALLCALLBACKS);
- call->server = afs_use_server(server, afs_server_trace_use_give_up_cb);
+ call->server = afs_use_server(server, false, afs_server_trace_use_give_up_cb);
afs_make_call(call, GFP_NOFS);
afs_wait_for_call_to_complete(call);
ret = call->error;
@@ -1756,7 +1756,7 @@ bool afs_fs_get_capabilities(struct afs_
return false;
call->key = key;
- call->server = afs_use_server(server, afs_server_trace_use_get_caps);
+ call->server = afs_use_server(server, false, afs_server_trace_use_get_caps);
call->peer = rxrpc_kernel_get_peer(estate->addresses->addrs[addr_index].peer);
call->probe = afs_get_endpoint_state(estate, afs_estate_trace_get_getcaps);
call->probe_index = addr_index;
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -317,18 +317,11 @@ struct afs_net {
* cell, but in practice, people create aliases and subsets and there's
* no easy way to distinguish them.
*/
- seqlock_t fs_lock; /* For fs_servers, fs_probe_*, fs_proc */
- struct rb_root fs_servers; /* afs_server (by server UUID or address) */
+ seqlock_t fs_lock; /* For fs_probe_*, fs_proc */
struct list_head fs_probe_fast; /* List of afs_server to probe at 30s intervals */
struct list_head fs_probe_slow; /* List of afs_server to probe at 5m intervals */
struct hlist_head fs_proc; /* procfs servers list */
- struct hlist_head fs_addresses; /* afs_server (by lowest IPv6 addr) */
- seqlock_t fs_addr_lock; /* For fs_addresses[46] */
-
- struct work_struct fs_manager;
- struct timer_list fs_timer;
-
struct work_struct fs_prober;
struct timer_list fs_probe_timer;
atomic_t servers_outstanding;
@@ -424,7 +417,7 @@ struct afs_cell {
/* Active fileserver interaction state. */
struct rb_root fs_servers; /* afs_server (by server UUID) */
- seqlock_t fs_lock; /* For fs_servers */
+ struct rw_semaphore fs_lock; /* For fs_servers */
/* VL server list. */
rwlock_t vl_servers_lock; /* Lock on vl_servers */
@@ -559,22 +552,22 @@ struct afs_server {
};
struct afs_cell *cell; /* Cell to which belongs (pins ref) */
- struct rb_node uuid_rb; /* Link in net->fs_servers */
- struct afs_server __rcu *uuid_next; /* Next server with same UUID */
- struct afs_server *uuid_prev; /* Previous server with same UUID */
- struct list_head probe_link; /* Link in net->fs_probe_list */
- struct hlist_node addr_link; /* Link in net->fs_addresses6 */
+ struct rb_node uuid_rb; /* Link in cell->fs_servers */
+ struct list_head probe_link; /* Link in net->fs_probe_* */
struct hlist_node proc_link; /* Link in net->fs_proc */
struct list_head volumes; /* RCU list of afs_server_entry objects */
- struct afs_server *gc_next; /* Next server in manager's list */
+ struct work_struct destroyer; /* Work item to try and destroy a server */
+ struct timer_list timer; /* Management timer */
time64_t unuse_time; /* Time at which last unused */
unsigned long flags;
#define AFS_SERVER_FL_RESPONDING 0 /* The server is responding */
#define AFS_SERVER_FL_UPDATING 1
#define AFS_SERVER_FL_NEEDS_UPDATE 2 /* Fileserver address list is out of date */
-#define AFS_SERVER_FL_NOT_READY 4 /* The record is not ready for use */
-#define AFS_SERVER_FL_NOT_FOUND 5 /* VL server says no such server */
-#define AFS_SERVER_FL_VL_FAIL 6 /* Failed to access VL server */
+#define AFS_SERVER_FL_UNCREATED 3 /* The record needs creating */
+#define AFS_SERVER_FL_CREATING 4 /* The record is being created */
+#define AFS_SERVER_FL_EXPIRED 5 /* The record has expired */
+#define AFS_SERVER_FL_NOT_FOUND 6 /* VL server says no such server */
+#define AFS_SERVER_FL_VL_FAIL 7 /* Failed to access VL server */
#define AFS_SERVER_FL_MAY_HAVE_CB 8 /* May have callbacks on this fileserver */
#define AFS_SERVER_FL_IS_YFS 16 /* Server is YFS not AFS */
#define AFS_SERVER_FL_NO_IBULK 17 /* Fileserver doesn't support FS.InlineBulkStatus */
@@ -584,6 +577,7 @@ struct afs_server {
atomic_t active; /* Active user count */
u32 addr_version; /* Address list version */
u16 service_id; /* Service ID we're using. */
+ short create_error; /* Creation error */
unsigned int rtt; /* Server's current RTT in uS */
unsigned int debug_id; /* Debugging ID for traces */
@@ -1478,19 +1472,29 @@ extern void __exit afs_clean_up_permit_c
extern spinlock_t afs_server_peer_lock;
struct afs_server *afs_find_server(const struct rxrpc_peer *peer);
-extern struct afs_server *afs_find_server_by_uuid(struct afs_net *, const uuid_t *);
extern struct afs_server *afs_lookup_server(struct afs_cell *, struct key *, const uuid_t *, u32);
extern struct afs_server *afs_get_server(struct afs_server *, enum afs_server_trace);
-extern struct afs_server *afs_use_server(struct afs_server *, enum afs_server_trace);
-extern void afs_unuse_server(struct afs_net *, struct afs_server *, enum afs_server_trace);
-extern void afs_unuse_server_notime(struct afs_net *, struct afs_server *, enum afs_server_trace);
+struct afs_server *afs_use_server(struct afs_server *server, bool activate,
+ enum afs_server_trace reason);
+void afs_unuse_server(struct afs_net *net, struct afs_server *server,
+ enum afs_server_trace reason);
+void afs_unuse_server_notime(struct afs_net *net, struct afs_server *server,
+ enum afs_server_trace reason);
extern void afs_put_server(struct afs_net *, struct afs_server *, enum afs_server_trace);
-extern void afs_manage_servers(struct work_struct *);
-extern void afs_servers_timer(struct timer_list *);
+void afs_purge_servers(struct afs_cell *cell);
extern void afs_fs_probe_timer(struct timer_list *);
-extern void __net_exit afs_purge_servers(struct afs_net *);
+void __net_exit afs_wait_for_servers(struct afs_net *net);
bool afs_check_server_record(struct afs_operation *op, struct afs_server *server, struct key *key);
+static inline void afs_see_server(struct afs_server *server, enum afs_server_trace trace)
+{
+ int r = refcount_read(&server->ref);
+ int a = atomic_read(&server->active);
+
+ trace_afs_server(server->debug_id, r, a, trace);
+
+}
+
static inline void afs_inc_servers_outstanding(struct afs_net *net)
{
atomic_inc(&net->servers_outstanding);
--- a/fs/afs/main.c
+++ b/fs/afs/main.c
@@ -86,16 +86,10 @@ static int __net_init afs_net_init(struc
INIT_HLIST_HEAD(&net->proc_cells);
seqlock_init(&net->fs_lock);
- net->fs_servers = RB_ROOT;
INIT_LIST_HEAD(&net->fs_probe_fast);
INIT_LIST_HEAD(&net->fs_probe_slow);
INIT_HLIST_HEAD(&net->fs_proc);
- INIT_HLIST_HEAD(&net->fs_addresses);
- seqlock_init(&net->fs_addr_lock);
-
- INIT_WORK(&net->fs_manager, afs_manage_servers);
- timer_setup(&net->fs_timer, afs_servers_timer, 0);
INIT_WORK(&net->fs_prober, afs_fs_probe_dispatcher);
timer_setup(&net->fs_probe_timer, afs_fs_probe_timer, 0);
atomic_set(&net->servers_outstanding, 1);
@@ -131,7 +125,7 @@ error_open_socket:
net->live = false;
afs_fs_probe_cleanup(net);
afs_cell_purge(net);
- afs_purge_servers(net);
+ afs_wait_for_servers(net);
error_cell_init:
net->live = false;
afs_proc_cleanup(net);
@@ -153,7 +147,7 @@ static void __net_exit afs_net_exit(stru
net->live = false;
afs_fs_probe_cleanup(net);
afs_cell_purge(net);
- afs_purge_servers(net);
+ afs_wait_for_servers(net);
afs_close_socket(net);
afs_proc_cleanup(net);
afs_put_sysnames(net->sysnames);
--- a/fs/afs/server.c
+++ b/fs/afs/server.c
@@ -14,9 +14,9 @@
static unsigned afs_server_gc_delay = 10; /* Server record timeout in seconds */
static atomic_t afs_server_debug_id;
-static struct afs_server *afs_maybe_use_server(struct afs_server *,
- enum afs_server_trace);
static void __afs_put_server(struct afs_net *, struct afs_server *);
+static void afs_server_timer(struct timer_list *timer);
+static void afs_server_destroyer(struct work_struct *work);
/*
* Find a server by one of its addresses.
@@ -27,148 +27,91 @@ struct afs_server *afs_find_server(const
if (!server)
return NULL;
- return afs_maybe_use_server(server, afs_server_trace_use_cm_call);
+ return afs_use_server(server, false, afs_server_trace_use_cm_call);
}
/*
- * Look up a server by its UUID and mark it active.
+ * Look up a server by its UUID and mark it active. The caller must hold
+ * cell->fs_lock.
*/
-struct afs_server *afs_find_server_by_uuid(struct afs_net *net, const uuid_t *uuid)
+static struct afs_server *afs_find_server_by_uuid(struct afs_cell *cell, const uuid_t *uuid)
{
- struct afs_server *server = NULL;
+ struct afs_server *server;
struct rb_node *p;
- int diff, seq = 1;
+ int diff;
_enter("%pU", uuid);
- do {
- /* Unfortunately, rbtree walking doesn't give reliable results
- * under just the RCU read lock, so we have to check for
- * changes.
- */
- if (server)
- afs_unuse_server(net, server, afs_server_trace_unuse_uuid_rsq);
- server = NULL;
- seq++; /* 2 on the 1st/lockless path, otherwise odd */
- read_seqbegin_or_lock(&net->fs_lock, &seq);
-
- p = net->fs_servers.rb_node;
- while (p) {
- server = rb_entry(p, struct afs_server, uuid_rb);
-
- diff = memcmp(uuid, &server->uuid, sizeof(*uuid));
- if (diff < 0) {
- p = p->rb_left;
- } else if (diff > 0) {
- p = p->rb_right;
- } else {
- afs_use_server(server, afs_server_trace_use_by_uuid);
- break;
- }
+ p = cell->fs_servers.rb_node;
+ while (p) {
+ server = rb_entry(p, struct afs_server, uuid_rb);
- server = NULL;
+ diff = memcmp(uuid, &server->uuid, sizeof(*uuid));
+ if (diff < 0) {
+ p = p->rb_left;
+ } else if (diff > 0) {
+ p = p->rb_right;
+ } else {
+ if (test_bit(AFS_SERVER_FL_UNCREATED, &server->flags))
+ return NULL; /* Need a write lock */
+ afs_use_server(server, true, afs_server_trace_use_by_uuid);
+ return server;
}
- } while (need_seqretry(&net->fs_lock, seq));
-
- done_seqretry(&net->fs_lock, seq);
+ }
- _leave(" = %p", server);
- return server;
+ return NULL;
}
/*
- * Install a server record in the namespace tree. If there's a clash, we stick
- * it into a list anchored on whichever afs_server struct is actually in the
- * tree.
+ * Install a server record in the cell tree. The caller must hold an exclusive
+ * lock on cell->fs_lock.
*/
static struct afs_server *afs_install_server(struct afs_cell *cell,
- struct afs_server *candidate)
+ struct afs_server **candidate)
{
- const struct afs_endpoint_state *estate;
- const struct afs_addr_list *alist;
- struct afs_server *server, *next;
+ struct afs_server *server;
struct afs_net *net = cell->net;
struct rb_node **pp, *p;
int diff;
_enter("%p", candidate);
- write_seqlock(&net->fs_lock);
-
/* Firstly install the server in the UUID lookup tree */
- pp = &net->fs_servers.rb_node;
+ pp = &cell->fs_servers.rb_node;
p = NULL;
while (*pp) {
p = *pp;
_debug("- consider %p", p);
server = rb_entry(p, struct afs_server, uuid_rb);
- diff = memcmp(&candidate->uuid, &server->uuid, sizeof(uuid_t));
- if (diff < 0) {
+ diff = memcmp(&(*candidate)->uuid, &server->uuid, sizeof(uuid_t));
+ if (diff < 0)
pp = &(*pp)->rb_left;
- } else if (diff > 0) {
+ else if (diff > 0)
pp = &(*pp)->rb_right;
- } else {
- if (server->cell == cell)
- goto exists;
-
- /* We have the same UUID representing servers in
- * different cells. Append the new server to the list.
- */
- for (;;) {
- next = rcu_dereference_protected(
- server->uuid_next,
- lockdep_is_held(&net->fs_lock.lock));
- if (!next)
- break;
- server = next;
- }
- rcu_assign_pointer(server->uuid_next, candidate);
- candidate->uuid_prev = server;
- server = candidate;
- goto added_dup;
- }
+ else
+ goto exists;
}
- server = candidate;
+ server = *candidate;
+ *candidate = NULL;
rb_link_node(&server->uuid_rb, p, pp);
- rb_insert_color(&server->uuid_rb, &net->fs_servers);
+ rb_insert_color(&server->uuid_rb, &cell->fs_servers);
+ write_seqlock(&net->fs_lock);
hlist_add_head_rcu(&server->proc_link, &net->fs_proc);
+ write_sequnlock(&net->fs_lock);
afs_get_cell(cell, afs_cell_trace_get_server);
-added_dup:
- write_seqlock(&net->fs_addr_lock);
- estate = rcu_dereference_protected(server->endpoint_state,
- lockdep_is_held(&net->fs_addr_lock.lock));
- alist = estate->addresses;
-
- /* Secondly, if the server has any IPv4 and/or IPv6 addresses, install
- * it in the IPv4 and/or IPv6 reverse-map lists.
- *
- * TODO: For speed we want to use something other than a flat list
- * here; even sorting the list in terms of lowest address would help a
- * bit, but anything we might want to do gets messy and memory
- * intensive.
- */
- if (alist->nr_addrs > 0)
- hlist_add_head_rcu(&server->addr_link, &net->fs_addresses);
-
- write_sequnlock(&net->fs_addr_lock);
-
exists:
- afs_get_server(server, afs_server_trace_get_install);
- write_sequnlock(&net->fs_lock);
+ afs_use_server(server, true, afs_server_trace_get_install);
return server;
}
/*
- * Allocate a new server record and mark it active.
+ * Allocate a new server record and mark it as active but uncreated.
*/
-static struct afs_server *afs_alloc_server(struct afs_cell *cell,
- const uuid_t *uuid,
- struct afs_addr_list *alist)
+static struct afs_server *afs_alloc_server(struct afs_cell *cell, const uuid_t *uuid)
{
- struct afs_endpoint_state *estate;
struct afs_server *server;
struct afs_net *net = cell->net;
@@ -176,65 +119,49 @@ static struct afs_server *afs_alloc_serv
server = kzalloc(sizeof(struct afs_server), GFP_KERNEL);
if (!server)
- goto enomem;
-
- estate = kzalloc(sizeof(struct afs_endpoint_state), GFP_KERNEL);
- if (!estate)
- goto enomem_server;
+ return NULL;
refcount_set(&server->ref, 1);
- atomic_set(&server->active, 1);
+ atomic_set(&server->active, 0);
+ __set_bit(AFS_SERVER_FL_UNCREATED, &server->flags);
server->debug_id = atomic_inc_return(&afs_server_debug_id);
- server->addr_version = alist->version;
server->uuid = *uuid;
rwlock_init(&server->fs_lock);
+ INIT_WORK(&server->destroyer, &afs_server_destroyer);
+ timer_setup(&server->timer, afs_server_timer, 0);
INIT_LIST_HEAD(&server->volumes);
init_waitqueue_head(&server->probe_wq);
INIT_LIST_HEAD(&server->probe_link);
+ INIT_HLIST_NODE(&server->proc_link);
spin_lock_init(&server->probe_lock);
server->cell = cell;
server->rtt = UINT_MAX;
server->service_id = FS_SERVICE;
-
server->probe_counter = 1;
server->probed_at = jiffies - LONG_MAX / 2;
- refcount_set(&estate->ref, 1);
- estate->addresses = alist;
- estate->server_id = server->debug_id;
- estate->probe_seq = 1;
- rcu_assign_pointer(server->endpoint_state, estate);
afs_inc_servers_outstanding(net);
- trace_afs_server(server->debug_id, 1, 1, afs_server_trace_alloc);
- trace_afs_estate(estate->server_id, estate->probe_seq, refcount_read(&estate->ref),
- afs_estate_trace_alloc_server);
_leave(" = %p", server);
return server;
-
-enomem_server:
- kfree(server);
-enomem:
- _leave(" = NULL [nomem]");
- return NULL;
}
/*
* Look up an address record for a server
*/
-static struct afs_addr_list *afs_vl_lookup_addrs(struct afs_cell *cell,
- struct key *key, const uuid_t *uuid)
+static struct afs_addr_list *afs_vl_lookup_addrs(struct afs_server *server,
+ struct key *key)
{
struct afs_vl_cursor vc;
struct afs_addr_list *alist = NULL;
int ret;
ret = -ERESTARTSYS;
- if (afs_begin_vlserver_operation(&vc, cell, key)) {
+ if (afs_begin_vlserver_operation(&vc, server->cell, key)) {
while (afs_select_vlserver(&vc)) {
if (test_bit(AFS_VLSERVER_FL_IS_YFS, &vc.server->flags))
- alist = afs_yfsvl_get_endpoints(&vc, uuid);
+ alist = afs_yfsvl_get_endpoints(&vc, &server->uuid);
else
- alist = afs_vl_get_addrs_u(&vc, uuid);
+ alist = afs_vl_get_addrs_u(&vc, &server->uuid);
}
ret = afs_end_vlserver_operation(&vc);
@@ -250,67 +177,116 @@ static struct afs_addr_list *afs_vl_look
struct afs_server *afs_lookup_server(struct afs_cell *cell, struct key *key,
const uuid_t *uuid, u32 addr_version)
{
- struct afs_addr_list *alist;
- struct afs_server *server, *candidate;
+ struct afs_addr_list *alist = NULL;
+ struct afs_server *server, *candidate = NULL;
+ bool creating = false;
+ int ret;
_enter("%p,%pU", cell->net, uuid);
- server = afs_find_server_by_uuid(cell->net, uuid);
+ down_read(&cell->fs_lock);
+ server = afs_find_server_by_uuid(cell, uuid);
+ /* Won't see servers marked uncreated. */
+ up_read(&cell->fs_lock);
+
if (server) {
+ timer_delete_sync(&server->timer);
+ if (test_bit(AFS_SERVER_FL_CREATING, &server->flags))
+ goto wait_for_creation;
if (server->addr_version != addr_version)
set_bit(AFS_SERVER_FL_NEEDS_UPDATE, &server->flags);
return server;
}
- alist = afs_vl_lookup_addrs(cell, key, uuid);
- if (IS_ERR(alist))
- return ERR_CAST(alist);
-
- candidate = afs_alloc_server(cell, uuid, alist);
+ candidate = afs_alloc_server(cell, uuid);
if (!candidate) {
afs_put_addrlist(alist, afs_alist_trace_put_server_oom);
return ERR_PTR(-ENOMEM);
}
- server = afs_install_server(cell, candidate);
- if (server != candidate) {
- afs_put_addrlist(alist, afs_alist_trace_put_server_dup);
+ down_write(&cell->fs_lock);
+ server = afs_install_server(cell, &candidate);
+ if (test_bit(AFS_SERVER_FL_CREATING, &server->flags)) {
+ /* We need to wait for creation to complete. */
+ up_write(&cell->fs_lock);
+ goto wait_for_creation;
+ }
+ if (test_bit(AFS_SERVER_FL_UNCREATED, &server->flags)) {
+ set_bit(AFS_SERVER_FL_CREATING, &server->flags);
+ clear_bit(AFS_SERVER_FL_UNCREATED, &server->flags);
+ creating = true;
+ }
+ up_write(&cell->fs_lock);
+ timer_delete_sync(&server->timer);
+
+ /* If we get to create the server, we look up the addresses and then
+ * immediately dispatch an asynchronous probe to each interface on the
+ * fileserver. This will make sure the repeat-probing service is
+ * started.
+ */
+ if (creating) {
+ alist = afs_vl_lookup_addrs(server, key);
+ if (IS_ERR(alist)) {
+ ret = PTR_ERR(alist);
+ goto create_failed;
+ }
+
+ ret = afs_fs_probe_fileserver(cell->net, server, alist, key);
+ if (ret)
+ goto create_failed;
+
+ clear_and_wake_up_bit(AFS_SERVER_FL_CREATING, &server->flags);
+ }
+
+out:
+ afs_put_addrlist(alist, afs_alist_trace_put_server_create);
+ if (candidate) {
+ kfree(rcu_access_pointer(server->endpoint_state));
kfree(candidate);
- } else {
- /* Immediately dispatch an asynchronous probe to each interface
- * on the fileserver. This will make sure the repeat-probing
- * service is started.
- */
- afs_fs_probe_fileserver(cell->net, server, alist, key);
+ afs_dec_servers_outstanding(cell->net);
}
+ return server ?: ERR_PTR(ret);
- return server;
-}
+wait_for_creation:
+ afs_see_server(server, afs_server_trace_wait_create);
+ wait_on_bit(&server->flags, AFS_SERVER_FL_CREATING, TASK_UNINTERRUPTIBLE);
+ if (test_bit_acquire(AFS_SERVER_FL_UNCREATED, &server->flags)) {
+ /* Barrier: read flag before error */
+ ret = READ_ONCE(server->create_error);
+ afs_put_server(cell->net, server, afs_server_trace_unuse_create_fail);
+ server = NULL;
+ goto out;
+ }
-/*
- * Set the server timer to fire after a given delay, assuming it's not already
- * set for an earlier time.
- */
-static void afs_set_server_timer(struct afs_net *net, time64_t delay)
-{
- if (net->live) {
- afs_inc_servers_outstanding(net);
- if (timer_reduce(&net->fs_timer, jiffies + delay * HZ))
- afs_dec_servers_outstanding(net);
+ ret = 0;
+ goto out;
+
+create_failed:
+ down_write(&cell->fs_lock);
+
+ WRITE_ONCE(server->create_error, ret);
+ smp_wmb(); /* Barrier: set error before flag. */
+ set_bit(AFS_SERVER_FL_UNCREATED, &server->flags);
+
+ clear_and_wake_up_bit(AFS_SERVER_FL_CREATING, &server->flags);
+
+ if (test_bit(AFS_SERVER_FL_UNCREATED, &server->flags)) {
+ clear_bit(AFS_SERVER_FL_UNCREATED, &server->flags);
+ creating = true;
}
+ afs_unuse_server(cell->net, server, afs_server_trace_unuse_create_fail);
+ server = NULL;
+
+ up_write(&cell->fs_lock);
+ goto out;
}
/*
- * Server management timer. We have an increment on fs_outstanding that we
- * need to pass along to the work item.
+ * Set/reduce a server's timer.
*/
-void afs_servers_timer(struct timer_list *timer)
+static void afs_set_server_timer(struct afs_server *server, unsigned int delay_secs)
{
- struct afs_net *net = container_of(timer, struct afs_net, fs_timer);
-
- _enter("");
- if (!queue_work(afs_wq, &net->fs_manager))
- afs_dec_servers_outstanding(net);
+ mod_timer(&server->timer, jiffies + delay_secs * HZ);
}
/*
@@ -329,32 +305,20 @@ struct afs_server *afs_get_server(struct
}
/*
- * Try to get a reference on a server object.
+ * Get an active count on a server object and maybe remove from the inactive
+ * list.
*/
-static struct afs_server *afs_maybe_use_server(struct afs_server *server,
- enum afs_server_trace reason)
-{
- unsigned int a;
- int r;
-
- if (!__refcount_inc_not_zero(&server->ref, &r))
- return NULL;
-
- a = atomic_inc_return(&server->active);
- trace_afs_server(server->debug_id, r + 1, a, reason);
- return server;
-}
-
-/*
- * Get an active count on a server object.
- */
-struct afs_server *afs_use_server(struct afs_server *server, enum afs_server_trace reason)
+struct afs_server *afs_use_server(struct afs_server *server, bool activate,
+ enum afs_server_trace reason)
{
unsigned int a;
int r;
__refcount_inc(&server->ref, &r);
a = atomic_inc_return(&server->active);
+ if (a == 1 && activate &&
+ !test_bit(AFS_SERVER_FL_EXPIRED, &server->flags))
+ del_timer(&server->timer);
trace_afs_server(server->debug_id, r + 1, a, reason);
return server;
@@ -388,13 +352,16 @@ void afs_put_server(struct afs_net *net,
void afs_unuse_server_notime(struct afs_net *net, struct afs_server *server,
enum afs_server_trace reason)
{
- if (server) {
- unsigned int active = atomic_dec_return(&server->active);
+ if (!server)
+ return;
- if (active == 0)
- afs_set_server_timer(net, afs_server_gc_delay);
- afs_put_server(net, server, reason);
+ if (atomic_dec_and_test(&server->active)) {
+ if (test_bit(AFS_SERVER_FL_EXPIRED, &server->flags) ||
+ READ_ONCE(server->cell->state) >= AFS_CELL_FAILED)
+ schedule_work(&server->destroyer);
}
+
+ afs_put_server(net, server, reason);
}
/*
@@ -403,10 +370,22 @@ void afs_unuse_server_notime(struct afs_
void afs_unuse_server(struct afs_net *net, struct afs_server *server,
enum afs_server_trace reason)
{
- if (server) {
- server->unuse_time = ktime_get_real_seconds();
- afs_unuse_server_notime(net, server, reason);
+ if (!server)
+ return;
+
+ if (atomic_dec_and_test(&server->active)) {
+ if (!test_bit(AFS_SERVER_FL_EXPIRED, &server->flags) &&
+ READ_ONCE(server->cell->state) < AFS_CELL_FAILED) {
+ time64_t unuse_time = ktime_get_real_seconds();
+
+ server->unuse_time = unuse_time;
+ afs_set_server_timer(server, afs_server_gc_delay);
+ } else {
+ schedule_work(&server->destroyer);
+ }
}
+
+ afs_put_server(net, server, reason);
}
static void afs_server_rcu(struct rcu_head *rcu)
@@ -436,166 +415,119 @@ static void afs_give_up_callbacks(struct
}
/*
- * destroy a dead server
+ * Check to see if the server record has expired.
*/
-static void afs_destroy_server(struct afs_net *net, struct afs_server *server)
+static bool afs_has_server_expired(const struct afs_server *server)
{
- struct afs_endpoint_state *estate;
+ time64_t expires_at;
- if (test_bit(AFS_SERVER_FL_MAY_HAVE_CB, &server->flags))
- afs_give_up_callbacks(net, server);
+ if (atomic_read(&server->active))
+ return false;
- /* Unbind the rxrpc_peer records from the server. */
- estate = rcu_access_pointer(server->endpoint_state);
- if (estate)
- afs_set_peer_appdata(server, estate->addresses, NULL);
+ if (server->cell->net->live ||
+ server->cell->state >= AFS_CELL_FAILED) {
+ trace_afs_server(server->debug_id, refcount_read(&server->ref),
+ 0, afs_server_trace_purging);
+ return true;
+ }
- afs_put_server(net, server, afs_server_trace_destroy);
+ expires_at = server->unuse_time;
+ if (!test_bit(AFS_SERVER_FL_VL_FAIL, &server->flags) &&
+ !test_bit(AFS_SERVER_FL_NOT_FOUND, &server->flags))
+ expires_at += afs_server_gc_delay;
+
+ return ktime_get_real_seconds() > expires_at;
}
/*
- * Garbage collect any expired servers.
+ * Remove a server record from it's parent cell's database.
*/
-static void afs_gc_servers(struct afs_net *net, struct afs_server *gc_list)
+static bool afs_remove_server_from_cell(struct afs_server *server)
{
- struct afs_server *server, *next, *prev;
- int active;
+ struct afs_cell *cell = server->cell;
- while ((server = gc_list)) {
- gc_list = server->gc_next;
-
- write_seqlock(&net->fs_lock);
-
- active = atomic_read(&server->active);
- if (active == 0) {
- trace_afs_server(server->debug_id, refcount_read(&server->ref),
- active, afs_server_trace_gc);
- next = rcu_dereference_protected(
- server->uuid_next, lockdep_is_held(&net->fs_lock.lock));
- prev = server->uuid_prev;
- if (!prev) {
- /* The one at the front is in the tree */
- if (!next) {
- rb_erase(&server->uuid_rb, &net->fs_servers);
- } else {
- rb_replace_node_rcu(&server->uuid_rb,
- &next->uuid_rb,
- &net->fs_servers);
- next->uuid_prev = NULL;
- }
- } else {
- /* This server is not at the front */
- rcu_assign_pointer(prev->uuid_next, next);
- if (next)
- next->uuid_prev = prev;
- }
-
- list_del(&server->probe_link);
- hlist_del_rcu(&server->proc_link);
- if (!hlist_unhashed(&server->addr_link))
- hlist_del_rcu(&server->addr_link);
- }
- write_sequnlock(&net->fs_lock);
+ down_write(&cell->fs_lock);
- if (active == 0)
- afs_destroy_server(net, server);
+ if (!afs_has_server_expired(server)) {
+ up_write(&cell->fs_lock);
+ return false;
}
+
+ set_bit(AFS_SERVER_FL_EXPIRED, &server->flags);
+ _debug("expire %pU %u", &server->uuid, atomic_read(&server->active));
+ afs_see_server(server, afs_server_trace_see_expired);
+ rb_erase(&server->uuid_rb, &cell->fs_servers);
+ up_write(&cell->fs_lock);
+ return true;
}
-/*
- * Manage the records of servers known to be within a network namespace. This
- * includes garbage collecting unused servers.
- *
- * Note also that we were given an increment on net->servers_outstanding by
- * whoever queued us that we need to deal with before returning.
- */
-void afs_manage_servers(struct work_struct *work)
+static void afs_server_destroyer(struct work_struct *work)
{
- struct afs_net *net = container_of(work, struct afs_net, fs_manager);
- struct afs_server *gc_list = NULL;
- struct rb_node *cursor;
- time64_t now = ktime_get_real_seconds(), next_manage = TIME64_MAX;
- bool purging = !net->live;
+ struct afs_endpoint_state *estate;
+ struct afs_server *server = container_of(work, struct afs_server, destroyer);
+ struct afs_net *net = server->cell->net;
- _enter("");
+ afs_see_server(server, afs_server_trace_see_destroyer);
- /* Trawl the server list looking for servers that have expired from
- * lack of use.
- */
- read_seqlock_excl(&net->fs_lock);
+ if (test_bit(AFS_SERVER_FL_EXPIRED, &server->flags))
+ return;
- for (cursor = rb_first(&net->fs_servers); cursor; cursor = rb_next(cursor)) {
- struct afs_server *server =
- rb_entry(cursor, struct afs_server, uuid_rb);
- int active = atomic_read(&server->active);
-
- _debug("manage %pU %u", &server->uuid, active);
-
- if (purging) {
- trace_afs_server(server->debug_id, refcount_read(&server->ref),
- active, afs_server_trace_purging);
- if (active != 0)
- pr_notice("Can't purge s=%08x\n", server->debug_id);
- }
+ if (!afs_remove_server_from_cell(server))
+ return;
- if (active == 0) {
- time64_t expire_at = server->unuse_time;
+ timer_shutdown_sync(&server->timer);
+ cancel_work(&server->destroyer);
- if (!test_bit(AFS_SERVER_FL_VL_FAIL, &server->flags) &&
- !test_bit(AFS_SERVER_FL_NOT_FOUND, &server->flags))
- expire_at += afs_server_gc_delay;
- if (purging || expire_at <= now) {
- server->gc_next = gc_list;
- gc_list = server;
- } else if (expire_at < next_manage) {
- next_manage = expire_at;
- }
- }
- }
+ if (test_bit(AFS_SERVER_FL_MAY_HAVE_CB, &server->flags))
+ afs_give_up_callbacks(net, server);
- read_sequnlock_excl(&net->fs_lock);
+ /* Unbind the rxrpc_peer records from the server. */
+ estate = rcu_access_pointer(server->endpoint_state);
+ if (estate)
+ afs_set_peer_appdata(server, estate->addresses, NULL);
- /* Update the timer on the way out. We have to pass an increment on
- * servers_outstanding in the namespace that we are in to the timer or
- * the work scheduler.
- */
- if (!purging && next_manage < TIME64_MAX) {
- now = ktime_get_real_seconds();
+ write_seqlock(&net->fs_lock);
+ list_del_init(&server->probe_link);
+ if (!hlist_unhashed(&server->proc_link))
+ hlist_del_rcu(&server->proc_link);
+ write_sequnlock(&net->fs_lock);
- if (next_manage - now <= 0) {
- if (queue_work(afs_wq, &net->fs_manager))
- afs_inc_servers_outstanding(net);
- } else {
- afs_set_server_timer(net, next_manage - now);
- }
- }
+ afs_put_server(net, server, afs_server_trace_destroy);
+}
- afs_gc_servers(net, gc_list);
+static void afs_server_timer(struct timer_list *timer)
+{
+ struct afs_server *server = container_of(timer, struct afs_server, timer);
- afs_dec_servers_outstanding(net);
- _leave(" [%d]", atomic_read(&net->servers_outstanding));
+ afs_see_server(server, afs_server_trace_see_timer);
+ if (!test_bit(AFS_SERVER_FL_EXPIRED, &server->flags))
+ schedule_work(&server->destroyer);
}
-static void afs_queue_server_manager(struct afs_net *net)
+/*
+ * Wake up all the servers in a cell so that they can purge themselves.
+ */
+void afs_purge_servers(struct afs_cell *cell)
{
- afs_inc_servers_outstanding(net);
- if (!queue_work(afs_wq, &net->fs_manager))
- afs_dec_servers_outstanding(net);
+ struct afs_server *server;
+ struct rb_node *rb;
+
+ down_read(&cell->fs_lock);
+ for (rb = rb_first(&cell->fs_servers); rb; rb = rb_next(rb)) {
+ server = rb_entry(rb, struct afs_server, uuid_rb);
+ afs_see_server(server, afs_server_trace_see_purge);
+ schedule_work(&server->destroyer);
+ }
+ up_read(&cell->fs_lock);
}
/*
- * Purge list of servers.
+ * Wait for outstanding servers.
*/
-void afs_purge_servers(struct afs_net *net)
+void afs_wait_for_servers(struct afs_net *net)
{
_enter("");
- if (del_timer_sync(&net->fs_timer))
- afs_dec_servers_outstanding(net);
-
- afs_queue_server_manager(net);
-
- _debug("wait");
atomic_dec(&net->servers_outstanding);
wait_var_event(&net->servers_outstanding,
!atomic_read(&net->servers_outstanding));
@@ -619,7 +551,7 @@ static noinline bool afs_update_server_r
atomic_read(&server->active),
afs_server_trace_update);
- alist = afs_vl_lookup_addrs(op->volume->cell, op->key, &server->uuid);
+ alist = afs_vl_lookup_addrs(server, op->key);
if (IS_ERR(alist)) {
rcu_read_lock();
estate = rcu_dereference(server->endpoint_state);
--- a/fs/afs/server_list.c
+++ b/fs/afs/server_list.c
@@ -97,8 +97,8 @@ struct afs_server_list *afs_alloc_server
break;
if (j < slist->nr_servers) {
if (slist->servers[j].server == server) {
- afs_unuse_server(volume->cell->net, server,
- afs_server_trace_unuse_slist_isort);
+ afs_unuse_server_notime(volume->cell->net, server,
+ afs_server_trace_unuse_slist_isort);
continue;
}
--- a/include/trace/events/afs.h
+++ b/include/trace/events/afs.h
@@ -127,7 +127,6 @@ enum yfs_cm_operation {
E_(afs_call_trace_work, "QUEUE")
#define afs_server_traces \
- EM(afs_server_trace_alloc, "ALLOC ") \
EM(afs_server_trace_callback, "CALLBACK ") \
EM(afs_server_trace_destroy, "DESTROY ") \
EM(afs_server_trace_free, "FREE ") \
@@ -137,12 +136,14 @@ enum yfs_cm_operation {
EM(afs_server_trace_purging, "PURGE ") \
EM(afs_server_trace_put_cbi, "PUT cbi ") \
EM(afs_server_trace_put_probe, "PUT probe") \
+ EM(afs_server_trace_see_destroyer, "SEE destr") \
EM(afs_server_trace_see_expired, "SEE expd ") \
+ EM(afs_server_trace_see_purge, "SEE purge") \
+ EM(afs_server_trace_see_timer, "SEE timer") \
EM(afs_server_trace_unuse_call, "UNU call ") \
EM(afs_server_trace_unuse_create_fail, "UNU cfail") \
EM(afs_server_trace_unuse_slist, "UNU slist") \
EM(afs_server_trace_unuse_slist_isort, "UNU isort") \
- EM(afs_server_trace_unuse_uuid_rsq, "PUT u-req") \
EM(afs_server_trace_update, "UPDATE ") \
EM(afs_server_trace_use_by_uuid, "USE uuid ") \
EM(afs_server_trace_use_cm_call, "USE cm-cl") \
@@ -229,7 +230,7 @@ enum yfs_cm_operation {
EM(afs_alist_trace_put_getaddru, "PUT GtAdrU") \
EM(afs_alist_trace_put_parse_empty, "PUT p-empt") \
EM(afs_alist_trace_put_parse_error, "PUT p-err ") \
- EM(afs_alist_trace_put_server_dup, "PUT sv-dup") \
+ EM(afs_alist_trace_put_server_create, "PUT sv-crt") \
EM(afs_alist_trace_put_server_oom, "PUT sv-oom") \
EM(afs_alist_trace_put_server_update, "PUT sv-upd") \
EM(afs_alist_trace_put_vlgetcaps, "PUT vgtcap") \
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 580/602] afs: Simplify cell record handling
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (578 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 579/602] afs: Fix afs_server ref accounting Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 581/602] afs: Fix dynamic lookup to fail on cell lookup failure Greg Kroah-Hartman
` (25 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Howells, Marc Dionne,
linux-afs, linux-fsdevel, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <dhowells@redhat.com>
[ Upstream commit e2c2cb8ef07affd9f69497ea128fa801240fdf32 ]
Simplify afs_cell record handling to avoid very occasional races that cause
module removal to hang (it waits for all cell records to be removed).
There are two things that particularly contribute to the difficulty:
firstly, the code tries to pass a ref on the cell to the cell's maintenance
work item (which gets awkward if the work item is already queued); and,
secondly, there's an overall cell manager that tries to use just one timer
for the entire cell collection (to avoid having loads of timers). However,
both of these are probably unnecessarily restrictive.
To simplify this, the following changes are made:
(1) The cell record collection manager is removed. Each cell record
manages itself individually.
(2) Each afs_cell is given a second work item (cell->destroyer) that is
queued when its refcount reaches zero. This is not done in the
context of the putting thread as it might be in an inconvenient place
to sleep.
(3) Each afs_cell is given its own timer. The timer is used to expire the
cell record after a period of unuse if not otherwise pinned and can
also be used for other maintenance tasks if necessary (of which there
are currently none as DNS refresh is triggered by filesystem
operations).
(4) The afs_cell manager work item (cell->manager) is no longer given a
ref on the cell when queued; rather, the manager must be deleted.
This does away with the need to deal with the consequences of losing a
race to queue cell->manager. Clean up of extra queuing is deferred to
the destroyer.
(5) The cell destroyer work item makes sure the cell timer is removed and
that the normal cell work is cancelled before farming the actual
destruction off to RCU.
(6) When a network namespace is destroyed or the kafs module is unloaded,
it's now a simple matter of marking the namespace as dead then just
waking up all the cell work items. They will then remove and destroy
themselves once all remaining activity counts and/or a ref counts are
dropped. This makes sure that all server records are dropped first.
(7) The cell record state set is reduced to just four states: SETTING_UP,
ACTIVE, REMOVING and DEAD. The record persists in the active state
even when it's not being used until the time comes to remove it rather
than downgrading it to an inactive state from whence it can be
restored.
This means that the cell still appears in /proc and /afs when not in
use until it switches to the REMOVING state - at which point it is
removed.
Note that the REMOVING state is included so that someone wanting to
resurrect the cell record is forced to wait whilst the cell is torn
down in that state. Once it's in the DEAD state, it has been removed
from net->cells tree and is no longer findable and can be replaced.
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
cc: linux-fsdevel@vger.kernel.org
Link: https://lore.kernel.org/r/20250224234154.2014840-16-dhowells@redhat.com/ # v1
Link: https://lore.kernel.org/r/20250310094206.801057-12-dhowells@redhat.com/ # v4
Stable-dep-of: 330e2c514823 ("afs: Fix dynamic lookup to fail on cell lookup failure")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/afs/cell.c | 404 ++++++++++++++++++---------------------------
fs/afs/dynroot.c | 4
fs/afs/internal.h | 16 -
fs/afs/main.c | 3
fs/afs/server.c | 8
fs/afs/vl_rotate.c | 2
include/trace/events/afs.h | 23 +-
7 files changed, 187 insertions(+), 273 deletions(-)
--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -20,8 +20,9 @@ static unsigned __read_mostly afs_cell_m
static unsigned __read_mostly afs_cell_max_ttl = 24 * 60 * 60;
static atomic_t cell_debug_id;
-static void afs_queue_cell_manager(struct afs_net *);
-static void afs_manage_cell_work(struct work_struct *);
+static void afs_cell_timer(struct timer_list *timer);
+static void afs_destroy_cell_work(struct work_struct *work);
+static void afs_manage_cell_work(struct work_struct *work);
static void afs_dec_cells_outstanding(struct afs_net *net)
{
@@ -29,19 +30,11 @@ static void afs_dec_cells_outstanding(st
wake_up_var(&net->cells_outstanding);
}
-/*
- * Set the cell timer to fire after a given delay, assuming it's not already
- * set for an earlier time.
- */
-static void afs_set_cell_timer(struct afs_net *net, time64_t delay)
+static void afs_set_cell_state(struct afs_cell *cell, enum afs_cell_state state)
{
- if (net->live) {
- atomic_inc(&net->cells_outstanding);
- if (timer_reduce(&net->cells_timer, jiffies + delay * HZ))
- afs_dec_cells_outstanding(net);
- } else {
- afs_queue_cell_manager(net);
- }
+ smp_store_release(&cell->state, state); /* Commit cell changes before state */
+ smp_wmb(); /* Set cell state before task state */
+ wake_up_var(&cell->state);
}
/*
@@ -116,7 +109,7 @@ static struct afs_cell *afs_alloc_cell(s
const char *name, unsigned int namelen,
const char *addresses)
{
- struct afs_vlserver_list *vllist;
+ struct afs_vlserver_list *vllist = NULL;
struct afs_cell *cell;
int i, ret;
@@ -163,7 +156,9 @@ static struct afs_cell *afs_alloc_cell(s
cell->net = net;
refcount_set(&cell->ref, 1);
atomic_set(&cell->active, 0);
+ INIT_WORK(&cell->destroyer, afs_destroy_cell_work);
INIT_WORK(&cell->manager, afs_manage_cell_work);
+ timer_setup(&cell->management_timer, afs_cell_timer, 0);
init_rwsem(&cell->vs_lock);
cell->volumes = RB_ROOT;
INIT_HLIST_HEAD(&cell->proc_volumes);
@@ -220,6 +215,7 @@ parse_failed:
if (ret == -EINVAL)
printk(KERN_ERR "kAFS: bad VL server IP address\n");
error:
+ afs_put_vlserverlist(cell->net, vllist);
kfree(cell->name - 1);
kfree(cell);
_leave(" = %d", ret);
@@ -296,26 +292,28 @@ struct afs_cell *afs_lookup_cell(struct
cell = candidate;
candidate = NULL;
- atomic_set(&cell->active, 2);
- trace_afs_cell(cell->debug_id, refcount_read(&cell->ref), 2, afs_cell_trace_insert);
+ afs_use_cell(cell, trace);
rb_link_node_rcu(&cell->net_node, parent, pp);
rb_insert_color(&cell->net_node, &net->cells);
up_write(&net->cells_lock);
- afs_queue_cell(cell, afs_cell_trace_get_queue_new);
+ afs_queue_cell(cell, afs_cell_trace_queue_new);
wait_for_cell:
- trace_afs_cell(cell->debug_id, refcount_read(&cell->ref), atomic_read(&cell->active),
- afs_cell_trace_wait);
_debug("wait_for_cell");
- wait_var_event(&cell->state,
- ({
- state = smp_load_acquire(&cell->state); /* vs error */
- state == AFS_CELL_ACTIVE || state == AFS_CELL_REMOVED;
- }));
+ state = smp_load_acquire(&cell->state); /* vs error */
+ if (state != AFS_CELL_ACTIVE &&
+ state != AFS_CELL_DEAD) {
+ afs_see_cell(cell, afs_cell_trace_wait);
+ wait_var_event(&cell->state,
+ ({
+ state = smp_load_acquire(&cell->state); /* vs error */
+ state == AFS_CELL_ACTIVE || state == AFS_CELL_DEAD;
+ }));
+ }
/* Check the state obtained from the wait check. */
- if (state == AFS_CELL_REMOVED) {
+ if (state == AFS_CELL_DEAD) {
ret = cell->error;
goto error;
}
@@ -397,7 +395,6 @@ int afs_cell_init(struct afs_net *net, c
/* install the new cell */
down_write(&net->cells_lock);
- afs_see_cell(new_root, afs_cell_trace_see_ws);
old_root = rcu_replace_pointer(net->ws_cell, new_root,
lockdep_is_held(&net->cells_lock));
up_write(&net->cells_lock);
@@ -532,30 +529,14 @@ static void afs_cell_destroy(struct rcu_
_leave(" [destroyed]");
}
-/*
- * Queue the cell manager.
- */
-static void afs_queue_cell_manager(struct afs_net *net)
-{
- int outstanding = atomic_inc_return(&net->cells_outstanding);
-
- _enter("%d", outstanding);
-
- if (!queue_work(afs_wq, &net->cells_manager))
- afs_dec_cells_outstanding(net);
-}
-
-/*
- * Cell management timer. We have an increment on cells_outstanding that we
- * need to pass along to the work item.
- */
-void afs_cells_timer(struct timer_list *timer)
+static void afs_destroy_cell_work(struct work_struct *work)
{
- struct afs_net *net = container_of(timer, struct afs_net, cells_timer);
+ struct afs_cell *cell = container_of(work, struct afs_cell, destroyer);
- _enter("");
- if (!queue_work(afs_wq, &net->cells_manager))
- afs_dec_cells_outstanding(net);
+ afs_see_cell(cell, afs_cell_trace_destroy);
+ timer_delete_sync(&cell->management_timer);
+ cancel_work_sync(&cell->manager);
+ call_rcu(&cell->rcu, afs_cell_destroy);
}
/*
@@ -587,7 +568,7 @@ void afs_put_cell(struct afs_cell *cell,
if (zero) {
a = atomic_read(&cell->active);
WARN(a != 0, "Cell active count %u > 0\n", a);
- call_rcu(&cell->rcu, afs_cell_destroy);
+ WARN_ON(!queue_work(afs_wq, &cell->destroyer));
}
}
}
@@ -599,10 +580,9 @@ struct afs_cell *afs_use_cell(struct afs
{
int r, a;
- r = refcount_read(&cell->ref);
- WARN_ON(r == 0);
+ __refcount_inc(&cell->ref, &r);
a = atomic_inc_return(&cell->active);
- trace_afs_cell(cell->debug_id, r, a, reason);
+ trace_afs_cell(cell->debug_id, r + 1, a, reason);
return cell;
}
@@ -614,6 +594,7 @@ void afs_unuse_cell(struct afs_cell *cel
{
unsigned int debug_id;
time64_t now, expire_delay;
+ bool zero;
int r, a;
if (!cell)
@@ -628,13 +609,15 @@ void afs_unuse_cell(struct afs_cell *cel
expire_delay = afs_cell_gc_delay;
debug_id = cell->debug_id;
- r = refcount_read(&cell->ref);
a = atomic_dec_return(&cell->active);
- trace_afs_cell(debug_id, r, a, reason);
- WARN_ON(a == 0);
- if (a == 1)
+ if (!a)
/* 'cell' may now be garbage collected. */
- afs_set_cell_timer(cell->net, expire_delay);
+ afs_set_cell_timer(cell, expire_delay);
+
+ zero = __refcount_dec_and_test(&cell->ref, &r);
+ trace_afs_cell(debug_id, r - 1, a, reason);
+ if (zero)
+ WARN_ON(!queue_work(afs_wq, &cell->destroyer));
}
/*
@@ -654,9 +637,27 @@ void afs_see_cell(struct afs_cell *cell,
*/
void afs_queue_cell(struct afs_cell *cell, enum afs_cell_trace reason)
{
- afs_get_cell(cell, reason);
- if (!queue_work(afs_wq, &cell->manager))
- afs_put_cell(cell, afs_cell_trace_put_queue_fail);
+ queue_work(afs_wq, &cell->manager);
+}
+
+/*
+ * Cell-specific management timer.
+ */
+static void afs_cell_timer(struct timer_list *timer)
+{
+ struct afs_cell *cell = container_of(timer, struct afs_cell, management_timer);
+
+ afs_see_cell(cell, afs_cell_trace_see_mgmt_timer);
+ if (refcount_read(&cell->ref) > 0 && cell->net->live)
+ queue_work(afs_wq, &cell->manager);
+}
+
+/*
+ * Set/reduce the cell timer.
+ */
+void afs_set_cell_timer(struct afs_cell *cell, unsigned int delay_secs)
+{
+ timer_reduce(&cell->management_timer, jiffies + delay_secs * HZ);
}
/*
@@ -739,212 +740,125 @@ static void afs_deactivate_cell(struct a
_leave("");
}
+static bool afs_has_cell_expired(struct afs_cell *cell, time64_t *_next_manage)
+{
+ const struct afs_vlserver_list *vllist;
+ time64_t expire_at = cell->last_inactive;
+ time64_t now = ktime_get_real_seconds();
+
+ if (atomic_read(&cell->active))
+ return false;
+ if (!cell->net->live)
+ return true;
+
+ vllist = rcu_dereference_protected(cell->vl_servers, true);
+ if (vllist && vllist->nr_servers > 0)
+ expire_at += afs_cell_gc_delay;
+
+ if (expire_at <= now)
+ return true;
+ if (expire_at < *_next_manage)
+ *_next_manage = expire_at;
+ return false;
+}
+
/*
* Manage a cell record, initialising and destroying it, maintaining its DNS
* records.
*/
-static void afs_manage_cell(struct afs_cell *cell)
+static bool afs_manage_cell(struct afs_cell *cell)
{
struct afs_net *net = cell->net;
- int ret, active;
+ time64_t next_manage = TIME64_MAX;
+ int ret;
_enter("%s", cell->name);
-again:
_debug("state %u", cell->state);
switch (cell->state) {
- case AFS_CELL_INACTIVE:
- case AFS_CELL_FAILED:
- down_write(&net->cells_lock);
- active = 1;
- if (atomic_try_cmpxchg_relaxed(&cell->active, &active, 0)) {
- rb_erase(&cell->net_node, &net->cells);
- trace_afs_cell(cell->debug_id, refcount_read(&cell->ref), 0,
- afs_cell_trace_unuse_delete);
- smp_store_release(&cell->state, AFS_CELL_REMOVED);
- }
- up_write(&net->cells_lock);
- if (cell->state == AFS_CELL_REMOVED) {
- wake_up_var(&cell->state);
- goto final_destruction;
- }
- if (cell->state == AFS_CELL_FAILED)
- goto done;
- smp_store_release(&cell->state, AFS_CELL_UNSET);
- wake_up_var(&cell->state);
- goto again;
-
- case AFS_CELL_UNSET:
- smp_store_release(&cell->state, AFS_CELL_ACTIVATING);
- wake_up_var(&cell->state);
- goto again;
+ case AFS_CELL_SETTING_UP:
+ goto set_up_cell;
+ case AFS_CELL_ACTIVE:
+ goto cell_is_active;
+ case AFS_CELL_REMOVING:
+ WARN_ON_ONCE(1);
+ return false;
+ case AFS_CELL_DEAD:
+ return false;
+ default:
+ _debug("bad state %u", cell->state);
+ WARN_ON_ONCE(1); /* Unhandled state */
+ return false;
+ }
- case AFS_CELL_ACTIVATING:
- ret = afs_activate_cell(net, cell);
- if (ret < 0)
- goto activation_failed;
+set_up_cell:
+ ret = afs_activate_cell(net, cell);
+ if (ret < 0) {
+ cell->error = ret;
+ goto remove_cell;
+ }
- smp_store_release(&cell->state, AFS_CELL_ACTIVE);
- wake_up_var(&cell->state);
- goto again;
+ afs_set_cell_state(cell, AFS_CELL_ACTIVE);
- case AFS_CELL_ACTIVE:
- if (atomic_read(&cell->active) > 1) {
- if (test_and_clear_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags)) {
- ret = afs_update_cell(cell);
- if (ret < 0)
- cell->error = ret;
- }
- goto done;
- }
- smp_store_release(&cell->state, AFS_CELL_DEACTIVATING);
- wake_up_var(&cell->state);
- goto again;
-
- case AFS_CELL_DEACTIVATING:
- if (atomic_read(&cell->active) > 1)
- goto reverse_deactivation;
- afs_deactivate_cell(net, cell);
- smp_store_release(&cell->state, AFS_CELL_INACTIVE);
- wake_up_var(&cell->state);
- goto again;
+cell_is_active:
+ if (afs_has_cell_expired(cell, &next_manage))
+ goto remove_cell;
- case AFS_CELL_REMOVED:
- goto done;
+ if (test_and_clear_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags)) {
+ ret = afs_update_cell(cell);
+ if (ret < 0)
+ cell->error = ret;
+ }
- default:
- break;
+ if (next_manage < TIME64_MAX && cell->net->live) {
+ time64_t now = ktime_get_real_seconds();
+
+ if (next_manage - now <= 0)
+ afs_queue_cell(cell, afs_cell_trace_queue_again);
+ else
+ afs_set_cell_timer(cell, next_manage - now);
}
- _debug("bad state %u", cell->state);
- BUG(); /* Unhandled state */
+ _leave(" [done %u]", cell->state);
+ return false;
-activation_failed:
- cell->error = ret;
- afs_deactivate_cell(net, cell);
+remove_cell:
+ down_write(&net->cells_lock);
- smp_store_release(&cell->state, AFS_CELL_FAILED); /* vs error */
- wake_up_var(&cell->state);
- goto again;
+ if (atomic_read(&cell->active)) {
+ up_write(&net->cells_lock);
+ goto cell_is_active;
+ }
-reverse_deactivation:
- smp_store_release(&cell->state, AFS_CELL_ACTIVE);
- wake_up_var(&cell->state);
- _leave(" [deact->act]");
- return;
+ /* Make sure that the expiring server records are going to see the fact
+ * that the cell is caput.
+ */
+ afs_set_cell_state(cell, AFS_CELL_REMOVING);
-done:
- _leave(" [done %u]", cell->state);
- return;
+ afs_deactivate_cell(net, cell);
+ afs_purge_servers(cell);
+
+ rb_erase(&cell->net_node, &net->cells);
+ afs_see_cell(cell, afs_cell_trace_unuse_delete);
+ up_write(&net->cells_lock);
-final_destruction:
/* The root volume is pinning the cell */
afs_put_volume(cell->root_volume, afs_volume_trace_put_cell_root);
cell->root_volume = NULL;
- afs_purge_servers(cell);
- afs_put_cell(cell, afs_cell_trace_put_destroy);
+
+ afs_set_cell_state(cell, AFS_CELL_DEAD);
+ return true;
}
static void afs_manage_cell_work(struct work_struct *work)
{
struct afs_cell *cell = container_of(work, struct afs_cell, manager);
+ bool final_put;
- afs_manage_cell(cell);
- afs_put_cell(cell, afs_cell_trace_put_queue_work);
-}
-
-/*
- * Manage the records of cells known to a network namespace. This includes
- * updating the DNS records and garbage collecting unused cells that were
- * automatically added.
- *
- * Note that constructed cell records may only be removed from net->cells by
- * this work item, so it is safe for this work item to stash a cursor pointing
- * into the tree and then return to caller (provided it skips cells that are
- * still under construction).
- *
- * Note also that we were given an increment on net->cells_outstanding by
- * whoever queued us that we need to deal with before returning.
- */
-void afs_manage_cells(struct work_struct *work)
-{
- struct afs_net *net = container_of(work, struct afs_net, cells_manager);
- struct rb_node *cursor;
- time64_t now = ktime_get_real_seconds(), next_manage = TIME64_MAX;
- bool purging = !net->live;
-
- _enter("");
-
- /* Trawl the cell database looking for cells that have expired from
- * lack of use and cells whose DNS results have expired and dispatch
- * their managers.
- */
- down_read(&net->cells_lock);
-
- for (cursor = rb_first(&net->cells); cursor; cursor = rb_next(cursor)) {
- struct afs_cell *cell =
- rb_entry(cursor, struct afs_cell, net_node);
- unsigned active;
- bool sched_cell = false;
-
- active = atomic_read(&cell->active);
- trace_afs_cell(cell->debug_id, refcount_read(&cell->ref),
- active, afs_cell_trace_manage);
-
- ASSERTCMP(active, >=, 1);
-
- if (purging) {
- if (test_and_clear_bit(AFS_CELL_FL_NO_GC, &cell->flags)) {
- active = atomic_dec_return(&cell->active);
- trace_afs_cell(cell->debug_id, refcount_read(&cell->ref),
- active, afs_cell_trace_unuse_pin);
- }
- }
-
- if (active == 1) {
- struct afs_vlserver_list *vllist;
- time64_t expire_at = cell->last_inactive;
-
- read_lock(&cell->vl_servers_lock);
- vllist = rcu_dereference_protected(
- cell->vl_servers,
- lockdep_is_held(&cell->vl_servers_lock));
- if (vllist->nr_servers > 0)
- expire_at += afs_cell_gc_delay;
- read_unlock(&cell->vl_servers_lock);
- if (purging || expire_at <= now)
- sched_cell = true;
- else if (expire_at < next_manage)
- next_manage = expire_at;
- }
-
- if (!purging) {
- if (test_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags))
- sched_cell = true;
- }
-
- if (sched_cell)
- afs_queue_cell(cell, afs_cell_trace_get_queue_manage);
- }
-
- up_read(&net->cells_lock);
-
- /* Update the timer on the way out. We have to pass an increment on
- * cells_outstanding in the namespace that we are in to the timer or
- * the work scheduler.
- */
- if (!purging && next_manage < TIME64_MAX) {
- now = ktime_get_real_seconds();
-
- if (next_manage - now <= 0) {
- if (queue_work(afs_wq, &net->cells_manager))
- atomic_inc(&net->cells_outstanding);
- } else {
- afs_set_cell_timer(net, next_manage - now);
- }
- }
-
- afs_dec_cells_outstanding(net);
- _leave(" [%d]", atomic_read(&net->cells_outstanding));
+ afs_see_cell(cell, afs_cell_trace_manage);
+ final_put = afs_manage_cell(cell);
+ afs_see_cell(cell, afs_cell_trace_managed);
+ if (final_put)
+ afs_put_cell(cell, afs_cell_trace_put_final);
}
/*
@@ -953,6 +867,7 @@ void afs_manage_cells(struct work_struct
void afs_cell_purge(struct afs_net *net)
{
struct afs_cell *ws;
+ struct rb_node *cursor;
_enter("");
@@ -962,12 +877,19 @@ void afs_cell_purge(struct afs_net *net)
up_write(&net->cells_lock);
afs_unuse_cell(ws, afs_cell_trace_unuse_ws);
- _debug("del timer");
- if (del_timer_sync(&net->cells_timer))
- atomic_dec(&net->cells_outstanding);
+ _debug("kick cells");
+ down_read(&net->cells_lock);
+ for (cursor = rb_first(&net->cells); cursor; cursor = rb_next(cursor)) {
+ struct afs_cell *cell = rb_entry(cursor, struct afs_cell, net_node);
+
+ afs_see_cell(cell, afs_cell_trace_purge);
- _debug("kick mgr");
- afs_queue_cell_manager(net);
+ if (test_and_clear_bit(AFS_CELL_FL_NO_GC, &cell->flags))
+ afs_unuse_cell(cell, afs_cell_trace_unuse_pin);
+
+ afs_queue_cell(cell, afs_cell_trace_queue_purge);
+ }
+ up_read(&net->cells_lock);
_debug("wait");
wait_var_event(&net->cells_outstanding,
--- a/fs/afs/dynroot.c
+++ b/fs/afs/dynroot.c
@@ -293,8 +293,8 @@ static int afs_dynroot_readdir_cells(str
cell = idr_get_next(&net->cells_dyn_ino, &ix);
if (!cell)
return 0;
- if (READ_ONCE(cell->state) == AFS_CELL_FAILED ||
- READ_ONCE(cell->state) == AFS_CELL_REMOVED) {
+ if (READ_ONCE(cell->state) == AFS_CELL_REMOVING ||
+ READ_ONCE(cell->state) == AFS_CELL_DEAD) {
ctx->pos += 2;
ctx->pos &= ~1;
continue;
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -304,8 +304,6 @@ struct afs_net {
struct rb_root cells;
struct idr cells_dyn_ino; /* cell->dynroot_ino mapping */
struct afs_cell __rcu *ws_cell;
- struct work_struct cells_manager;
- struct timer_list cells_timer;
atomic_t cells_outstanding;
struct rw_semaphore cells_lock;
struct mutex cells_alias_lock;
@@ -354,13 +352,10 @@ struct afs_net {
extern const char afs_init_sysname[];
enum afs_cell_state {
- AFS_CELL_UNSET,
- AFS_CELL_ACTIVATING,
+ AFS_CELL_SETTING_UP,
AFS_CELL_ACTIVE,
- AFS_CELL_DEACTIVATING,
- AFS_CELL_INACTIVE,
- AFS_CELL_FAILED,
- AFS_CELL_REMOVED,
+ AFS_CELL_REMOVING,
+ AFS_CELL_DEAD,
};
/*
@@ -391,7 +386,9 @@ struct afs_cell {
struct afs_cell *alias_of; /* The cell this is an alias of */
struct afs_volume *root_volume; /* The root.cell volume if there is one */
struct key *anonymous_key; /* anonymous user key for this cell */
+ struct work_struct destroyer; /* Destroyer for cell */
struct work_struct manager; /* Manager for init/deinit/dns */
+ struct timer_list management_timer; /* General management timer */
struct hlist_node proc_link; /* /proc cell list link */
time64_t dns_expiry; /* Time AFSDB/SRV record expires */
time64_t last_inactive; /* Time of last drop of usage count */
@@ -1047,8 +1044,7 @@ extern struct afs_cell *afs_get_cell(str
extern void afs_see_cell(struct afs_cell *, enum afs_cell_trace);
extern void afs_put_cell(struct afs_cell *, enum afs_cell_trace);
extern void afs_queue_cell(struct afs_cell *, enum afs_cell_trace);
-extern void afs_manage_cells(struct work_struct *);
-extern void afs_cells_timer(struct timer_list *);
+void afs_set_cell_timer(struct afs_cell *cell, unsigned int delay_secs);
extern void __net_exit afs_cell_purge(struct afs_net *);
/*
--- a/fs/afs/main.c
+++ b/fs/afs/main.c
@@ -78,9 +78,6 @@ static int __net_init afs_net_init(struc
net->cells = RB_ROOT;
idr_init(&net->cells_dyn_ino);
init_rwsem(&net->cells_lock);
- INIT_WORK(&net->cells_manager, afs_manage_cells);
- timer_setup(&net->cells_timer, afs_cells_timer, 0);
-
mutex_init(&net->cells_alias_lock);
mutex_init(&net->proc_cells_lock);
INIT_HLIST_HEAD(&net->proc_cells);
--- a/fs/afs/server.c
+++ b/fs/afs/server.c
@@ -103,7 +103,7 @@ static struct afs_server *afs_install_se
afs_get_cell(cell, afs_cell_trace_get_server);
exists:
- afs_use_server(server, true, afs_server_trace_get_install);
+ afs_use_server(server, true, afs_server_trace_use_install);
return server;
}
@@ -357,7 +357,7 @@ void afs_unuse_server_notime(struct afs_
if (atomic_dec_and_test(&server->active)) {
if (test_bit(AFS_SERVER_FL_EXPIRED, &server->flags) ||
- READ_ONCE(server->cell->state) >= AFS_CELL_FAILED)
+ READ_ONCE(server->cell->state) >= AFS_CELL_REMOVING)
schedule_work(&server->destroyer);
}
@@ -375,7 +375,7 @@ void afs_unuse_server(struct afs_net *ne
if (atomic_dec_and_test(&server->active)) {
if (!test_bit(AFS_SERVER_FL_EXPIRED, &server->flags) &&
- READ_ONCE(server->cell->state) < AFS_CELL_FAILED) {
+ READ_ONCE(server->cell->state) < AFS_CELL_REMOVING) {
time64_t unuse_time = ktime_get_real_seconds();
server->unuse_time = unuse_time;
@@ -425,7 +425,7 @@ static bool afs_has_server_expired(const
return false;
if (server->cell->net->live ||
- server->cell->state >= AFS_CELL_FAILED) {
+ server->cell->state >= AFS_CELL_REMOVING) {
trace_afs_server(server->debug_id, refcount_read(&server->ref),
0, afs_server_trace_purging);
return true;
--- a/fs/afs/vl_rotate.c
+++ b/fs/afs/vl_rotate.c
@@ -48,7 +48,7 @@ static bool afs_start_vl_iteration(struc
cell->dns_expiry <= ktime_get_real_seconds()) {
dns_lookup_count = smp_load_acquire(&cell->dns_lookup_count);
set_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags);
- afs_queue_cell(cell, afs_cell_trace_get_queue_dns);
+ afs_queue_cell(cell, afs_cell_trace_queue_dns);
if (cell->dns_source == DNS_RECORD_UNAVAILABLE) {
if (wait_var_event_interruptible(
--- a/include/trace/events/afs.h
+++ b/include/trace/events/afs.h
@@ -131,7 +131,6 @@ enum yfs_cm_operation {
EM(afs_server_trace_destroy, "DESTROY ") \
EM(afs_server_trace_free, "FREE ") \
EM(afs_server_trace_gc, "GC ") \
- EM(afs_server_trace_get_install, "GET inst ") \
EM(afs_server_trace_get_probe, "GET probe") \
EM(afs_server_trace_purging, "PURGE ") \
EM(afs_server_trace_put_cbi, "PUT cbi ") \
@@ -149,6 +148,7 @@ enum yfs_cm_operation {
EM(afs_server_trace_use_cm_call, "USE cm-cl") \
EM(afs_server_trace_use_get_caps, "USE gcaps") \
EM(afs_server_trace_use_give_up_cb, "USE gvupc") \
+ EM(afs_server_trace_use_install, "USE inst ") \
E_(afs_server_trace_wait_create, "WAIT crt ")
#define afs_volume_traces \
@@ -171,37 +171,36 @@ enum yfs_cm_operation {
#define afs_cell_traces \
EM(afs_cell_trace_alloc, "ALLOC ") \
+ EM(afs_cell_trace_destroy, "DESTROY ") \
EM(afs_cell_trace_free, "FREE ") \
EM(afs_cell_trace_get_atcell, "GET atcell") \
- EM(afs_cell_trace_get_queue_dns, "GET q-dns ") \
- EM(afs_cell_trace_get_queue_manage, "GET q-mng ") \
- EM(afs_cell_trace_get_queue_new, "GET q-new ") \
EM(afs_cell_trace_get_server, "GET server") \
EM(afs_cell_trace_get_vol, "GET vol ") \
- EM(afs_cell_trace_insert, "INSERT ") \
- EM(afs_cell_trace_manage, "MANAGE ") \
+ EM(afs_cell_trace_purge, "PURGE ") \
EM(afs_cell_trace_put_atcell, "PUT atcell") \
EM(afs_cell_trace_put_candidate, "PUT candid") \
- EM(afs_cell_trace_put_destroy, "PUT destry") \
- EM(afs_cell_trace_put_queue_work, "PUT q-work") \
- EM(afs_cell_trace_put_queue_fail, "PUT q-fail") \
+ EM(afs_cell_trace_put_final, "PUT final ") \
EM(afs_cell_trace_put_server, "PUT server") \
EM(afs_cell_trace_put_vol, "PUT vol ") \
+ EM(afs_cell_trace_queue_again, "QUE again ") \
+ EM(afs_cell_trace_queue_dns, "QUE dns ") \
+ EM(afs_cell_trace_queue_new, "QUE new ") \
+ EM(afs_cell_trace_queue_purge, "QUE purge ") \
+ EM(afs_cell_trace_manage, "MANAGE ") \
+ EM(afs_cell_trace_managed, "MANAGED ") \
EM(afs_cell_trace_see_source, "SEE source") \
- EM(afs_cell_trace_see_ws, "SEE ws ") \
+ EM(afs_cell_trace_see_mgmt_timer, "SEE mtimer") \
EM(afs_cell_trace_unuse_alias, "UNU alias ") \
EM(afs_cell_trace_unuse_check_alias, "UNU chk-al") \
EM(afs_cell_trace_unuse_delete, "UNU delete") \
EM(afs_cell_trace_unuse_dynroot_mntpt, "UNU dyn-mp") \
EM(afs_cell_trace_unuse_fc, "UNU fc ") \
- EM(afs_cell_trace_unuse_lookup, "UNU lookup") \
EM(afs_cell_trace_unuse_lookup_dynroot, "UNU lu-dyn") \
EM(afs_cell_trace_unuse_lookup_error, "UNU lu-err") \
EM(afs_cell_trace_unuse_mntpt, "UNU mntpt ") \
EM(afs_cell_trace_unuse_no_pin, "UNU no-pin") \
EM(afs_cell_trace_unuse_parse, "UNU parse ") \
EM(afs_cell_trace_unuse_pin, "UNU pin ") \
- EM(afs_cell_trace_unuse_probe, "UNU probe ") \
EM(afs_cell_trace_unuse_sbi, "UNU sbi ") \
EM(afs_cell_trace_unuse_ws, "UNU ws ") \
EM(afs_cell_trace_use_alias, "USE alias ") \
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 581/602] afs: Fix dynamic lookup to fail on cell lookup failure
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (579 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 580/602] afs: Simplify cell record handling Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 582/602] afs: Fix lack of locking around modifications of net->cells_dyn_ino Greg Kroah-Hartman
` (24 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Markus Suvanto, David Howells,
Marc Dionne, linux-afs, Christian Brauner, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <dhowells@redhat.com>
[ Upstream commit 330e2c514823008b22e6afd2055715bc46dd8d55 ]
When a process tries to access an entry in /afs, normally what happens is
that an automount dentry is created by ->lookup() and then triggered, which
jumps through the ->d_automount() op. Currently, afs_dynroot_lookup() does
not do cell DNS lookup, leaving that to afs_d_automount() to perform -
however, it is possible to use access() or stat() on the automount point,
which will always return successfully, have briefly created an afs_cell
record if one did not already exist.
This means that something like:
test -d "/afs/.west" && echo Directory exists
will print "Directory exists" even though no such cell is configured. This
breaks the "west" python module available on PIP as it expects this access
to fail.
Now, it could be possible to make afs_dynroot_lookup() perform the DNS[*]
lookup, but that would make "ls --color /afs" do this for each cell in /afs
that is listed but not yet probed. kafs-client, probably wrongly, preloads
the entire cell database and all the known cells are then listed in /afs -
and doing ls /afs would be very, very slow, especially if any cell supplied
addresses but was wholly inaccessible.
[*] When I say "DNS", actually read getaddrinfo(), which could use any one
of a host of mechanisms. Could also use static configuration.
To fix this, make the following changes:
(1) Create an enum to specify the origination point of a call to
afs_lookup_cell() and pass this value into that function in place of
the "excl" parameter (which can be derived from it). There are six
points of origination:
- Cell preload through /proc/net/afs/cells
- Root cell config through /proc/net/afs/rootcell
- Lookup in dynamic root
- Automount trigger
- Direct mount with mount() syscall
- Alias check where YFS tells us the cell name is different
(2) Add an extra state into the afs_cell state machine to indicate a cell
that's been initialised, but not yet looked up. This is separate from
one that can be considered active and has been looked up at least
once.
(3) Make afs_lookup_cell() vary its behaviour more, depending on where it
was called from:
If called from preload or root cell config, DNS lookup will not happen
until we definitely want to use the cell (dynroot mount, automount,
direct mount or alias check). The cell will appear in /afs but stat()
won't trigger DNS lookup.
If the cell already exists, dynroot will not wait for the DNS lookup
to complete. If the cell did not already exist, dynroot will wait.
If called from automount, direct mount or alias check, it will wait
for the DNS lookup to complete.
(4) Make afs_lookup_cell() return an error if lookup failed in one way or
another. We try to return -ENOENT if the DNS says the cell does not
exist and -EDESTADDRREQ if we couldn't access the DNS.
Reported-by: Markus Suvanto <markus.suvanto@gmail.com>
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220685
Signed-off-by: David Howells <dhowells@redhat.com>
Link: https://patch.msgid.link/1784747.1761158912@warthog.procyon.org.uk
Fixes: 1d0b929fc070 ("afs: Change dynroot to create contents on demand")
Tested-by: Markus Suvanto <markus.suvanto@gmail.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
Signed-off-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/afs/cell.c | 78 +++++++++++++++++++++++++++++++++++++++++++++---------
fs/afs/dynroot.c | 3 +-
fs/afs/internal.h | 12 +++++++-
fs/afs/mntpt.c | 3 +-
fs/afs/proc.c | 3 +-
fs/afs/super.c | 2 -
fs/afs/vl_alias.c | 3 +-
7 files changed, 86 insertions(+), 18 deletions(-)
--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -228,7 +228,7 @@ error:
* @name: The name of the cell.
* @namesz: The strlen of the cell name.
* @vllist: A colon/comma separated list of numeric IP addresses or NULL.
- * @excl: T if an error should be given if the cell name already exists.
+ * @reason: The reason we're doing the lookup
* @trace: The reason to be logged if the lookup is successful.
*
* Look up a cell record by name and query the DNS for VL server addresses if
@@ -238,7 +238,8 @@ error:
*/
struct afs_cell *afs_lookup_cell(struct afs_net *net,
const char *name, unsigned int namesz,
- const char *vllist, bool excl,
+ const char *vllist,
+ enum afs_lookup_cell_for reason,
enum afs_cell_trace trace)
{
struct afs_cell *cell, *candidate, *cursor;
@@ -246,12 +247,18 @@ struct afs_cell *afs_lookup_cell(struct
enum afs_cell_state state;
int ret, n;
- _enter("%s,%s", name, vllist);
+ _enter("%s,%s,%u", name, vllist, reason);
- if (!excl) {
+ if (reason != AFS_LOOKUP_CELL_PRELOAD) {
cell = afs_find_cell(net, name, namesz, trace);
- if (!IS_ERR(cell))
+ if (!IS_ERR(cell)) {
+ if (reason == AFS_LOOKUP_CELL_DYNROOT)
+ goto no_wait;
+ if (cell->state == AFS_CELL_SETTING_UP ||
+ cell->state == AFS_CELL_UNLOOKED)
+ goto lookup_cell;
goto wait_for_cell;
+ }
}
/* Assume we're probably going to create a cell and preallocate and
@@ -297,26 +304,69 @@ struct afs_cell *afs_lookup_cell(struct
rb_insert_color(&cell->net_node, &net->cells);
up_write(&net->cells_lock);
- afs_queue_cell(cell, afs_cell_trace_queue_new);
+lookup_cell:
+ if (reason != AFS_LOOKUP_CELL_PRELOAD &&
+ reason != AFS_LOOKUP_CELL_ROOTCELL) {
+ set_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags);
+ afs_queue_cell(cell, afs_cell_trace_queue_new);
+ }
wait_for_cell:
- _debug("wait_for_cell");
state = smp_load_acquire(&cell->state); /* vs error */
- if (state != AFS_CELL_ACTIVE &&
- state != AFS_CELL_DEAD) {
+ switch (state) {
+ case AFS_CELL_ACTIVE:
+ case AFS_CELL_DEAD:
+ break;
+ case AFS_CELL_UNLOOKED:
+ default:
+ if (reason == AFS_LOOKUP_CELL_PRELOAD ||
+ reason == AFS_LOOKUP_CELL_ROOTCELL)
+ break;
+ _debug("wait_for_cell");
afs_see_cell(cell, afs_cell_trace_wait);
wait_var_event(&cell->state,
({
state = smp_load_acquire(&cell->state); /* vs error */
state == AFS_CELL_ACTIVE || state == AFS_CELL_DEAD;
}));
+ _debug("waited_for_cell %d %d", cell->state, cell->error);
}
+no_wait:
/* Check the state obtained from the wait check. */
+ state = smp_load_acquire(&cell->state); /* vs error */
if (state == AFS_CELL_DEAD) {
ret = cell->error;
goto error;
}
+ if (state == AFS_CELL_ACTIVE) {
+ switch (cell->dns_status) {
+ case DNS_LOOKUP_NOT_DONE:
+ if (cell->dns_source == DNS_RECORD_FROM_CONFIG) {
+ ret = 0;
+ break;
+ }
+ fallthrough;
+ default:
+ ret = -EIO;
+ goto error;
+ case DNS_LOOKUP_GOOD:
+ case DNS_LOOKUP_GOOD_WITH_BAD:
+ ret = 0;
+ break;
+ case DNS_LOOKUP_GOT_NOT_FOUND:
+ ret = -ENOENT;
+ goto error;
+ case DNS_LOOKUP_BAD:
+ ret = -EREMOTEIO;
+ goto error;
+ case DNS_LOOKUP_GOT_LOCAL_FAILURE:
+ case DNS_LOOKUP_GOT_TEMP_FAILURE:
+ case DNS_LOOKUP_GOT_NS_FAILURE:
+ ret = -EDESTADDRREQ;
+ goto error;
+ }
+ }
_leave(" = %p [cell]", cell);
return cell;
@@ -324,7 +374,7 @@ wait_for_cell:
cell_already_exists:
_debug("cell exists");
cell = cursor;
- if (excl) {
+ if (reason == AFS_LOOKUP_CELL_PRELOAD) {
ret = -EEXIST;
} else {
afs_use_cell(cursor, trace);
@@ -383,7 +433,8 @@ int afs_cell_init(struct afs_net *net, c
return -EINVAL;
/* allocate a cell record for the root/workstation cell */
- new_root = afs_lookup_cell(net, rootcell, len, vllist, false,
+ new_root = afs_lookup_cell(net, rootcell, len, vllist,
+ AFS_LOOKUP_CELL_ROOTCELL,
afs_cell_trace_use_lookup_ws);
if (IS_ERR(new_root)) {
_leave(" = %ld", PTR_ERR(new_root));
@@ -778,6 +829,7 @@ static bool afs_manage_cell(struct afs_c
switch (cell->state) {
case AFS_CELL_SETTING_UP:
goto set_up_cell;
+ case AFS_CELL_UNLOOKED:
case AFS_CELL_ACTIVE:
goto cell_is_active;
case AFS_CELL_REMOVING:
@@ -798,7 +850,7 @@ set_up_cell:
goto remove_cell;
}
- afs_set_cell_state(cell, AFS_CELL_ACTIVE);
+ afs_set_cell_state(cell, AFS_CELL_UNLOOKED);
cell_is_active:
if (afs_has_cell_expired(cell, &next_manage))
@@ -808,6 +860,8 @@ cell_is_active:
ret = afs_update_cell(cell);
if (ret < 0)
cell->error = ret;
+ if (cell->state == AFS_CELL_UNLOOKED)
+ afs_set_cell_state(cell, AFS_CELL_ACTIVE);
}
if (next_manage < TIME64_MAX && cell->net->live) {
--- a/fs/afs/dynroot.c
+++ b/fs/afs/dynroot.c
@@ -108,7 +108,8 @@ static struct dentry *afs_dynroot_lookup
dotted = true;
}
- cell = afs_lookup_cell(net, name, len, NULL, false,
+ cell = afs_lookup_cell(net, name, len, NULL,
+ AFS_LOOKUP_CELL_DYNROOT,
afs_cell_trace_use_lookup_dynroot);
if (IS_ERR(cell)) {
ret = PTR_ERR(cell);
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -353,6 +353,7 @@ extern const char afs_init_sysname[];
enum afs_cell_state {
AFS_CELL_SETTING_UP,
+ AFS_CELL_UNLOOKED,
AFS_CELL_ACTIVE,
AFS_CELL_REMOVING,
AFS_CELL_DEAD,
@@ -1034,9 +1035,18 @@ static inline bool afs_cb_is_broken(unsi
extern int afs_cell_init(struct afs_net *, const char *);
extern struct afs_cell *afs_find_cell(struct afs_net *, const char *, unsigned,
enum afs_cell_trace);
+enum afs_lookup_cell_for {
+ AFS_LOOKUP_CELL_DYNROOT,
+ AFS_LOOKUP_CELL_MOUNTPOINT,
+ AFS_LOOKUP_CELL_DIRECT_MOUNT,
+ AFS_LOOKUP_CELL_PRELOAD,
+ AFS_LOOKUP_CELL_ROOTCELL,
+ AFS_LOOKUP_CELL_ALIAS_CHECK,
+};
struct afs_cell *afs_lookup_cell(struct afs_net *net,
const char *name, unsigned int namesz,
- const char *vllist, bool excl,
+ const char *vllist,
+ enum afs_lookup_cell_for reason,
enum afs_cell_trace trace);
extern struct afs_cell *afs_use_cell(struct afs_cell *, enum afs_cell_trace);
void afs_unuse_cell(struct afs_cell *cell, enum afs_cell_trace reason);
--- a/fs/afs/mntpt.c
+++ b/fs/afs/mntpt.c
@@ -107,7 +107,8 @@ static int afs_mntpt_set_params(struct f
if (size > AFS_MAXCELLNAME)
return -ENAMETOOLONG;
- cell = afs_lookup_cell(ctx->net, p, size, NULL, false,
+ cell = afs_lookup_cell(ctx->net, p, size, NULL,
+ AFS_LOOKUP_CELL_MOUNTPOINT,
afs_cell_trace_use_lookup_mntpt);
if (IS_ERR(cell)) {
pr_err("kAFS: unable to lookup cell '%pd'\n", mntpt);
--- a/fs/afs/proc.c
+++ b/fs/afs/proc.c
@@ -122,7 +122,8 @@ static int afs_proc_cells_write(struct f
if (strcmp(buf, "add") == 0) {
struct afs_cell *cell;
- cell = afs_lookup_cell(net, name, strlen(name), args, true,
+ cell = afs_lookup_cell(net, name, strlen(name), args,
+ AFS_LOOKUP_CELL_PRELOAD,
afs_cell_trace_use_lookup_add);
if (IS_ERR(cell)) {
ret = PTR_ERR(cell);
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -290,7 +290,7 @@ static int afs_parse_source(struct fs_co
/* lookup the cell record */
if (cellname) {
cell = afs_lookup_cell(ctx->net, cellname, cellnamesz,
- NULL, false,
+ NULL, AFS_LOOKUP_CELL_DIRECT_MOUNT,
afs_cell_trace_use_lookup_mount);
if (IS_ERR(cell)) {
pr_err("kAFS: unable to lookup cell '%*.*s'\n",
--- a/fs/afs/vl_alias.c
+++ b/fs/afs/vl_alias.c
@@ -269,7 +269,8 @@ static int yfs_check_canonical_cell_name
if (!name_len || name_len > AFS_MAXCELLNAME)
master = ERR_PTR(-EOPNOTSUPP);
else
- master = afs_lookup_cell(cell->net, cell_name, name_len, NULL, false,
+ master = afs_lookup_cell(cell->net, cell_name, name_len, NULL,
+ AFS_LOOKUP_CELL_ALIAS_CHECK,
afs_cell_trace_use_lookup_canonical);
kfree(cell_name);
if (IS_ERR(master))
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 582/602] afs: Fix lack of locking around modifications of net->cells_dyn_ino
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (580 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 581/602] afs: Fix dynamic lookup to fail on cell lookup failure Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 583/602] USB: gadget: Use str_enable_disable-like helpers Greg Kroah-Hartman
` (23 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Howells, Marc Dionne,
linux-afs, Christian Brauner (Amutable), Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <dhowells@redhat.com>
[ Upstream commit 55e841836c6f4646490f7b0347192b7a92d431ba ]
Fix the lack of locking around modifications of net->cells_dyn_ino by
taking net->cells_lock exclusively. This also requires to cell to be
removed from net->cells_dyn_ino in afs_destroy_cell_work() rather than in
afs_cell_destroy() as the latter runs in RCU cleanup context and sleeping
locks cannot be taken there.
Fixes: 1d0b929fc070 ("afs: Change dynroot to create contents on demand")
Closes: https://sashiko.dev/#/patchset/20260618074903.2374756-1-dhowells%40redhat.com
Signed-off-by: David Howells <dhowells@redhat.com>
Link: https://patch.msgid.link/20260622090856.2746629-19-dhowells@redhat.com
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Stable-dep-of: 26f17ce6fa3f ("afs: Fix premature cell exposure through /afs")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/afs/cell.c | 8 +++++++-
fs/afs/dynroot.c | 2 +-
2 files changed, 8 insertions(+), 2 deletions(-)
--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -198,8 +198,10 @@ static struct afs_cell *afs_alloc_cell(s
cell->dns_source = vllist->source;
cell->dns_status = vllist->status;
smp_store_release(&cell->dns_lookup_count, 1); /* vs source/status */
+ down_write(&net->cells_lock);
ret = idr_alloc_cyclic(&net->cells_dyn_ino, cell,
2, INT_MAX / 2, GFP_KERNEL);
+ up_write(&net->cells_lock);
if (ret < 0)
goto error;
atomic_inc(&net->cells_outstanding);
@@ -572,7 +574,6 @@ static void afs_cell_destroy(struct rcu_
afs_put_vlserverlist(net, rcu_access_pointer(cell->vl_servers));
afs_unuse_cell(cell->alias_of, afs_cell_trace_unuse_alias);
key_put(cell->anonymous_key);
- idr_remove(&net->cells_dyn_ino, cell->dynroot_ino);
kfree(cell->name - 1);
kfree(cell);
@@ -587,6 +588,11 @@ static void afs_destroy_cell_work(struct
afs_see_cell(cell, afs_cell_trace_destroy);
timer_delete_sync(&cell->management_timer);
cancel_work_sync(&cell->manager);
+
+ down_write(&cell->net->cells_lock);
+ idr_remove(&cell->net->cells_dyn_ino, cell->dynroot_ino);
+ up_write(&cell->net->cells_lock);
+
call_rcu(&cell->rcu, afs_cell_destroy);
}
--- a/fs/afs/dynroot.c
+++ b/fs/afs/dynroot.c
@@ -278,7 +278,7 @@ static struct dentry *afs_lookup_atcell(
}
/*
- * Transcribe the cell database into readdir content under the RCU read lock.
+ * Transcribe the cell database into readdir content under net->cells_lock.
* Each cell produces two entries, one prefixed with a dot and one not.
*/
static int afs_dynroot_readdir_cells(struct afs_net *net, struct dir_context *ctx)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 583/602] USB: gadget: Use str_enable_disable-like helpers
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (581 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 582/602] afs: Fix lack of locking around modifications of net->cells_dyn_ino Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 584/602] USB: gadget: fsl-udc: fix dev_printk() device Greg Kroah-Hartman
` (22 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Krzysztof Kozlowski, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
[ Upstream commit 5b6dc50e9ed870fffbf2ae6de77b30fb0d15eab8 ]
Replace ternary (condition ? "enable" : "disable") syntax with helpers
from string_choices.h because:
1. Simple function call with one argument is easier to read. Ternary
operator has three arguments and with wrapping might lead to quite
long code.
2. Is slightly shorter thus also easier to read.
3. It brings uniformity in the text - same string.
4. Allows deduping by the linker, which results in a smaller binary
file.
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Link: https://lore.kernel.org/r/20250114-str-enable-disable-usb-v1-5-c8405df47c19@linaro.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Stable-dep-of: c4dd150fceab ("USB: gadget: fsl-udc: fix dev_printk() device")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/gadget/function/f_ecm.c | 4 ++--
drivers/usb/gadget/function/f_ncm.c | 3 ++-
drivers/usb/gadget/function/u_serial.c | 3 ++-
drivers/usb/gadget/legacy/inode.c | 3 ++-
drivers/usb/gadget/udc/aspeed-vhub/hub.c | 3 ++-
drivers/usb/gadget/udc/at91_udc.c | 3 ++-
drivers/usb/gadget/udc/cdns2/cdns2-gadget.c | 13 +++++++------
drivers/usb/gadget/udc/dummy_hcd.c | 3 ++-
drivers/usb/gadget/udc/fsl_udc_core.c | 3 ++-
drivers/usb/gadget/udc/omap_udc.c | 3 ++-
drivers/usb/gadget/udc/pxa27x_udc.c | 3 ++-
11 files changed, 27 insertions(+), 17 deletions(-)
--- a/drivers/usb/gadget/function/f_ecm.c
+++ b/drivers/usb/gadget/function/f_ecm.c
@@ -14,6 +14,7 @@
#include <linux/module.h>
#include <linux/device.h>
#include <linux/etherdevice.h>
+#include <linux/string_choices.h>
#include <linux/usb/gadget.h>
@@ -390,8 +391,7 @@ static void ecm_do_notify(struct f_ecm *
event->wLength = 0;
req->length = sizeof *event;
- DBG(cdev, "notify connect %s\n",
- ecm->is_open ? "true" : "false");
+ DBG(cdev, "notify connect %s\n", str_true_false(ecm->is_open));
ecm->notify_state = ECM_NOTIFY_SPEED;
break;
--- a/drivers/usb/gadget/function/f_ncm.c
+++ b/drivers/usb/gadget/function/f_ncm.c
@@ -18,6 +18,7 @@
#include <linux/device.h>
#include <linux/etherdevice.h>
#include <linux/crc32.h>
+#include <linux/string_choices.h>
#include <linux/usb/cdc.h>
#include <linux/usb/gadget.h>
@@ -560,7 +561,7 @@ static void ncm_do_notify(struct f_ncm *
req->length = sizeof *event;
DBG(cdev, "notify connect %s\n",
- ncm->is_open ? "true" : "false");
+ str_true_false(ncm->is_open));
ncm->notify_state = NCM_NOTIFY_NONE;
break;
--- a/drivers/usb/gadget/function/u_serial.c
+++ b/drivers/usb/gadget/function/u_serial.c
@@ -21,6 +21,7 @@
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/slab.h>
+#include <linux/string_choices.h>
#include <linux/export.h>
#include <linux/module.h>
#include <linux/console.h>
@@ -1541,7 +1542,7 @@ static int __init userial_init(void)
pr_debug("%s: registered %d ttyGS* device%s\n", __func__,
MAX_U_SERIAL_PORTS,
- (MAX_U_SERIAL_PORTS == 1) ? "" : "s");
+ str_plural(MAX_U_SERIAL_PORTS));
return status;
fail:
--- a/drivers/usb/gadget/legacy/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
@@ -20,6 +20,7 @@
#include <linux/uaccess.h>
#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/string_choices.h>
#include <linux/poll.h>
#include <linux/kthread.h>
#include <linux/aio.h>
@@ -1182,7 +1183,7 @@ ep0_fasync (int f, struct file *fd, int
{
struct dev_data *dev = fd->private_data;
// caller must F_SETOWN before signal delivery happens
- VDEBUG (dev, "%s %s\n", __func__, on ? "on" : "off");
+ VDEBUG(dev, "%s %s\n", __func__, str_on_off(on));
return fasync_helper (f, fd, on, &dev->fasync);
}
--- a/drivers/usb/gadget/udc/aspeed-vhub/hub.c
+++ b/drivers/usb/gadget/udc/aspeed-vhub/hub.c
@@ -22,6 +22,7 @@
#include <linux/usb/gadget.h>
#include <linux/of.h>
#include <linux/regmap.h>
+#include <linux/string_choices.h>
#include <linux/dma-mapping.h>
#include <linux/bcd.h>
#include <linux/version.h>
@@ -219,7 +220,7 @@ static int ast_vhub_hub_dev_feature(stru
if (wValue == USB_DEVICE_REMOTE_WAKEUP) {
ep->vhub->wakeup_en = is_set;
EPDBG(ep, "Hub remote wakeup %s\n",
- is_set ? "enabled" : "disabled");
+ str_enabled_disabled(is_set));
return std_req_complete;
}
--- a/drivers/usb/gadget/udc/at91_udc.c
+++ b/drivers/usb/gadget/udc/at91_udc.c
@@ -16,6 +16,7 @@
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/slab.h>
+#include <linux/string_choices.h>
#include <linux/errno.h>
#include <linux/list.h>
#include <linux/interrupt.h>
@@ -131,7 +132,7 @@ static void proc_ep_show(struct seq_file
seq_printf(s, "csr %08x rxbytes=%d %s %s %s" EIGHTBITS "\n",
csr,
(csr & 0x07ff0000) >> 16,
- (csr & (1 << 15)) ? "enabled" : "disabled",
+ str_enabled_disabled(csr & (1 << 15)),
(csr & (1 << 11)) ? "DATA1" : "DATA0",
types[(csr & 0x700) >> 8],
--- a/drivers/usb/gadget/udc/cdns2/cdns2-gadget.c
+++ b/drivers/usb/gadget/udc/cdns2/cdns2-gadget.c
@@ -29,6 +29,7 @@
#include <linux/pm_runtime.h>
#include <linux/interrupt.h>
#include <linux/property.h>
+#include <linux/string_choices.h>
#include <linux/dmapool.h>
#include <linux/iopoll.h>
@@ -2233,12 +2234,12 @@ static int cdns2_init_eps(struct cdns2_d
dev_dbg(pdev->dev, "Init %s, SupType: CTRL: %s, INT: %s, "
"BULK: %s, ISOC %s, SupDir IN: %s, OUT: %s\n",
pep->name,
- (pep->endpoint.caps.type_control) ? "yes" : "no",
- (pep->endpoint.caps.type_int) ? "yes" : "no",
- (pep->endpoint.caps.type_bulk) ? "yes" : "no",
- (pep->endpoint.caps.type_iso) ? "yes" : "no",
- (pep->endpoint.caps.dir_in) ? "yes" : "no",
- (pep->endpoint.caps.dir_out) ? "yes" : "no");
+ str_yes_no(pep->endpoint.caps.type_control),
+ str_yes_no(pep->endpoint.caps.type_int),
+ str_yes_no(pep->endpoint.caps.type_bulk),
+ str_yes_no(pep->endpoint.caps.type_iso),
+ str_yes_no(pep->endpoint.caps.dir_in),
+ str_yes_no(pep->endpoint.caps.dir_out));
INIT_LIST_HEAD(&pep->pending_list);
INIT_LIST_HEAD(&pep->deferred_list);
--- a/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
@@ -28,6 +28,7 @@
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/slab.h>
+#include <linux/string_choices.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/hrtimer.h>
@@ -649,7 +650,7 @@ static int dummy_enable(struct usb_ep *_
desc->bEndpointAddress & 0x0f,
(desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
usb_ep_type_string(usb_endpoint_type(desc)),
- max, ep->stream_en ? "enabled" : "disabled");
+ max, str_enabled_disabled(ep->stream_en));
/* at this point real hardware should be NAKing transfers
* to that endpoint, until a buffer is queued to it.
--- a/drivers/usb/gadget/udc/fsl_udc_core.c
+++ b/drivers/usb/gadget/udc/fsl_udc_core.c
@@ -22,6 +22,7 @@
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/slab.h>
+#include <linux/string_choices.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/interrupt.h>
@@ -1181,7 +1182,7 @@ static int fsl_vbus_session(struct usb_g
udc = container_of(gadget, struct fsl_udc, gadget);
spin_lock_irqsave(&udc->lock, flags);
- dev_vdbg(&gadget->dev, "VBUS %s\n", is_active ? "on" : "off");
+ dev_vdbg(&gadget->dev, "VBUS %s\n", str_on_off(is_active));
udc->vbus_active = (is_active != 0);
if (can_pullup(udc))
fsl_writel((fsl_readl(&dr_regs->usbcmd) | USB_CMD_RUN_STOP),
--- a/drivers/usb/gadget/udc/omap_udc.c
+++ b/drivers/usb/gadget/udc/omap_udc.c
@@ -18,6 +18,7 @@
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/slab.h>
+#include <linux/string_choices.h>
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/interrupt.h>
@@ -1248,7 +1249,7 @@ static int omap_vbus_session(struct usb_
udc = container_of(gadget, struct omap_udc, gadget);
spin_lock_irqsave(&udc->lock, flags);
- VDBG("VBUS %s\n", is_active ? "on" : "off");
+ VDBG("VBUS %s\n", str_on_off(is_active));
udc->vbus_active = (is_active != 0);
if (cpu_is_omap15xx()) {
/* "software" detect, ignored if !VBUS_MODE_1510 */
--- a/drivers/usb/gadget/udc/pxa27x_udc.c
+++ b/drivers/usb/gadget/udc/pxa27x_udc.c
@@ -20,6 +20,7 @@
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/slab.h>
+#include <linux/string_choices.h>
#include <linux/prefetch.h>
#include <linux/byteorder/generic.h>
#include <linux/platform_data/pxa2xx_udc.h>
@@ -1083,7 +1084,7 @@ static int pxa_ep_queue(struct usb_ep *_
is_first_req = list_empty(&ep->queue);
ep_dbg(ep, "queue req %p(first=%s), len %d buf %p\n",
- _req, is_first_req ? "yes" : "no",
+ _req, str_yes_no(is_first_req),
_req->length, _req->buf);
if (!ep->enabled) {
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 584/602] USB: gadget: fsl-udc: fix dev_printk() device
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (582 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 583/602] USB: gadget: Use str_enable_disable-like helpers Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 585/602] usb: musb: omap2430: clean up probe error handling Greg Kroah-Hartman
` (21 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, stable, Uwe Kleine-König,
Johan Hovold, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <johan@kernel.org>
[ Upstream commit c4dd150fceab281496acb3a643ae712aacb74864 ]
A change replacing custom printk() macros with dev_printk() incorrectly
used the gadget struct device instead of the controller struct device
(including for messages printed before the gadget device name has been
initialised).
Switch to using the controller platform device with dev_printk() so that
the controller device and driver names are included in log messages as
expected.
Fixes: 6025f20f16c2 ("usb: gadget: fsl-udc: Replace custom log wrappers by dev_{err,warn,dbg,vdbg}")
Cc: stable <stable@kernel.org>
Cc: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Signed-off-by: Johan Hovold <johan@kernel.org>
Acked-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Link: https://patch.msgid.link/20260702141536.90887-4-johan@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/gadget/udc/fsl_udc_core.c | 92 +++++++++++++++-------------------
drivers/usb/gadget/udc/fsl_usb2_udc.h | 1
2 files changed, 43 insertions(+), 50 deletions(-)
--- a/drivers/usb/gadget/udc/fsl_udc_core.c
+++ b/drivers/usb/gadget/udc/fsl_udc_core.c
@@ -184,7 +184,7 @@ __acquires(ep->udc->lock)
usb_gadget_unmap_request(&ep->udc->gadget, &req->req, ep_is_in(ep));
if (status && (status != -ESHUTDOWN))
- dev_vdbg(&udc->gadget.dev, "complete %s req %p stat %d len %u/%u\n",
+ dev_vdbg(udc->dev, "complete %s req %p stat %d len %u/%u\n",
ep->ep.name, &req->req, status,
req->req.actual, req->req.length);
@@ -286,7 +286,7 @@ static int dr_controller_setup(struct fs
timeout = jiffies + FSL_UDC_RESET_TIMEOUT;
while (fsl_readl(&dr_regs->usbcmd) & USB_CMD_CTRL_RESET) {
if (time_after(jiffies, timeout)) {
- dev_err(&udc->gadget.dev, "udc reset timeout!\n");
+ dev_err(udc->dev, "udc reset timeout!\n");
return -ETIMEDOUT;
}
cpu_relax();
@@ -309,7 +309,7 @@ static int dr_controller_setup(struct fs
tmp &= USB_EP_LIST_ADDRESS_MASK;
fsl_writel(tmp, &dr_regs->endpointlistaddr);
- dev_vdbg(&udc->gadget.dev,
+ dev_vdbg(udc->dev,
"vir[qh_base] is %p phy[qh_base] is 0x%8x reg is 0x%8x\n",
udc->ep_qh, (int)tmp,
fsl_readl(&dr_regs->endpointlistaddr));
@@ -500,7 +500,7 @@ static void struct_ep_qh_setup(struct fs
tmp = max_pkt_len << EP_QUEUE_HEAD_MAX_PKT_LEN_POS;
break;
default:
- dev_vdbg(&udc->gadget.dev, "error ep type is %d\n", ep_type);
+ dev_vdbg(udc->dev, "error ep type is %d\n", ep_type);
return;
}
if (zlt)
@@ -613,7 +613,7 @@ static int fsl_ep_enable(struct usb_ep *
spin_unlock_irqrestore(&udc->lock, flags);
retval = 0;
- dev_vdbg(&udc->gadget.dev, "enabled %s (ep%d%s) maxpacket %d\n",
+ dev_vdbg(udc->dev, "enabled %s (ep%d%s) maxpacket %d\n",
ep->ep.name, ep->ep.desc->bEndpointAddress & 0x0f,
(desc->bEndpointAddress & USB_DIR_IN) ? "in" : "out",
max);
@@ -634,13 +634,8 @@ static int fsl_ep_disable(struct usb_ep
int ep_num;
ep = container_of(_ep, struct fsl_ep, ep);
- if (!_ep || !ep->ep.desc) {
- /*
- * dev_vdbg(&udc->gadget.dev, "%s not enabled\n",
- * _ep ? ep->ep.name : NULL);
- */
+ if (!_ep || !ep->ep.desc)
return -EINVAL;
- }
/* disable ep on controller */
ep_num = ep_index(ep);
@@ -664,7 +659,7 @@ static int fsl_ep_disable(struct usb_ep
ep->stopped = 1;
spin_unlock_irqrestore(&udc->lock, flags);
- dev_vdbg(&udc->gadget.dev, "disabled %s OK\n", _ep->name);
+ dev_vdbg(udc->dev, "disabled %s OK\n", _ep->name);
return 0;
}
@@ -724,9 +719,6 @@ static void fsl_queue_td(struct fsl_ep *
{
u32 temp, bitmask, tmp_stat;
- /* dev_vdbg(&udc->gadget.dev, "QH addr Register 0x%8x\n", dr_regs->endpointlistaddr);
- dev_vdbg(&udc->gadget.dev, "ep_qh[%d] addr is 0x%8x\n", i, (u32)&(ep->udc->ep_qh[i])); */
-
bitmask = ep_is_in(ep)
? (1 << (ep_index(ep) + 16))
: (1 << (ep_index(ep)));
@@ -813,7 +805,7 @@ static struct ep_td_struct *fsl_build_dt
*is_last = 0;
if ((*is_last) == 0)
- dev_vdbg(&udc_controller->gadget.dev, "multi-dtd request!\n");
+ dev_vdbg(udc_controller->dev, "multi-dtd request!\n");
/* Fill in the transfer size; set active bit */
swap_temp = ((*length << DTD_LENGTH_BIT_POS) | DTD_STATUS_ACTIVE);
@@ -825,7 +817,7 @@ static struct ep_td_struct *fsl_build_dt
mb();
- dev_vdbg(&udc_controller->gadget.dev, "length = %d address= 0x%x\n", *length, (int)*dma);
+ dev_vdbg(udc_controller->dev, "length = %d address= 0x%x\n", *length, (int)*dma);
return dtd;
}
@@ -876,11 +868,11 @@ fsl_ep_queue(struct usb_ep *_ep, struct
/* catch various bogus parameters */
if (!_req || !req->req.complete || !req->req.buf
|| !list_empty(&req->queue)) {
- dev_vdbg(&udc->gadget.dev, "%s, bad params\n", __func__);
+ dev_vdbg(udc->dev, "%s, bad params\n", __func__);
return -EINVAL;
}
if (unlikely(!ep->ep.desc)) {
- dev_vdbg(&udc->gadget.dev, "%s, bad ep\n", __func__);
+ dev_vdbg(udc->dev, "%s, bad ep\n", __func__);
return -EINVAL;
}
if (usb_endpoint_xfer_isoc(ep->ep.desc)) {
@@ -1040,7 +1032,7 @@ static int fsl_ep_set_halt(struct usb_ep
udc->ep0_dir = 0;
}
out:
- dev_vdbg(&udc->gadget.dev, "%s %s halt stat %d\n", ep->ep.name,
+ dev_vdbg(udc->dev, "%s %s halt stat %d\n", ep->ep.name,
value ? "set" : "clear", status);
return status;
@@ -1109,7 +1101,7 @@ static void fsl_ep_fifo_flush(struct usb
/* Wait until flush complete */
while (fsl_readl(&dr_regs->endptflush)) {
if (time_after(jiffies, timeout)) {
- dev_err(&udc_controller->gadget.dev,
+ dev_err(udc_controller->dev,
"ep flush timeout\n");
return;
}
@@ -1182,7 +1174,7 @@ static int fsl_vbus_session(struct usb_g
udc = container_of(gadget, struct fsl_udc, gadget);
spin_lock_irqsave(&udc->lock, flags);
- dev_vdbg(&gadget->dev, "VBUS %s\n", str_on_off(is_active));
+ dev_vdbg(udc->dev, "VBUS %s\n", str_on_off(is_active));
udc->vbus_active = (is_active != 0);
if (can_pullup(udc))
fsl_writel((fsl_readl(&dr_regs->usbcmd) | USB_CMD_RUN_STOP),
@@ -1548,7 +1540,7 @@ static void ep0_req_complete(struct fsl_
udc->ep0_state = WAIT_FOR_SETUP;
break;
case WAIT_FOR_SETUP:
- dev_err(&udc->gadget.dev, "Unexpected ep0 packets\n");
+ dev_err(udc->dev, "Unexpected ep0 packets\n");
break;
default:
ep0stall(udc);
@@ -1617,7 +1609,7 @@ static int process_ep_req(struct fsl_udc
errors = hc32_to_cpu(curr_td->size_ioc_sts);
if (errors & DTD_ERROR_MASK) {
if (errors & DTD_STATUS_HALTED) {
- dev_err(&udc->gadget.dev, "dTD error %08x QH=%d\n", errors, pipe);
+ dev_err(udc->dev, "dTD error %08x QH=%d\n", errors, pipe);
/* Clear the errors and Halt condition */
tmp = hc32_to_cpu(curr_qh->size_ioc_int_sts);
tmp &= ~errors;
@@ -1628,26 +1620,26 @@ static int process_ep_req(struct fsl_udc
break;
}
if (errors & DTD_STATUS_DATA_BUFF_ERR) {
- dev_vdbg(&udc->gadget.dev, "Transfer overflow\n");
+ dev_vdbg(udc->dev, "Transfer overflow\n");
status = -EPROTO;
break;
} else if (errors & DTD_STATUS_TRANSACTION_ERR) {
- dev_vdbg(&udc->gadget.dev, "ISO error\n");
+ dev_vdbg(udc->dev, "ISO error\n");
status = -EILSEQ;
break;
} else
- dev_err(&udc->gadget.dev,
+ dev_err(udc->dev,
"Unknown error has occurred (0x%x)!\n",
errors);
} else if (hc32_to_cpu(curr_td->size_ioc_sts)
& DTD_STATUS_ACTIVE) {
- dev_vdbg(&udc->gadget.dev, "Request not complete\n");
+ dev_vdbg(udc->dev, "Request not complete\n");
status = REQ_UNCOMPLETE;
return status;
} else if (remaining_length) {
if (direction) {
- dev_vdbg(&udc->gadget.dev,
+ dev_vdbg(udc->dev,
"Transmit dTD remaining length not zero\n");
status = -EPROTO;
break;
@@ -1655,8 +1647,7 @@ static int process_ep_req(struct fsl_udc
break;
}
} else {
- dev_vdbg(&udc->gadget.dev,
- "dTD transmitted successful\n");
+ dev_vdbg(udc->dev, "dTD transmitted successful\n");
}
if (j != curr_req->dtd_count - 1)
@@ -1699,7 +1690,7 @@ static void dtd_complete_irq(struct fsl_
/* If the ep is configured */
if (!curr_ep->ep.name) {
- dev_warn(&udc->gadget.dev, "Invalid EP?\n");
+ dev_warn(udc->dev, "Invalid EP?\n");
continue;
}
@@ -1708,7 +1699,7 @@ static void dtd_complete_irq(struct fsl_
queue) {
status = process_ep_req(udc, i, curr_req);
- dev_vdbg(&udc->gadget.dev,
+ dev_vdbg(udc->dev,
"status of process_ep_req= %d, ep = %d\n",
status, ep_num);
if (status == REQ_UNCOMPLETE)
@@ -1829,7 +1820,7 @@ static void reset_irq(struct fsl_udc *ud
while (fsl_readl(&dr_regs->endpointprime)) {
/* Wait until all endptprime bits cleared */
if (time_after(jiffies, timeout)) {
- dev_err(&udc->gadget.dev, "Timeout for reset\n");
+ dev_err(udc->dev, "Timeout for reset\n");
break;
}
cpu_relax();
@@ -1839,7 +1830,7 @@ static void reset_irq(struct fsl_udc *ud
fsl_writel(0xffffffff, &dr_regs->endptflush);
if (fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET) {
- dev_vdbg(&udc->gadget.dev, "Bus reset\n");
+ dev_vdbg(udc->dev, "Bus reset\n");
/* Bus is reseting */
udc->bus_reset = 1;
/* Reset all the queues, include XD, dTD, EP queue
@@ -1847,7 +1838,7 @@ static void reset_irq(struct fsl_udc *ud
reset_queues(udc, true);
udc->usb_state = USB_STATE_DEFAULT;
} else {
- dev_vdbg(&udc->gadget.dev, "Controller reset\n");
+ dev_vdbg(udc->dev, "Controller reset\n");
/* initialize usb hw reg except for regs for EP, not
* touch usbintr reg */
dr_controller_setup(udc);
@@ -1881,7 +1872,7 @@ static irqreturn_t fsl_udc_irq(int irq,
/* Clear notification bits */
fsl_writel(irq_src, &dr_regs->usbsts);
- /* dev_vdbg(&udc->gadget.dev, "irq_src [0x%8x]", irq_src); */
+ /* dev_vdbg(udc->dev, "irq_src [0x%8x]", irq_src); */
/* Need to resume? */
if (udc->usb_state == USB_STATE_SUSPENDED)
@@ -1890,7 +1881,7 @@ static irqreturn_t fsl_udc_irq(int irq,
/* USB Interrupt */
if (irq_src & USB_STS_INT) {
- dev_vdbg(&udc->gadget.dev, "Packet int\n");
+ dev_vdbg(udc->dev, "Packet int\n");
/* Setup package, we only support ep0 as control ep */
if (fsl_readl(&dr_regs->endptsetupstat) & EP_SETUP_STATUS_EP0) {
tripwire_handler(udc, 0,
@@ -1919,7 +1910,7 @@ static irqreturn_t fsl_udc_irq(int irq,
/* Reset Received */
if (irq_src & USB_STS_RESET) {
- dev_vdbg(&udc->gadget.dev, "reset int\n");
+ dev_vdbg(udc->dev, "reset int\n");
reset_irq(udc);
status = IRQ_HANDLED;
}
@@ -1931,7 +1922,7 @@ static irqreturn_t fsl_udc_irq(int irq,
}
if (irq_src & (USB_STS_ERR | USB_STS_SYS_ERR)) {
- dev_vdbg(&udc->gadget.dev, "Error IRQ %x\n", irq_src);
+ dev_vdbg(udc->dev, "Error IRQ %x\n", irq_src);
}
spin_unlock_irqrestore(&udc->lock, flags);
@@ -1967,7 +1958,7 @@ static int fsl_udc_start(struct usb_gadg
udc_controller->transceiver->otg,
&udc_controller->gadget);
if (retval < 0) {
- dev_err(&udc_controller->gadget.dev, "can't bind to transceiver\n");
+ dev_err(udc_controller->dev, "can't bind to transceiver\n");
udc_controller->driver = NULL;
return retval;
}
@@ -2252,7 +2243,7 @@ static int struct_udc_setup(struct fsl_u
udc->eps = kcalloc(udc->max_ep, sizeof(struct fsl_ep), GFP_KERNEL);
if (!udc->eps) {
- dev_err(&udc->gadget.dev, "kmalloc udc endpoint status failed\n");
+ dev_err(udc->dev, "kmalloc udc endpoint status failed\n");
goto eps_alloc_failed;
}
@@ -2267,7 +2258,7 @@ static int struct_udc_setup(struct fsl_u
udc->ep_qh = dma_alloc_coherent(&pdev->dev, size,
&udc->ep_qh_dma, GFP_KERNEL);
if (!udc->ep_qh) {
- dev_err(&udc->gadget.dev, "malloc QHs for udc failed\n");
+ dev_err(udc->dev, "malloc QHs for udc failed\n");
goto ep_queue_alloc_failed;
}
@@ -2278,14 +2269,14 @@ static int struct_udc_setup(struct fsl_u
udc->status_req = container_of(fsl_alloc_request(NULL, GFP_KERNEL),
struct fsl_req, req);
if (!udc->status_req) {
- dev_err(&udc->gadget.dev, "kzalloc for udc status request failed\n");
+ dev_err(udc->dev, "kzalloc for udc status request failed\n");
goto udc_status_alloc_failed;
}
/* allocate a small amount of memory to get valid address */
udc->status_req->req.buf = kmalloc(8, GFP_KERNEL);
if (!udc->status_req->req.buf) {
- dev_err(&udc->gadget.dev, "kzalloc for udc request buffer failed\n");
+ dev_err(udc->dev, "kzalloc for udc request buffer failed\n");
goto udc_req_buf_alloc_failed;
}
@@ -2373,6 +2364,7 @@ static int fsl_udc_probe(struct platform
if (udc_controller == NULL)
return -ENOMEM;
+ udc_controller->dev = &pdev->dev;
pdata = dev_get_platdata(&pdev->dev);
udc_controller->pdata = pdata;
spin_lock_init(&udc_controller->lock);
@@ -2382,7 +2374,7 @@ static int fsl_udc_probe(struct platform
if (pdata->operating_mode == FSL_USB2_DR_OTG) {
udc_controller->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
if (IS_ERR_OR_NULL(udc_controller->transceiver)) {
- dev_err(&udc_controller->gadget.dev, "Can't find OTG driver!\n");
+ dev_err(&pdev->dev, "Can't find OTG driver!\n");
ret = -ENODEV;
goto err_kfree;
}
@@ -2398,7 +2390,7 @@ static int fsl_udc_probe(struct platform
if (pdata->operating_mode == FSL_USB2_DR_DEVICE) {
if (!request_mem_region(res->start, resource_size(res),
driver_name)) {
- dev_err(&udc_controller->gadget.dev, "request mem region for %s failed\n", pdev->name);
+ dev_err(&pdev->dev, "failed to request mem region\n");
ret = -EBUSY;
goto err_kfree;
}
@@ -2429,7 +2421,7 @@ static int fsl_udc_probe(struct platform
/* Read Device Controller Capability Parameters register */
dccparams = fsl_readl(&dr_regs->dccparams);
if (!(dccparams & DCCPARAMS_DC)) {
- dev_err(&udc_controller->gadget.dev, "This SOC doesn't support device role\n");
+ dev_err(&pdev->dev, "This SOC doesn't support device role\n");
ret = -ENODEV;
goto err_exit;
}
@@ -2447,14 +2439,14 @@ static int fsl_udc_probe(struct platform
ret = request_irq(udc_controller->irq, fsl_udc_irq, IRQF_SHARED,
driver_name, udc_controller);
if (ret != 0) {
- dev_err(&udc_controller->gadget.dev, "cannot request irq %d err %d\n",
+ dev_err(&pdev->dev, "cannot request irq %d err %d\n",
udc_controller->irq, ret);
goto err_exit;
}
/* Initialize the udc structure including QH member and other member */
if (struct_udc_setup(udc_controller, pdev)) {
- dev_err(&udc_controller->gadget.dev, "Can't initialize udc data structure\n");
+ dev_err(&pdev->dev, "Can't initialize udc data structure\n");
ret = -ENOMEM;
goto err_free_irq;
}
--- a/drivers/usb/gadget/udc/fsl_usb2_udc.h
+++ b/drivers/usb/gadget/udc/fsl_usb2_udc.h
@@ -470,6 +470,7 @@ struct fsl_ep {
#define EP_DIR_OUT 0
struct fsl_udc {
+ struct device *dev;
struct usb_gadget gadget;
struct usb_gadget_driver *driver;
struct fsl_usb2_platform_data *pdata;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 585/602] usb: musb: omap2430: clean up probe error handling
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (583 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 584/602] USB: gadget: fsl-udc: fix dev_printk() device Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 586/602] usb: musb: omap2430: Do not put borrowed of_node in probe Greg Kroah-Hartman
` (20 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Johan Hovold, Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <johan@kernel.org>
commit 51d4b0a44c82e5eff056ef76acd2c3c605a8eb74 upstream.
Using numbered error labels is discouraged (e.g. as it requires
renumbering them when adding a new intermediate error path).
Rename the error labels after what they do.
While at it, drop the redundant platform allocation failure dev_err()
as the error would already have been logged by the allocator.
Signed-off-by: Johan Hovold <johan@kernel.org>
Link: https://lore.kernel.org/r/20250724091910.21092-6-johan@kernel.org
Stable-dep-of: c947360ae63e ("usb: musb: omap2430: Do not put borrowed of_node in probe")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/musb/omap2430.c | 23 ++++++++++-------------
1 file changed, 10 insertions(+), 13 deletions(-)
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -318,13 +318,11 @@ static int omap2430_probe(struct platfor
glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
if (!glue)
- goto err0;
+ return -ENOMEM;
musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
- if (!musb) {
- dev_err(&pdev->dev, "failed to allocate musb device\n");
- goto err0;
- }
+ if (!musb)
+ return -ENOMEM;
musb->dev.parent = &pdev->dev;
musb->dev.dma_mask = &omap2430_dmamask;
@@ -348,15 +346,15 @@ static int omap2430_probe(struct platfor
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
- goto err2;
+ goto err_put_musb;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
- goto err2;
+ goto err_put_musb;
config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
if (!config)
- goto err2;
+ goto err_put_musb;
of_property_read_u32(np, "mode", (u32 *)&pdata->mode);
of_property_read_u32(np, "interface-type",
@@ -379,7 +377,7 @@ static int omap2430_probe(struct platfor
if (!control_pdev) {
dev_err(&pdev->dev, "Failed to get control device\n");
ret = -EINVAL;
- goto err2;
+ goto err_put_musb;
}
glue->control_otghs = &control_pdev->dev;
}
@@ -455,22 +453,21 @@ static int omap2430_probe(struct platfor
ret = platform_device_add(musb);
if (ret) {
dev_err(&pdev->dev, "failed to register musb device\n");
- goto err3;
+ goto err_disable_rpm;
}
of_node_put(np);
return 0;
-err3:
+err_disable_rpm:
pm_runtime_disable(glue->dev);
err_put_control_otghs:
if (!IS_ERR(glue->control_otghs))
put_device(glue->control_otghs);
-err2:
+err_put_musb:
of_node_put(np);
platform_device_put(musb);
-err0:
return ret;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 586/602] usb: musb: omap2430: Do not put borrowed of_node in probe
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (584 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 585/602] usb: musb: omap2430: clean up probe error handling Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 587/602] net/mlx5e: Fix NULL pointer dereference in ioctl module EEPROM query Greg Kroah-Hartman
` (19 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, stable, Johan Hovold, Guangshuo Li,
Sasha Levin
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <lgs201920130244@gmail.com>
commit c947360ae63eee1c9eacc030dd6f5a53f717addf upstream.
omap2430_probe() stores pdev->dev.of_node in a local np variable. This is
a borrowed pointer and the probe function does not take a reference to
it.
The success and error paths nevertheless call of_node_put(np). This drops
a reference that is owned by the platform device, and can leave
pdev->dev.of_node with an unbalanced reference count.
Do not put the borrowed platform device node from omap2430_probe().
References taken for the child MUSB device are handled by the device core,
and the ctrl-module phandle reference is still released separately.
Fixes: ffbe2feac59b ("usb: musb: omap2430: Fix probe regression for missing resources")
Cc: stable <stable@kernel.org>
Reviewed-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
Link: https://patch.msgid.link/20260713114711.955253-1-lgs201920130244@gmail.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/musb/omap2430.c | 2 --
1 file changed, 2 deletions(-)
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -455,7 +455,6 @@ static int omap2430_probe(struct platfor
dev_err(&pdev->dev, "failed to register musb device\n");
goto err_disable_rpm;
}
- of_node_put(np);
return 0;
@@ -465,7 +464,6 @@ err_put_control_otghs:
if (!IS_ERR(glue->control_otghs))
put_device(glue->control_otghs);
err_put_musb:
- of_node_put(np);
platform_device_put(musb);
return ret;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 587/602] net/mlx5e: Fix NULL pointer dereference in ioctl module EEPROM query
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (585 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 586/602] usb: musb: omap2430: Do not put borrowed of_node in probe Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 588/602] gpu: Fix uninitialized buddy for built-in drivers Greg Kroah-Hartman
` (18 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Gal Pressman, Tariq Toukan,
Dragos Tatulea, Mark Bloch, Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gal Pressman <gal@nvidia.com>
commit 7d36a4a8bf62dc508bc6bb4b59727aec25064ca5 upstream.
The mlx5_query_mcia() function unconditionally dereferences the status
pointer to store the MCIA register status value.
However, mlx5e_get_module_id() passes NULL since it doesn't need the
status value.
Add a NULL check before dereferencing the status pointer to prevent a
NULL pointer dereference.
Fixes: 2e4c44b12f4d ("net/mlx5: Refactor EEPROM query error handling to return status separately")
Signed-off-by: Gal Pressman <gal@nvidia.com>
Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
Reviewed-by: Dragos Tatulea <dtatulea@nvidia.com>
Signed-off-by: Mark Bloch <mbloch@nvidia.com>
Link: https://patch.msgid.link/20251225132717.358820-4-mbloch@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/mellanox/mlx5/core/port.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
--- a/drivers/net/ethernet/mellanox/mlx5/core/port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c
@@ -393,9 +393,11 @@ static int mlx5_query_mcia(struct mlx5_c
if (err)
return err;
- *status = MLX5_GET(mcia_reg, out, status);
- if (*status)
+ if (MLX5_GET(mcia_reg, out, status)) {
+ if (status)
+ *status = MLX5_GET(mcia_reg, out, status);
return -EIO;
+ }
ptr = MLX5_ADDR_OF(mcia_reg, out, dwords);
memcpy(data, ptr, size);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 588/602] gpu: Fix uninitialized buddy for built-in drivers
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (586 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 587/602] net/mlx5e: Fix NULL pointer dereference in ioctl module EEPROM query Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 589/602] rxrpc: Disable IRQ, not BH, to take the lock for ->attend_link Greg Kroah-Hartman
` (17 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Joel Fernandes, Dave Airlie,
intel-xe, Peter Senna Tschudin, Koen Koning
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Koen Koning <koen.koning@linux.intel.com>
commit cc27314c67516c138ee3829197d1c3b998e29fae upstream.
Move buddy to the start of the link order, so its __init runs before any
other built-in drivers that may depend on it. Otherwise, a built-in
driver that tries to use the buddy allocator will run into a kernel NULL
pointer dereference because slab_blocks is uninitialized.
Specifically, this fixes drm/xe (as built-in) running into a kernel
panic during boot, because it uses buddy during device probe.
Fixes: ba110db8e1bc ("gpu: Move DRM buddy allocator one level up (part two)")
Cc: Joel Fernandes <joelagnelf@nvidia.com>
Cc: Dave Airlie <airlied@redhat.com>
Cc: intel-xe@lists.freedesktop.org
Reviewed-by: Dave Airlie <airlied@redhat.com>
Tested-by: Peter Senna Tschudin <peter.senna@linux.intel.com>
Signed-off-by: Koen Koning <koen.koning@linux.intel.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Link: https://patch.msgid.link/20260213152047.179628-1-koen.koning@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/Makefile | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/drivers/gpu/Makefile
+++ b/drivers/gpu/Makefile
@@ -2,7 +2,8 @@
# drm/tegra depends on host1x, so if both drivers are built-in care must be
# taken to initialize them in the correct order. Link order is the only way
# to ensure this currently.
+# Similarly, buddy must come first since it is used by other drivers.
+obj-$(CONFIG_GPU_BUDDY) += buddy.o
obj-y += host1x/ drm/ vga/ tests/
obj-$(CONFIG_IMX_IPUV3_CORE) += ipu-v3/
obj-$(CONFIG_TRACE_GPU_MEM) += trace/
-obj-$(CONFIG_GPU_BUDDY) += buddy.o
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 589/602] rxrpc: Disable IRQ, not BH, to take the lock for ->attend_link
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (587 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 588/602] gpu: Fix uninitialized buddy for built-in drivers Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 590/602] rxrpc: Fix locking issues with the peer record hash Greg Kroah-Hartman
` (16 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Howells, Marc Dionne,
linux-afs, Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <dhowells@redhat.com>
commit d920270a6dbf756384b125ce39c17666a7c0c9f4 upstream.
Use spin_lock_irq(), not spin_lock_bh() to take the lock when accessing the
->attend_link() to stop a delay in the I/O thread due to an interrupt being
taken in the app thread whilst that holds the lock and vice versa.
Fixes: a2ea9a907260 ("rxrpc: Use irq-disabling spinlocks between app and I/O thread")
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
Link: https://patch.msgid.link/2870146.1734037095@warthog.procyon.org.uk
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/rxrpc/io_thread.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
--- a/net/rxrpc/io_thread.c
+++ b/net/rxrpc/io_thread.c
@@ -482,9 +482,9 @@ int rxrpc_io_thread(void *data)
while ((conn = list_first_entry_or_null(&conn_attend_q,
struct rxrpc_connection,
attend_link))) {
- spin_lock_bh(&local->lock);
+ spin_lock_irq(&local->lock);
list_del_init(&conn->attend_link);
- spin_unlock_bh(&local->lock);
+ spin_unlock_irq(&local->lock);
rxrpc_input_conn_event(conn, NULL);
rxrpc_put_connection(conn, rxrpc_conn_put_poke);
}
@@ -501,9 +501,9 @@ int rxrpc_io_thread(void *data)
while ((call = list_first_entry_or_null(&call_attend_q,
struct rxrpc_call,
attend_link))) {
- spin_lock_bh(&local->lock);
+ spin_lock_irq(&local->lock);
list_del_init(&call->attend_link);
- spin_unlock_bh(&local->lock);
+ spin_unlock_irq(&local->lock);
trace_rxrpc_call_poked(call);
rxrpc_input_call_event(call);
rxrpc_put_call(call, rxrpc_call_put_poke);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 590/602] rxrpc: Fix locking issues with the peer record hash
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (588 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 589/602] rxrpc: Disable IRQ, not BH, to take the lock for ->attend_link Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 591/602] wifi: nl80211: fix nl80211_start_radar_detection return value Greg Kroah-Hartman
` (15 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Howells, Marc Dionne,
Simon Horman, linux-afs, Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <dhowells@redhat.com>
commit 71f5409176f4ffd460689eb5423a20332d00e342 upstream.
rxrpc_new_incoming_peer() can't use spin_lock_bh() whilst its caller has
interrupts disabled.
WARNING: CPU: 0 PID: 1550 at kernel/softirq.c:369 __local_bh_enable_ip+0x46/0xd0
...
Call Trace:
rxrpc_alloc_incoming_call+0x1b0/0x400
rxrpc_new_incoming_call+0x1dd/0x5e0
rxrpc_input_packet+0x84a/0x920
rxrpc_io_thread+0x40d/0xb40
kthread+0x2ec/0x300
ret_from_fork+0x24/0x40
ret_from_fork_asm+0x1a/0x30
</TASK>
irq event stamp: 1811
hardirqs last enabled at (1809): _raw_spin_unlock_irq+0x24/0x50
hardirqs last disabled at (1810): _raw_read_lock_irq+0x17/0x70
softirqs last enabled at (1182): handle_softirqs+0x3ee/0x430
softirqs last disabled at (1811): rxrpc_new_incoming_peer+0x56/0x120
Fix this by using a plain spin_lock() instead. IRQs are held, so softirqs
can't happen.
Fixes: a2ea9a907260 ("rxrpc: Use irq-disabling spinlocks between app and I/O thread")
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
Link: https://patch.msgid.link/20250218192250.296870-4-dhowells@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/rxrpc/peer_object.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/net/rxrpc/peer_object.c
+++ b/net/rxrpc/peer_object.c
@@ -314,10 +314,10 @@ void rxrpc_new_incoming_peer(struct rxrp
hash_key = rxrpc_peer_hash_key(local, &peer->srx);
rxrpc_init_peer(local, peer, hash_key);
- spin_lock_bh(&rxnet->peer_hash_lock);
+ spin_lock(&rxnet->peer_hash_lock);
hash_add_rcu(rxnet->peer_hash, &peer->hash_link, hash_key);
list_add_tail(&peer->keepalive_link, &rxnet->peer_keepalive_new);
- spin_unlock_bh(&rxnet->peer_hash_lock);
+ spin_unlock(&rxnet->peer_hash_lock);
}
/*
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 591/602] wifi: nl80211: fix nl80211_start_radar_detection return value
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (589 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 590/602] rxrpc: Fix locking issues with the peer record hash Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 592/602] net: ethernet: Remove accidental duplication in Kconfig file Greg Kroah-Hartman
` (14 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Nicolas Escande, Johannes Berg
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolas Escande <nico.escande@gmail.com>
commit 22159143ff99883667f340998cfbb52b4aaac14c upstream.
Since the wiphy_guard changes, rdev_start_radar_detection's return value
in nl80211_start_radar_detection is ignored and we always returned 0.
Fixes: f42d22d3f796 ("wifi: cfg80211: define and use wiphy guard")
Signed-off-by: Nicolas Escande <nico.escande@gmail.com>
Link: https://patch.msgid.link/20250109161040.325742-1-nico.escande@gmail.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/wireless/nl80211.c | 37 +++++++++++++++++++------------------
1 file changed, 19 insertions(+), 18 deletions(-)
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -10140,25 +10140,26 @@ static int nl80211_start_radar_detection
err = rdev_start_radar_detection(rdev, dev, &chandef, cac_time_ms,
link_id);
- if (!err) {
- switch (wdev->iftype) {
- case NL80211_IFTYPE_AP:
- case NL80211_IFTYPE_P2P_GO:
- wdev->links[0].ap.chandef = chandef;
- break;
- case NL80211_IFTYPE_ADHOC:
- wdev->u.ibss.chandef = chandef;
- break;
- case NL80211_IFTYPE_MESH_POINT:
- wdev->u.mesh.chandef = chandef;
- break;
- default:
- break;
- }
- wdev->links[link_id].cac_started = true;
- wdev->links[link_id].cac_start_time = jiffies;
- wdev->links[link_id].cac_time_ms = cac_time_ms;
+ if (err)
+ return err;
+
+ switch (wdev->iftype) {
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_P2P_GO:
+ wdev->links[0].ap.chandef = chandef;
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ wdev->u.ibss.chandef = chandef;
+ break;
+ case NL80211_IFTYPE_MESH_POINT:
+ wdev->u.mesh.chandef = chandef;
+ break;
+ default:
+ break;
}
+ wdev->links[link_id].cac_started = true;
+ wdev->links[link_id].cac_start_time = jiffies;
+ wdev->links[link_id].cac_time_ms = cac_time_ms;
return 0;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 592/602] net: ethernet: Remove accidental duplication in Kconfig file
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (590 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 591/602] wifi: nl80211: fix nl80211_start_radar_detection return value Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 593/602] afs: Set vllist to NULL if addr parsing fails Greg Kroah-Hartman
` (13 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Lukas Bulwahn, Lorenzo Bianconi,
Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lukas Bulwahn <lukas.bulwahn@redhat.com>
commit e2537326e3b6b1bb18f834ebb80b8453c0018883 upstream.
Commit fb3dda82fd38 ("net: airoha: Move airoha_eth driver in a dedicated
folder") accidentally added the line:
source "drivers/net/ethernet/mellanox/Kconfig"
in drivers/net/ethernet/Kconfig, so that this line is duplicated in that
file.
Remove this accidental duplication.
Fixes: fb3dda82fd38 ("net: airoha: Move airoha_eth driver in a dedicated folder")
Signed-off-by: Lukas Bulwahn <lukas.bulwahn@redhat.com>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20250306094753.63806-1-lukas.bulwahn@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/Kconfig | 1 -
1 file changed, 1 deletion(-)
--- a/drivers/net/ethernet/Kconfig
+++ b/drivers/net/ethernet/Kconfig
@@ -21,7 +21,6 @@ source "drivers/net/ethernet/adaptec/Kco
source "drivers/net/ethernet/aeroflex/Kconfig"
source "drivers/net/ethernet/agere/Kconfig"
source "drivers/net/ethernet/airoha/Kconfig"
-source "drivers/net/ethernet/mellanox/Kconfig"
source "drivers/net/ethernet/alacritech/Kconfig"
source "drivers/net/ethernet/allwinner/Kconfig"
source "drivers/net/ethernet/alteon/Kconfig"
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 593/602] afs: Set vllist to NULL if addr parsing fails
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (591 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 592/602] net: ethernet: Remove accidental duplication in Kconfig file Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 594/602] dpll: fix clock quality level reporting Greg Kroah-Hartman
` (12 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, syzbot+5c042fbab0b292c98fc6,
Edward Adam Davis, David Howells, Marc Dionne, linux-afs,
linux-fsdevel, Christian Brauner
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Edward Adam Davis <eadavis@qq.com>
commit 8b3c655fa2406b9853138142746a39b7615c54a2 upstream.
syzbot reported a bug in in afs_put_vlserverlist.
kAFS: bad VL server IP address
BUG: unable to handle page fault for address: fffffffffffffffa
...
Oops: Oops: 0002 [#1] SMP KASAN PTI
...
RIP: 0010:refcount_dec_and_test include/linux/refcount.h:450 [inline]
RIP: 0010:afs_put_vlserverlist+0x3a/0x220 fs/afs/vl_list.c:67
...
Call Trace:
<TASK>
afs_alloc_cell fs/afs/cell.c:218 [inline]
afs_lookup_cell+0x12a5/0x1680 fs/afs/cell.c:264
afs_cell_init+0x17a/0x380 fs/afs/cell.c:386
afs_proc_rootcell_write+0x21f/0x290 fs/afs/proc.c:247
proc_simple_write+0x114/0x1b0 fs/proc/generic.c:825
pde_write fs/proc/inode.c:330 [inline]
proc_reg_write+0x23d/0x330 fs/proc/inode.c:342
vfs_write+0x25c/0x1180 fs/read_write.c:682
ksys_write+0x12a/0x240 fs/read_write.c:736
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xcd/0x260 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Because afs_parse_text_addrs() parses incorrectly, its return value -EINVAL
is assigned to vllist, which results in -EINVAL being used as the vllist
address when afs_put_vlserverlist() is executed.
Set the vllist value to NULL when a parsing error occurs to avoid this
issue.
Fixes: e2c2cb8ef07a ("afs: Simplify cell record handling")
Reported-by: syzbot+5c042fbab0b292c98fc6@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=5c042fbab0b292c98fc6
Tested-by: syzbot+5c042fbab0b292c98fc6@syzkaller.appspotmail.com
Signed-off-by: Edward Adam Davis <eadavis@qq.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Link: https://lore.kernel.org/4119365.1753108011@warthog.procyon.org.uk
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
cc: linux-fsdevel@vger.kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/afs/cell.c | 1 +
1 file changed, 1 insertion(+)
--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -177,6 +177,7 @@ static struct afs_cell *afs_alloc_cell(s
VL_SERVICE, AFS_VL_PORT);
if (IS_ERR(vllist)) {
ret = PTR_ERR(vllist);
+ vllist = NULL;
goto parse_failed;
}
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 594/602] dpll: fix clock quality level reporting
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (592 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 593/602] afs: Set vllist to NULL if addr parsing fails Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 595/602] afs: Fix delayed allocation of a cells anonymous key Greg Kroah-Hartman
` (11 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Ivan Vecera, Arkadiusz Kubalewski,
Jakub Kicinski
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ivan Vecera <ivecera@redhat.com>
commit 70d99623d5c11e1a9bcc564b8fbad6fa916913d8 upstream.
The DPLL_CLOCK_QUALITY_LEVEL_ITU_OPT1_EPRC is not reported via netlink
due to bug in dpll_msg_add_clock_quality_level(). The usage of
DPLL_CLOCK_QUALITY_LEVEL_MAX for both DECLARE_BITMAP() and
for_each_set_bit() is not correct because these macros requires bitmap
size and not the highest valid bit in the bitmap.
Use correct bitmap size to fix this issue.
Fixes: a1afb959add1 ("dpll: add clock quality level attribute and op")
Signed-off-by: Ivan Vecera <ivecera@redhat.com>
Reviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Link: https://patch.msgid.link/20250912093331.862333-1-ivecera@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/dpll/dpll_netlink.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/dpll/dpll_netlink.c
+++ b/drivers/dpll/dpll_netlink.c
@@ -191,8 +191,8 @@ static int
dpll_msg_add_clock_quality_level(struct sk_buff *msg, struct dpll_device *dpll,
struct netlink_ext_ack *extack)
{
+ DECLARE_BITMAP(qls, DPLL_CLOCK_QUALITY_LEVEL_MAX + 1) = { 0 };
const struct dpll_device_ops *ops = dpll_device_ops(dpll);
- DECLARE_BITMAP(qls, DPLL_CLOCK_QUALITY_LEVEL_MAX) = { 0 };
enum dpll_clock_quality_level ql;
int ret;
@@ -201,7 +201,7 @@ dpll_msg_add_clock_quality_level(struct
ret = ops->clock_quality_level_get(dpll, dpll_priv(dpll), qls, extack);
if (ret)
return ret;
- for_each_set_bit(ql, qls, DPLL_CLOCK_QUALITY_LEVEL_MAX)
+ for_each_set_bit(ql, qls, DPLL_CLOCK_QUALITY_LEVEL_MAX + 1)
if (nla_put_u32(msg, DPLL_A_CLOCK_QUALITY_LEVEL, ql))
return -EMSGSIZE;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 595/602] afs: Fix delayed allocation of a cells anonymous key
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (593 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 594/602] dpll: fix clock quality level reporting Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 596/602] afs: handle CB.InitCallBackState3 requests without a server record Greg Kroah-Hartman
` (10 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, syzbot+41c68824eefb67cdf00c,
David Howells, Marc Dionne, linux-afs, linux-fsdevel,
Christian Brauner
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <dhowells@redhat.com>
commit d27c71257825dced46104eefe42e4d9964bd032e upstream.
The allocation of a cell's anonymous key is done in a background thread
along with other cell setup such as doing a DNS upcall. In the reported
bug, this is triggered by afs_parse_source() parsing the device name given
to mount() and calling afs_lookup_cell() with the name of the cell.
The normal key lookup then tries to use the key description on the
anonymous authentication key as the reference for request_key() - but it
may not yet be set and so an oops can happen.
This has been made more likely to happen by the fix for dynamic lookup
failure.
Fix this by firstly allocating a reference name and attaching it to the
afs_cell record when the record is created. It can share the memory
allocation with the cell name (unfortunately it can't just overlap the cell
name by prepending it with "afs@" as the cell name already has a '.'
prepended for other purposes). This reference name is then passed to
request_key().
Secondly, the anon key is now allocated on demand at the point a key is
requested in afs_request_key() if it is not already allocated. A mutex is
used to prevent multiple allocation for a cell.
Thirdly, make afs_request_key_rcu() return NULL if the anonymous key isn't
yet allocated (if we need it) and then the caller can return -ECHILD to
drop out of RCU-mode and afs_request_key() can be called.
Note that the anonymous key is kind of necessary to make the key lookup
cache work as that doesn't currently cache a negative lookup, but it's
probably worth some investigation to see if NULL can be used instead.
Fixes: 330e2c514823 ("afs: Fix dynamic lookup to fail on cell lookup failure")
Reported-by: syzbot+41c68824eefb67cdf00c@syzkaller.appspotmail.com
Signed-off-by: David Howells <dhowells@redhat.com>
Link: https://patch.msgid.link/800328.1764325145@warthog.procyon.org.uk
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
cc: linux-fsdevel@vger.kernel.org
Signed-off-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/afs/cell.c | 43 ++++++++-----------------------------------
fs/afs/internal.h | 1 +
fs/afs/security.c | 48 ++++++++++++++++++++++++++++++++++++++++--------
3 files changed, 49 insertions(+), 43 deletions(-)
--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -140,7 +140,9 @@ static struct afs_cell *afs_alloc_cell(s
return ERR_PTR(-ENOMEM);
}
- cell->name = kmalloc(1 + namelen + 1, GFP_KERNEL);
+ /* Allocate the cell name and the key name in one go. */
+ cell->name = kmalloc(1 + namelen + 1 +
+ 4 + namelen + 1, GFP_KERNEL);
if (!cell->name) {
kfree(cell);
return ERR_PTR(-ENOMEM);
@@ -151,7 +153,11 @@ static struct afs_cell *afs_alloc_cell(s
cell->name_len = namelen;
for (i = 0; i < namelen; i++)
cell->name[i] = tolower(name[i]);
- cell->name[i] = 0;
+ cell->name[i++] = 0;
+
+ cell->key_desc = cell->name + i;
+ memcpy(cell->key_desc, "afs@", 4);
+ memcpy(cell->key_desc + 4, cell->name, cell->name_len + 1);
cell->net = net;
refcount_set(&cell->ref, 1);
@@ -719,33 +725,6 @@ void afs_set_cell_timer(struct afs_cell
}
/*
- * Allocate a key to use as a placeholder for anonymous user security.
- */
-static int afs_alloc_anon_key(struct afs_cell *cell)
-{
- struct key *key;
- char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp;
-
- /* Create a key to represent an anonymous user. */
- memcpy(keyname, "afs@", 4);
- dp = keyname + 4;
- cp = cell->name;
- do {
- *dp++ = tolower(*cp);
- } while (*cp++);
-
- key = rxrpc_get_null_key(keyname);
- if (IS_ERR(key))
- return PTR_ERR(key);
-
- cell->anonymous_key = key;
-
- _debug("anon key %p{%x}",
- cell->anonymous_key, key_serial(cell->anonymous_key));
- return 0;
-}
-
-/*
* Activate a cell.
*/
static int afs_activate_cell(struct afs_net *net, struct afs_cell *cell)
@@ -754,12 +733,6 @@ static int afs_activate_cell(struct afs_
struct afs_cell *pcell;
int ret;
- if (!cell->anonymous_key) {
- ret = afs_alloc_anon_key(cell);
- if (ret < 0)
- return ret;
- }
-
ret = afs_proc_cell_setup(cell);
if (ret < 0)
return ret;
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -423,6 +423,7 @@ struct afs_cell {
u8 name_len; /* Length of name */
char *name; /* Cell name, case-flattened and NUL-padded */
+ char *key_desc; /* Authentication key description */
};
/*
--- a/fs/afs/security.c
+++ b/fs/afs/security.c
@@ -16,6 +16,30 @@
static DEFINE_HASHTABLE(afs_permits_cache, 10);
static DEFINE_SPINLOCK(afs_permits_lock);
+static DEFINE_MUTEX(afs_key_lock);
+
+/*
+ * Allocate a key to use as a placeholder for anonymous user security.
+ */
+static int afs_alloc_anon_key(struct afs_cell *cell)
+{
+ struct key *key;
+
+ mutex_lock(&afs_key_lock);
+ if (!cell->anonymous_key) {
+ key = rxrpc_get_null_key(cell->key_desc);
+ if (!IS_ERR(key))
+ cell->anonymous_key = key;
+ }
+ mutex_unlock(&afs_key_lock);
+
+ if (IS_ERR(key))
+ return PTR_ERR(key);
+
+ _debug("anon key %p{%x}",
+ cell->anonymous_key, key_serial(cell->anonymous_key));
+ return 0;
+}
/*
* get a key
@@ -23,11 +47,12 @@ static DEFINE_SPINLOCK(afs_permits_lock)
struct key *afs_request_key(struct afs_cell *cell)
{
struct key *key;
+ int ret;
- _enter("{%x}", key_serial(cell->anonymous_key));
+ _enter("{%s}", cell->key_desc);
- _debug("key %s", cell->anonymous_key->description);
- key = request_key_net(&key_type_rxrpc, cell->anonymous_key->description,
+ _debug("key %s", cell->key_desc);
+ key = request_key_net(&key_type_rxrpc, cell->key_desc,
cell->net->net, NULL);
if (IS_ERR(key)) {
if (PTR_ERR(key) != -ENOKEY) {
@@ -35,6 +60,12 @@ struct key *afs_request_key(struct afs_c
return key;
}
+ if (!cell->anonymous_key) {
+ ret = afs_alloc_anon_key(cell);
+ if (ret < 0)
+ return ERR_PTR(ret);
+ }
+
/* act as anonymous user */
_leave(" = {%x} [anon]", key_serial(cell->anonymous_key));
return key_get(cell->anonymous_key);
@@ -52,11 +83,10 @@ struct key *afs_request_key_rcu(struct a
{
struct key *key;
- _enter("{%x}", key_serial(cell->anonymous_key));
+ _enter("{%s}", cell->key_desc);
- _debug("key %s", cell->anonymous_key->description);
- key = request_key_net_rcu(&key_type_rxrpc,
- cell->anonymous_key->description,
+ _debug("key %s", cell->key_desc);
+ key = request_key_net_rcu(&key_type_rxrpc, cell->key_desc,
cell->net->net);
if (IS_ERR(key)) {
if (PTR_ERR(key) != -ENOKEY) {
@@ -65,6 +95,8 @@ struct key *afs_request_key_rcu(struct a
}
/* act as anonymous user */
+ if (!cell->anonymous_key)
+ return NULL; /* Need to allocate */
_leave(" = {%x} [anon]", key_serial(cell->anonymous_key));
return key_get(cell->anonymous_key);
} else {
@@ -408,7 +440,7 @@ int afs_permission(struct mnt_idmap *idm
if (mask & MAY_NOT_BLOCK) {
key = afs_request_key_rcu(vnode->volume->cell);
- if (IS_ERR(key))
+ if (IS_ERR_OR_NULL(key))
return -ECHILD;
ret = -ECHILD;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 596/602] afs: handle CB.InitCallBackState3 requests without a server record
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (594 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 595/602] afs: Fix delayed allocation of a cells anonymous key Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 597/602] Bluetooth: hci_conn: Fix running bis_cleanup for hci_conn->type PA_LINK Greg Kroah-Hartman
` (9 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, stable, Yuan Tan, Yifan Wu,
Juefei Pu, Xin Liu, Nan Li, Ren Wei, David Howells, Marc Dionne,
linux-afs, Christian Brauner (Amutable)
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nan Li <tonanli66@gmail.com>
commit f3cf725cd284b7912d5522babb44721bf38c8887 upstream.
The cache manager callback path now attaches the server record to an
incoming call through the rxrpc peer's app data. That association is
not guaranteed to exist for every callback request, and most callback
handlers already tolerate that case.
Make CB.InitCallBackState3 follow the same pattern by checking whether a
server record was attached before using it. If the peer is not mapped
to a server record, trace the request and ignore it, matching the
existing behaviour for other unmatched callback requests.
This keeps the callback handler consistent with the rest of the cache
manager service and avoids depending on peer state that may not be
available for a given request.
Fixes: 40e8b52fe8c8 ("afs: Use the per-peer app data provided by rxrpc")
Cc: stable@kernel.org
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Signed-off-by: Nan Li <tonanli66@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
Signed-off-by: David Howells <dhowells@redhat.com>
Link: https://patch.msgid.link/20260622090856.2746629-2-dhowells@redhat.com
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/afs/cmservice.c | 5 +++++
1 file changed, 5 insertions(+)
--- a/fs/afs/cmservice.c
+++ b/fs/afs/cmservice.c
@@ -369,6 +369,11 @@ static int afs_deliver_cb_init_call_back
return 0;
}
+ if (!call->server) {
+ trace_afs_cm_no_server_u(call, call->request);
+ return 0;
+ }
+
if (memcmp(call->request, &call->server->_uuid, sizeof(call->server->_uuid)) != 0) {
pr_notice("Callback UUID does not match fileserver UUID\n");
trace_afs_cm_no_server_u(call, call->request);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 597/602] Bluetooth: hci_conn: Fix running bis_cleanup for hci_conn->type PA_LINK
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (595 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 596/602] afs: handle CB.InitCallBackState3 requests without a server record Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 598/602] Bluetooth: hci_conn: Fix not cleaning up Broadcaster/Broadcast Source Greg Kroah-Hartman
` (8 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Luiz Augusto von Dentz
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
commit d36349ea73d805bb72cbc24ab90cb1da4ad5c379 upstream.
Connections with type of PA_LINK shall be considered temporary just to
track the lifetime of PA Sync setup, once the BIG Sync is established
and connection are created with BIS_LINK the existing PA_LINK
connection shall not longer use bis_cleanup otherwise it terminates the
PA Sync when that shall be left to BIS_LINK connection to do it.
Fixes: a7bcffc673de ("Bluetooth: Add PA_LINK to distinguish BIG sync and PA sync connections")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/bluetooth/hci_conn.c | 10 +++++++++-
net/bluetooth/hci_event.c | 7 ++++++-
2 files changed, 15 insertions(+), 2 deletions(-)
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -830,7 +830,15 @@ static void bis_cleanup(struct hci_conn
/* Check if ISO connection is a BIS and terminate advertising
* set and BIG if there are no other connections using it.
*/
- bis = hci_conn_hash_lookup_big(hdev, conn->iso_qos.bcast.big);
+ bis = hci_conn_hash_lookup_big_state(hdev,
+ conn->iso_qos.bcast.big,
+ BT_CONNECTED);
+ if (bis)
+ return;
+
+ bis = hci_conn_hash_lookup_big_state(hdev,
+ conn->iso_qos.bcast.big,
+ BT_CONNECT);
if (bis)
return;
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -7026,9 +7026,14 @@ static void hci_le_big_sync_established_
continue;
}
- if (ev->status != 0x42)
+ if (ev->status != 0x42) {
/* Mark PA sync as established */
set_bit(HCI_CONN_PA_SYNC, &bis->flags);
+ /* Reset cleanup callback of PA Sync so it doesn't
+ * terminate the sync when deleting the connection.
+ */
+ conn->cleanup = NULL;
+ }
bis->sync_handle = conn->sync_handle;
bis->iso_qos.bcast.big = ev->handle;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 598/602] Bluetooth: hci_conn: Fix not cleaning up Broadcaster/Broadcast Source
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (596 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 597/602] Bluetooth: hci_conn: Fix running bis_cleanup for hci_conn->type PA_LINK Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 599/602] Bluetooth: hci_conn: Fix not cleaning up PA_LINK connections Greg Kroah-Hartman
` (7 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Luiz Augusto von Dentz
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
commit 3ba486c5f3ce2c22ffd29c0103404cdbe21912b3 upstream.
This fixes Broadcaster/Broadcast Source not sending HCI_OP_LE_TERM_BIG
because HCI_CONN_PER_ADV where not being set.
Fixes: a7bcffc673de ("Bluetooth: Add PA_LINK to distinguish BIG sync and PA sync connections")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/bluetooth/hci_conn.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -2277,7 +2277,7 @@ struct hci_conn *hci_connect_bis(struct
* the start periodic advertising and create BIG commands have
* been queued
*/
- hci_conn_hash_list_state(hdev, bis_mark_per_adv, PA_LINK,
+ hci_conn_hash_list_state(hdev, bis_mark_per_adv, BIS_LINK,
BT_BOUND, &data);
/* Queue start periodic advertising and create BIG */
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 599/602] Bluetooth: hci_conn: Fix not cleaning up PA_LINK connections
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (597 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 598/602] Bluetooth: hci_conn: Fix not cleaning up Broadcaster/Broadcast Source Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 600/602] Bluetooth: hci_conn: Fix memory leak in hci_le_big_terminate() Greg Kroah-Hartman
` (6 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Luiz Augusto von Dentz
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
commit 41bf23338a501e745c398e0faee948dd05d0be98 upstream.
Contrary to what was stated on d36349ea73d8 ("Bluetooth: hci_conn:
Fix running bis_cleanup for hci_conn->type PA_LINK") the PA_LINK does
in fact needs to run bis_cleanup in order to terminate the PA Sync,
since that is bond to the listening socket which is the entity that
controls the lifetime of PA Sync, so if it is closed/released the PA
Sync shall be terminated, terminating the PA Sync shall not result in
the BIG Sync being terminated since once the later is established it
doesn't depend on the former anymore.
If the use user wants to reconnect/rebind a number of BIS(s) it shall
keep the socket open until it no longer needs the PA Sync, which means
it retains full control of the lifetime of both PA and BIG Syncs.
Fixes: d36349ea73d8 ("Bluetooth: hci_conn: Fix running bis_cleanup for hci_conn->type PA_LINK")
Fixes: a7bcffc673de ("Bluetooth: Add PA_LINK to distinguish BIG sync and PA sync connections")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/bluetooth/hci_conn.c | 33 +++++++++++++++++++--------------
net/bluetooth/hci_event.c | 7 +------
net/bluetooth/hci_sync.c | 2 +-
3 files changed, 21 insertions(+), 21 deletions(-)
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -770,21 +770,23 @@ static void find_bis(struct hci_conn *co
d->count++;
}
-static int hci_le_big_terminate(struct hci_dev *hdev, u8 big, struct hci_conn *conn)
+static int hci_le_big_terminate(struct hci_dev *hdev, struct hci_conn *conn)
{
struct iso_list_data *d;
int ret;
- bt_dev_dbg(hdev, "big 0x%2.2x sync_handle 0x%4.4x", big, conn->sync_handle);
+ bt_dev_dbg(hdev, "hcon %p big 0x%2.2x sync_handle 0x%4.4x", conn,
+ conn->iso_qos.bcast.big, conn->sync_handle);
d = kzalloc(sizeof(*d), GFP_KERNEL);
if (!d)
return -ENOMEM;
- d->big = big;
+ d->big = conn->iso_qos.bcast.big;
d->sync_handle = conn->sync_handle;
- if (test_and_clear_bit(HCI_CONN_PA_SYNC, &conn->flags)) {
+ if (conn->type == PA_LINK &&
+ test_and_clear_bit(HCI_CONN_PA_SYNC, &conn->flags)) {
hci_conn_hash_list_flag(hdev, find_bis, PA_LINK,
HCI_CONN_PA_SYNC, d);
@@ -802,6 +804,9 @@ static int hci_le_big_terminate(struct h
d->big_sync_term = true;
}
+ if (!d->pa_sync_term && !d->big_sync_term)
+ return 0;
+
ret = hci_cmd_sync_queue(hdev, big_terminate_sync, d,
terminate_big_destroy);
if (ret)
@@ -844,8 +849,7 @@ static void bis_cleanup(struct hci_conn
hci_le_terminate_big(hdev, conn);
} else {
- hci_le_big_terminate(hdev, conn->iso_qos.bcast.big,
- conn);
+ hci_le_big_terminate(hdev, conn);
}
}
@@ -988,19 +992,20 @@ static struct hci_conn *__hci_conn_add(s
conn->mtu = hdev->le_mtu ? hdev->le_mtu : hdev->acl_mtu;
break;
case CIS_LINK:
- case BIS_LINK:
- case PA_LINK:
/* conn->src should reflect the local identity address */
hci_copy_identity_address(hdev, &conn->src, &conn->src_type);
- /* set proper cleanup function */
- if (!bacmp(dst, BDADDR_ANY))
- conn->cleanup = bis_cleanup;
- else if (conn->role == HCI_ROLE_MASTER)
+ if (conn->role == HCI_ROLE_MASTER)
conn->cleanup = cis_cleanup;
- conn->mtu = hdev->iso_mtu ? hdev->iso_mtu :
- hdev->le_mtu ? hdev->le_mtu : hdev->acl_mtu;
+ conn->mtu = hdev->iso_mtu;
+ break;
+ case PA_LINK:
+ case BIS_LINK:
+ /* conn->src should reflect the local identity address */
+ hci_copy_identity_address(hdev, &conn->src, &conn->src_type);
+ conn->cleanup = bis_cleanup;
+ conn->mtu = hdev->iso_mtu;
break;
case SCO_LINK:
if (lmp_esco_capable(hdev))
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -7026,14 +7026,9 @@ static void hci_le_big_sync_established_
continue;
}
- if (ev->status != 0x42) {
+ if (ev->status != 0x42)
/* Mark PA sync as established */
set_bit(HCI_CONN_PA_SYNC, &bis->flags);
- /* Reset cleanup callback of PA Sync so it doesn't
- * terminate the sync when deleting the connection.
- */
- conn->cleanup = NULL;
- }
bis->sync_handle = conn->sync_handle;
bis->iso_qos.bcast.big = ev->handle;
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -7150,7 +7150,7 @@ static void create_pa_complete(struct hc
hci_dev_lock(hdev);
- if (!hci_conn_valid(hdev, conn))
+ if (hci_conn_valid(hdev, conn))
clear_bit(HCI_CONN_CREATE_PA_SYNC, &conn->flags);
if (!err)
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 600/602] Bluetooth: hci_conn: Fix memory leak in hci_le_big_terminate()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (598 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 599/602] Bluetooth: hci_conn: Fix not cleaning up PA_LINK connections Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 601/602] afs: Fix uninit var in afs_alloc_anon_key() Greg Kroah-Hartman
` (5 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Pavitra Jha, Luiz Augusto von Dentz
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pavitra Jha <jhapavitra98@gmail.com>
commit bfa9d28960ed677d556bdf097073bc3129686229 upstream.
hci_le_big_terminate() allocates iso_list_data via kzalloc_obj but
returns 0 without freeing it when neither pa_sync_term nor big_sync_term
flags are set after evaluating the PA and BIG sync connection state.
This early-return path was introduced when hci_le_big_terminate() was
refactored to take struct hci_conn instead of raw u8 parameters, adding
PA/BIG flag evaluation logic. The existing kfree() on hci_cmd_sync_queue
failure does not cover this path.
Fixes: a7bcffc673de ("Bluetooth: Add PA_LINK to distinguish BIG sync and PA sync connections")
Cc: stable@vger.kernel.org
Signed-off-by: Pavitra Jha <jhapavitra98@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/bluetooth/hci_conn.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -804,8 +804,10 @@ static int hci_le_big_terminate(struct h
d->big_sync_term = true;
}
- if (!d->pa_sync_term && !d->big_sync_term)
+ if (!d->pa_sync_term && !d->big_sync_term) {
+ kfree(d);
return 0;
+ }
ret = hci_cmd_sync_queue(hdev, big_terminate_sync, d,
terminate_big_destroy);
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 601/602] afs: Fix uninit var in afs_alloc_anon_key()
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (599 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 600/602] Bluetooth: hci_conn: Fix memory leak in hci_le_big_terminate() Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 602/602] KVM: SVM: Bump asid_generation on CPU online to avoid ASID collision after hotplug Greg Kroah-Hartman
` (4 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Paulo Alcantra, David Howells,
Marc Dionne, syzbot+41c68824eefb67cdf00c, linux-afs,
linux-fsdevel, Linus Torvalds
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <dhowells@redhat.com>
commit 19eef1d98eeda3745df35839190b7d4a4adea656 upstream.
Fix an uninitialised variable (key) in afs_alloc_anon_key() by setting it
to cell->anonymous_key. Without this change, the error check may return a
false failure with a bad error number.
Most of the time this is unlikely to happen because the first encounter
with afs_alloc_anon_key() will usually be from (auto)mount, for which all
subsequent operations must wait - apart from other (auto)mounts. Once the
call->anonymous_key is allocated, all further calls to afs_request_key()
will skip the call to afs_alloc_anon_key() for that cell.
Fixes: d27c71257825 ("afs: Fix delayed allocation of a cell's anonymous key")
Reported-by: Paulo Alcantra <pc@manguebit.org>
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Paulo Alcantara <pc@manguebit.org>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: syzbot+41c68824eefb67cdf00c@syzkaller.appspotmail.com
cc: linux-afs@lists.infradead.org
cc: linux-fsdevel@vger.kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/afs/security.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/fs/afs/security.c
+++ b/fs/afs/security.c
@@ -26,7 +26,8 @@ static int afs_alloc_anon_key(struct afs
struct key *key;
mutex_lock(&afs_key_lock);
- if (!cell->anonymous_key) {
+ key = cell->anonymous_key;
+ if (!key) {
key = rxrpc_get_null_key(cell->key_desc);
if (!IS_ERR(key))
cell->anonymous_key = key;
^ permalink raw reply [flat|nested] 608+ messages in thread
* [PATCH 6.12 602/602] KVM: SVM: Bump asid_generation on CPU online to avoid ASID collision after hotplug
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (600 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 601/602] afs: Fix uninit var in afs_alloc_anon_key() Greg Kroah-Hartman
@ 2026-07-30 14:16 ` Greg Kroah-Hartman
2026-07-30 17:37 ` [PATCH 6.12 000/602] 6.12.101-rc1 review Florian Fainelli
` (3 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Greg Kroah-Hartman @ 2026-07-30 14:16 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Chandrakanth Silveru,
Srikanth Aithal, K Prateek Nayak, Tom Lendacky, Nikunj A Dadhania,
Paolo Bonzini
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikunj A Dadhania <nikunj@amd.com>
commit 25f744ffa0c8e799e06250ce2e618367b166b0d4 upstream.
If a vCPU stays scheduled out (or blocked) while the last pCPU it ran
on goes through a hotplug cycle (online->offline->online), and the vCPU
then resumes execution on the same pCPU, then it is possible for it to
run with an ASID that has now been assigned to a different vCPU,
resulting in stale TLB translations being used.
svm_enable_virtualization_cpu() resets asid_generation to 1 and sets
next_asid to max_asid + 1 on every CPU online event, including hotplug
cycles. Because next_asid starts beyond the pool boundary, the first
call to new_asid() after an online event always wraps the pool,
incrementing asid_generation to 2 and assigning ASIDs starting from
min_asid.
Consider two vCPUs from different VMs, vCPU-A pinned to CPU-X holding
asid_generation=2 and ASID=N from before the hotplug event:
1. CPU-X goes offline and back online: asid_generation resets to 1,
next_asid = max_asid + 1.
2. One or more vCPUs migrate to CPU-X and call new_asid(), wrapping
the pool and consuming ASIDs starting from min_asid. Eventually
vCPU-B from a different VM is assigned asid_generation=2, ASID=N
— the same ASID that vCPU-A held before the hotplug.
3. vCPU-A enters pre_svm_run() on CPU-X: current_vmcb->cpu is
unchanged so the migration branch is skipped. Its saved
asid_generation=2 matches sd->asid_generation=2, so the generation
check silently passes and vCPU-A continues running with ASID=N —
the same ASID just freshly assigned to vCPU-B.
Both vCPUs from different VMs now run on CPU-X with the same ASID,
causing them to share NPT TLB entries and producing stale translations.
The collision manifests as a KVM internal error (Suberror: 1, emulation
failure). The NPT page fault reports a faulting GPA far outside the
VM's physical memory range — a sign of stale TLB translations being
used. KVM falls back to instruction emulation, which fails on
FPU/XSave instructions (XRSTOR, STMXCSR) that the emulator does not
implement.
Fix this by incrementing asid_generation instead of resetting it to 1
in svm_enable_virtualization_cpu(). On module load, asid_generation
starts at 0 (memset) and the increment produces 1, identical to the
old behaviour. On subsequent hotplug cycles the generation advances
beyond any value a vCPU previously observed on this CPU, so the
generation check in pre_svm_run() reliably forces new_asid() on every
vCPU after every hotplug cycle.
Fixes: 774c47f1d78e ("[PATCH] KVM: cpu hotplug support")
Reported-by: Chandrakanth Silveru <Chandrakanth.Silveru@amd.com>
Tested-by: Srikanth Aithal <Srikanth.Aithal@amd.com>
Reviewed-by: K Prateek Nayak <kprateek.nayak@amd.com>
Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Nikunj A Dadhania <nikunj@amd.com>
Message-ID: <20260715063506.672432-1-nikunj@amd.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/x86/kvm/svm/svm.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -626,7 +626,12 @@ static int svm_enable_virtualization_cpu
return -EBUSY;
sd = per_cpu_ptr(&svm_data, me);
- sd->asid_generation = 1;
+ /*
+ * Bump the current asid_generation value to ensure any vCPU that
+ * previously ran on this CPU sees a stale generation and is forced
+ * to acquire a new ASID, preventing a latent ASID collision.
+ */
+ sd->asid_generation++;
sd->max_asid = cpuid_ebx(SVM_CPUID_FUNC) - 1;
sd->next_asid = sd->max_asid + 1;
sd->min_asid = max_sev_asid + 1;
^ permalink raw reply [flat|nested] 608+ messages in thread
* Re: [PATCH 6.12 000/602] 6.12.101-rc1 review
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (601 preceding siblings ...)
2026-07-30 14:16 ` [PATCH 6.12 602/602] KVM: SVM: Bump asid_generation on CPU online to avoid ASID collision after hotplug Greg Kroah-Hartman
@ 2026-07-30 17:37 ` Florian Fainelli
2026-07-30 18:47 ` Miguel Ojeda
` (2 subsequent siblings)
605 siblings, 0 replies; 608+ messages in thread
From: Florian Fainelli @ 2026-07-30 17:37 UTC (permalink / raw)
To: Greg Kroah-Hartman, stable
Cc: patches, linux-kernel, torvalds, akpm, linux, shuah, patches,
lkft-triage, pavel, jonathanh, sudipm.mukherjee, rwarsow, conor,
hargar, broonie, achill, sr
On 7/30/26 07:06, Greg Kroah-Hartman wrote:
> This is the start of the stable review cycle for the 6.12.101 release.
> There are 602 patches in this series, all will be posted as a response
> to this one. If anyone has any issues with these being applied, please
> let me know.
>
> Responses should be made by Sat, 01 Aug 2026 14:13:43 +0000.
> Anything received after that time might be too late.
>
> The whole patch series can be found in one patch at:
> https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.12.101-rc1.gz
> or in the git tree and branch at:
> git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.12.y
> and the diffstat can be found below.
>
> thanks,
>
> greg k-h
On ARCH_BRCMSTB using 32-bit and 64-bit ARM kernels, build tested on
BMIPS_GENERIC:
Tested-by: Florian Fainelli <florian.fainelli@broadcom.com>
--
Florian
^ permalink raw reply [flat|nested] 608+ messages in thread
* Re: [PATCH 6.12 389/602] ceph: add owner/capability checks for CEPH_IOC_SET_LAYOUT*
2026-07-30 14:13 ` [PATCH 6.12 389/602] ceph: add owner/capability checks for CEPH_IOC_SET_LAYOUT* Greg Kroah-Hartman
@ 2026-07-30 17:40 ` Ilya Dryomov
0 siblings, 0 replies; 608+ messages in thread
From: Ilya Dryomov @ 2026-07-30 17:40 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: stable, patches, Max Kellermann, Xiubo Li
On Thu, Jul 30, 2026 at 5:45 PM Greg Kroah-Hartman
<gregkh@linuxfoundation.org> wrote:
>
> 6.12-stable review patch. If anyone has any objections, please let me know.
>
> ------------------
>
> From: Max Kellermann <max.kellermann@ionos.com>
>
> commit cee38bbf5556a8e0a232ccae41649580827d7806 upstream.
>
> These permission checks were already missing in the initial
> impementation of these ioctls. This Ceph allows any user who owns a
> file descriptor to manipulate the layout of any file, even if they
> don't have write permissions.
>
> It might be a good idea to guard other ioctls with permission checks
> as well or even disallow regular users (even if they own the file) to
> manipulate layout settings completely, as this may be abused to DoS
> the Ceph servers, but right now, I find it most urgent to have setter
> checks at all.
>
> Cc: stable@vger.kernel.org
> Fixes: 8f4e91dee2a2 ("ceph: ioctls")
> Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
> Reviewed-by: Xiubo Li <xiubo.li@clyso.com>
> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> ---
> fs/ceph/ioctl.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> --- a/fs/ceph/ioctl.c
> +++ b/fs/ceph/ioctl.c
> @@ -72,6 +72,9 @@ static long ceph_ioctl_set_layout(struct
> struct ceph_ioctl_layout nl;
> int err;
>
> + if (!inode_owner_or_capable(&nop_mnt_idmap, inode))
> + return -EACCES;
> +
> if (copy_from_user(&l, arg, sizeof(l)))
> return -EFAULT;
>
> @@ -142,6 +145,9 @@ static long ceph_ioctl_set_layout_policy
> int err;
> struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
>
> + if (!inode_owner_or_capable(&nop_mnt_idmap, inode))
> + return -EACCES;
> +
> /* copy and validate */
> if (copy_from_user(&l, arg, sizeof(l)))
> return -EFAULT;
>
>
Hi Greg,
There is a concern about the correctness of this patch, please drop it
for now.
Thanks,
Ilya
^ permalink raw reply [flat|nested] 608+ messages in thread
* Re: [PATCH 6.12 000/602] 6.12.101-rc1 review
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (602 preceding siblings ...)
2026-07-30 17:37 ` [PATCH 6.12 000/602] 6.12.101-rc1 review Florian Fainelli
@ 2026-07-30 18:47 ` Miguel Ojeda
2026-07-30 19:15 ` Peter Schneider
2026-07-30 20:06 ` Brett A C Sheffield
605 siblings, 0 replies; 608+ messages in thread
From: Miguel Ojeda @ 2026-07-30 18:47 UTC (permalink / raw)
To: gregkh
Cc: achill, akpm, broonie, conor, f.fainelli, hargar, jonathanh,
linux-kernel, linux, lkft-triage, patches, patches, pavel,
rwarsow, shuah, sr, stable, sudipm.mukherjee, torvalds,
Miguel Ojeda
On Thu, 30 Jul 2026 16:06:32 +0200 Greg Kroah-Hartman <gregkh@linuxfoundation.org> wrote:
>
> This is the start of the stable review cycle for the 6.12.101 release.
> There are 602 patches in this series, all will be posted as a response
> to this one. If anyone has any issues with these being applied, please
> let me know.
>
> Responses should be made by Sat, 01 Aug 2026 14:13:43 +0000.
> Anything received after that time might be too late.
Boot-tested under QEMU for Rust x86_64, arm64 and riscv64; built-tested
for loongarch64:
Tested-by: Miguel Ojeda <ojeda@kernel.org>
Thanks!
Cheers,
Miguel
^ permalink raw reply [flat|nested] 608+ messages in thread
* Re: [PATCH 6.12 000/602] 6.12.101-rc1 review
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (603 preceding siblings ...)
2026-07-30 18:47 ` Miguel Ojeda
@ 2026-07-30 19:15 ` Peter Schneider
2026-07-30 20:06 ` Brett A C Sheffield
605 siblings, 0 replies; 608+ messages in thread
From: Peter Schneider @ 2026-07-30 19:15 UTC (permalink / raw)
To: Greg Kroah-Hartman, stable
Cc: patches, linux-kernel, torvalds, akpm, linux, shuah, patches,
lkft-triage, pavel, jonathanh, f.fainelli, sudipm.mukherjee,
rwarsow, conor, hargar, broonie, achill, sr
Am 30.07.2026 um 16:06 schrieb Greg Kroah-Hartman:
> This is the start of the stable review cycle for the 6.12.101 release.
> There are 602 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.
Builds, boots and works on my 2-socket Ivy Bridge Xeon E5-2697 v2 server. No dmesg oddities or regressions found.
Tested-by: Peter Schneider <pschneider1968@googlemail.com>
Beste Grüße,
Peter Schneider
--
Climb the mountain not to plant your flag, but to embrace the challenge,
enjoy the air and behold the view. Climb it so you can see the world,
not so the world can see you. -- David McCullough Jr.
OpenPGP: 0xA3828BD796CCE11A8CADE8866E3A92C92C3FF244
Download: https://www.peters-netzplatz.de/download/pschneider1968_pub.asc
https://keys.mailvelope.com/pks/lookup?op=get&search=pschneider1968@googlemail.com
https://keys.mailvelope.com/pks/lookup?op=get&search=pschneider1968@gmail.com
^ permalink raw reply [flat|nested] 608+ messages in thread
* Re: [PATCH 6.12 000/602] 6.12.101-rc1 review
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
` (604 preceding siblings ...)
2026-07-30 19:15 ` Peter Schneider
@ 2026-07-30 20:06 ` Brett A C Sheffield
605 siblings, 0 replies; 608+ messages in thread
From: Brett A C Sheffield @ 2026-07-30 20:06 UTC (permalink / raw)
To: gregkh
Cc: stable, patches, linux-kernel, torvalds, akpm, linux, shuah,
patches, lkft-triage, pavel, jonathanh, f.fainelli,
sudipm.mukherjee, rwarsow, conor, hargar, broonie, achill, sr,
Brett A C Sheffield
# Librecast Test Results
020/020 [ OK ] liblcrq
010/010 [ OK ] libmld
120/120 [ OK ] liblibrecast
CPU/kernel: Linux auntie 6.12.101-rc1-gfdd6287bb54f #1 SMP PREEMPT_DYNAMIC Thu Jul 30 19:54:24 -00 2026 x86_64 AMD Ryzen 9 9950X 16-Core Processor AuthenticAMD GNU/Linux
Tested-by: Brett A C Sheffield <bacs@librecast.net>
^ permalink raw reply [flat|nested] 608+ messages in thread
end of thread, other threads:[~2026-07-30 20:41 UTC | newest]
Thread overview: 608+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-30 14:06 [PATCH 6.12 000/602] 6.12.101-rc1 review Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 001/602] platform/x86/intel-uncore-freq: Fix current_freq_khz after CPU hotplug Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 002/602] net: airoha: Move airoha_eth driver in a dedicated folder Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 003/602] net: airoha: Fix skb->priority underflow in airoha_dev_select_queue() Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 004/602] bpf: Fix ld_{abs,ind} failure path analysis in subprogs Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 005/602] selftests/bpf: Add tests for ld_{abs,ind} failure path " Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 006/602] netfilter: nft_counter: serialize reset with spinlock Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 007/602] netfilter: nft_quota: use atomic64_xchg for reset Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 008/602] netfilter: nf_tables: revert commit_mutex usage in reset path Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 009/602] drm/virtio: fix deadlock in display_info_cb by removing hotplug from dequeue worker Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 010/602] fs/proc/task_mmu: fix make_uffd_wp_huge_pte() prot-update race Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 011/602] seqlock: Cure some more scoped_seqlock() optimization fails Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 012/602] seqlock: Allow KASAN to fail optimizing Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 013/602] seqlock: Allow UBSAN_ALIGNMENT " Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 014/602] KVM: x86: Check for invalid/obsolete root *after* making MMU pages available Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 015/602] KVM: x86: Only reset TSC Deadline Timer in apic_timer_expired on KVM_RUN Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 016/602] KVM: nVMX: Hide shadow VMCS right after VMCLEAR Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 017/602] KVM: x86/mmu: Fix use-after-free on vendor module reload Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 018/602] can: bcm: add locking when updating filter and timer values Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 019/602] can: bcm: fix CAN frame rx/tx statistics Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 020/602] can: bcm: extend bcm_tx_lock usage for data and timer updates Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 021/602] can: bcm: validate frame length in bcm_rx_setup() for RTR replies Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 022/602] can: bcm: add missing device refcount for CAN filter removal Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 023/602] can: bcm: fix stale rx/tx ops after device removal Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 024/602] can: bcm: fix data race on rx_stamp/rx_ifindex in bcm_rx_handler() Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 025/602] can: bcm: track a single source interface for ANYDEV timeout/throttle ops Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 026/602] can: isotp: fix use-after-free race with concurrent NETDEV_UNREGISTER Greg Kroah-Hartman
2026-07-30 14:06 ` [PATCH 6.12 027/602] can: isotp: serialize TX state transitions under so->rx_lock Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 028/602] dmaengine: sh: rz-dmac: Move interrupt request after everything is set up Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 029/602] Revert "arm64: dts: ti: k3-am62a7-sk: Add bootph-all tag to vqmmc" Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 030/602] gpu: host1x: Fix use-after-free in host1x_bo_clear_cached_mappings Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 031/602] crypto: tegra - Dont touch bo refcount in host1x bo pin/unpin Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 032/602] xprtrdma: Clear receive-side ownership pointers on release Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 033/602] Input: ims-pcu - fix heap-buffer-overflow in ims_pcu_process_data() Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 034/602] Input: ims-pcu - fix logic error in packet reset Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 035/602] soc: qcom: ice: Allow explicit votes on iface clock for ICE Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 036/602] arm64: tegra: Fix CPU compatible string to cortex-a78ae on Tegra234 Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 037/602] firmware: arm_ffa: Respect firmware advertised RX/TX buffer size limits Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 038/602] IB/mad: Drop unmatched RMPP responses before reassembly Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 039/602] mtd: mtdswap: remove debugfs stats file on teardown Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 040/602] mtd: nand: mtk-ecc: stop on ECC idle timeouts Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 041/602] btrfs: reject free space cache with more entries than pages Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 042/602] btrfs: fix root leak if its reloc root is unexpected in merge_reloc_roots() Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 043/602] firmware: arm_ffa: Fix NULL dereference in ffa_partition_info_get() Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 044/602] RDMA/cma: Fix hardware address comparison length in netevent callback Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 045/602] RDMA/umem: Add pinned revocable dmabuf import interface Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 046/602] RDMA/irdma: Prevent rereg_mr for non-mem regions Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 047/602] RDMA/erdma: initialize ret for empty receive WR lists Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 048/602] RDMA/hns: Fix potential integer overflow in mhop hem cleanup Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 049/602] RDMA/siw: publish QP after initialization Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 050/602] mtd: fix double free and WARN_ON in add_mtd_device() error paths Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 051/602] selftests/alsa: Fix memory leak in find_controls error path Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 052/602] RDMA/irdma: Prevent overflows in memory contiguity checks Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 053/602] xfrm6: clear dst.dev on error to avoid double netdev_put in xfrm6_fill_dst() Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 054/602] xfrm: policy: preallocate inexact bins before xfrm_hash_rebuild reinsert Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 055/602] wifi: cfg80211: cancel sched scan results work on unregister Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 056/602] wifi: ipw2100: fix potential memory leak in ipw2100_pci_init_one() Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 057/602] wifi: mac80211_hwsim: clamp virtio RX length before skb_put Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 058/602] wifi: mac80211: fix unsol_bcast_probe_resp double free on alloc failure Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 059/602] wifi: mac80211: fix fils_discovery " Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 060/602] wifi: libertas: fix memory leak in helper_firmware_cb() Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 061/602] wifi: p54: validate RX frame length in p54_rx_eeprom_readback() Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 062/602] wifi: cfg80211: pass net_device to .set_monitor_channel Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 063/602] wifi: cfg80211: define and use wiphy guard Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 064/602] wifi: cfg80211: convert pmsr_free_wk to wiphy_work to fix deadlock Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 065/602] wifi: nl80211: free RNR data on MBSSID mismatch Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 066/602] wifi: cfg80211: derive S1G beacon TSF from S1G fields Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 067/602] wifi: nl80211: validate nested MBSSID IE blobs Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 068/602] wifi: cfg80211: validate PMSR measurement type data Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 069/602] wifi: cfg80211: validate PMSR FTM preamble range Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 070/602] wifi: cfg80211: reject unsupported PMSR FTM location requests Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 071/602] wifi: mac80211: free AP_VLAN bc_buf SKBs outside IRQ lock Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 072/602] wifi: brcmfmac: initialize SDIO data work before cleanup Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 073/602] wifi: cfg80211: bound element ID read when checking non-inheritance Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 074/602] ASoC: meson: aiu: fifo-spdif: soft reset the S/PDIF datapath on start/stop Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 075/602] ASoC: amd: ps: fix wrong ACP version string in pci_request_regions() Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 076/602] ASoC: cs42l43: Correct report for forced microphone jack Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 077/602] ASoC: tas2562: fix deprecated shut-down GPIO always cleared after lookup Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 078/602] firmware: arm_scmi: Rate-limit queue-full warnings in IRQ context Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 079/602] cpufreq: Make cpufreq_update_pressure() fall back to cpuinfo.max_freq Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 080/602] ppp: defer channel free to an RCU grace period to fix pppol2tp RX UAF Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 081/602] ipv4: fib: free fib_alias with kfree_rcu() on insert error path Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 082/602] net/iucv: take a reference on the socket found in afiucv_hs_rcv() Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 083/602] udmabuf: Ensure to perform cache synchronisation in begin_cpu_udmabuf() Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 084/602] scsi: core: wake eh reliably when using scsi_schedule_eh Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 085/602] ata: sata_dwc_460ex: enable SATA interrupts only after IRQ handler is registered Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 086/602] ata: sata_dwc_460ex: use platform_get_irq() Greg Kroah-Hartman
2026-07-30 14:07 ` [PATCH 6.12 087/602] ata: sata_dwc_460ex: fix clear_interrupt_bit() clearing all pending interrupts Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 088/602] ata: sata_dwc_460ex: fix infinite loop in NCQ tag completion bit-scanning Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 089/602] accel/ivpu: Fix wrong register read in LNL failure diagnostics Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 090/602] ALSA: usb-audio: Skip DSD quirk for Musical Fidelity M6s DAC Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 091/602] Bluetooth: qca: fix NVM tag length underflow in TLV parser Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 092/602] Bluetooth: MGMT: revalidate LOAD_CONN_PARAM queued update Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 093/602] Bluetooth: mgmt: fix locking in unpair_device/disconnect_sync Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 094/602] Bluetooth: mgmt: hold reference for hci_conn in mgmt_pending_cmds Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 095/602] Bluetooth: hci_qca: Clear memdump state on invalid dump size Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 096/602] smb/client: handle overlapping allocated ranges in fallocate Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 097/602] drm/i915/gt: use correct selftest config symbol Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 098/602] powerpc/85xx: Add fsl,ifc to common device ids Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 099/602] powerpc/time: Prepare to stop elapsing in dynticks-idle Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 100/602] powerpc/vtime: Initialize starttime at boot for native accounting Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 101/602] bpf, sockmap: Reject unhashed UDP sockets on sockmap update Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 102/602] s390/checksum: Fix csum_partial() without vector facility Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 103/602] riscv: hwprobe: Avoid uninitialized read in hwprobe_get_cpus() Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 104/602] can: j1939: fix lockless local-destination check Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 105/602] drm/xe/wopcm: fix WOPCM size for LNL+ Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 106/602] smb: move some duplicate definitions to common/cifsglob.h Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 107/602] ksmbd: pin conn during async oplock break notification Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 108/602] ksmbd: validate compound request size before reading StructureSize2 Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 109/602] drm/i915/selftests: Fix GT PM sort comparators Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 110/602] net/sched: act_tunnel_key: Defer dst_release to RCU callback Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 111/602] sctp: fix auth_hmacs array size in struct sctp_cookie Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 112/602] mpls: fix NULL deref in mpls_valid_fib_dump_req() on CONFIG_INET=n Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 113/602] usb: core: sysfs: add lock to bos_descriptors_read() Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 114/602] wifi: at76c50x-usb: avoid length underflow in at76_guess_freq() Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 115/602] usb: core: port: Deattach Type-C connector on component unbind Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 116/602] USB: storage: add NO_ATA_1X quirk for Longmai USB Key Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 117/602] usb: chipidea: fix usage_count leak when autosuspend_delay is negative Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 118/602] usb: gadget: dummy_hcd: prevent fifo_req reuse during giveback Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 119/602] usb: gadget: f_midi: cancel pending IN work before freeing the midi object Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 120/602] usb: gadget: printer: fix infinite loop in printer_read() Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 121/602] USB: gadget: snps-udc: fix device name leak on probe failure Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 122/602] USB: gadget: fsl-udc: " Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 123/602] usb: gadget: f_ncm: validate datagram bounds in ncm_unwrap_ntb() Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 124/602] usb: gadget: udc: bdc: free IRQ and drain func_wake_notify before teardown Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 125/602] usb: gadget: uvc: clamp SEND_RESPONSE length to the response buffer Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 126/602] USB: serial: ftdi_sio: add support for E+H FXA291 Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 127/602] USB: serial: io_edgeport: cap received transmit credits Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 128/602] USB: serial: keyspan_pda: fix data loss on receive throttling Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 129/602] USB: serial: option: add TDTECH MT5710-CN Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 130/602] crypto: rsa-pkcs1pad: Dont WARN on an empty digest Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 131/602] Revert "drm/amd/display: Add missing kdoc for ALLM parameters" Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 132/602] RISC-V: KVM: Serialize virtual interrupt pending state updates Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 133/602] usb: xhci-pci: Limit VIA VL805 DMA addressing to 36 bits Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 134/602] wifi: ath9k: hif_usb: dont dereference hif_dev after re-arming firmware request Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 135/602] wifi: ath11k: fix NULL pointer dereference in ath11k_hal_srng_access_begin Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 136/602] hwmon: (corsair-psu) Stop device IO before calling hid_hw_stop Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 137/602] hwmon: (corsair-cpro) " Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 138/602] hwmon: (gigabyte_waterforce) " Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 139/602] hwmon: (nzxt-smart2) " Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 140/602] hwmon: (nzxt-kraken3) " Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 141/602] watchdog: pretimeout: Fix UAF in watchdog_unregister_governor() Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 142/602] wifi: ath11k: fix potential buffer underflow in ath11k_hal_rx_msdu_list_get() Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 143/602] wifi: ath11k: Flush the posted write after writing to PCIE_SOC_GLOBAL_RESET Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 144/602] wifi: ath12k: " Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 145/602] firewire: net: Fix fragmented datagram reassembly Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 146/602] wifi: ath6kl: fix OOB read from firmware num_msg in TX complete handler Greg Kroah-Hartman
2026-07-30 14:08 ` [PATCH 6.12 147/602] wifi: ath6kl: fix OOB read from firmware IE lengths in connect event Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 148/602] wifi: carl9170: bound memcpy length in cmd callback to prevent OOB read Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 149/602] wifi: carl9170: fix OOB read from off-by-two in TX status handler Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 150/602] wifi: carl9170: fix buffer overflow in rx_stream failover path Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 151/602] btrfs: declare btrfs_ioctl_search_args_v2::buf as __u8 Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 152/602] btrfs: dont propagate EXTENT_FLAG_LOGGING to split extent maps Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 153/602] btrfs: free mapping node on duplicate reloc root insert Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 154/602] ASoC: tas2781: bound firmware description string parsing Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 155/602] ALSA: hda: cs35l41: Fix NULL pointer dereference in cs35l41_get_acpi_mute_state() Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 156/602] ALSA: hda: cs35l41: validate and free ACPI mute object Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 157/602] ASoC: bt-sco: fix duplicate DAPM widget names for wideband DAI Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 158/602] ASoC: cs35l56: Dont use devres to unregister component Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 159/602] ASoC: cs35l56: Fix potential probe() deadlock Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 160/602] ASoC: cs35l56: Use complete_all() to signal init_completion Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 161/602] wifi: iwlwifi: mvm: validate SAR GEO response payload size Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 162/602] wifi: iwlwifi: mvm: fix read in wake packet notification handler Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 163/602] usb: atm: ueagle-atm: reject descriptors that confuse probe and disconnect Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 164/602] drivers/virt: pkvm: Fix end calculation in mmio_guard_ioremap_hook() Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 165/602] hwmon: (asus-ec-sensors) fix looping over banks while reading from EC Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 166/602] hwmon: (asus-ec-sensors) fix EC read intervals Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 167/602] hwmon: (asus-ec-sensors) add missed handle for ENOMEM Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 168/602] smb: client: validate DFS referral PathConsumed Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 169/602] hwmon: occ: validate poll response sensor blocks Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 170/602] regulator: mt6358: use regmap helper to read fixed LDO calibration Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 171/602] Bluetooth: btusb: validate Realtek vendor event length Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 172/602] netlink: specs: rt-link: convert bridge port flag attributes to u8 Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 173/602] net/packet: avoid fanout hook re-registration after unregister Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 174/602] bonding: fix devconf_all NULL dereference when IPv6 is disabled Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 175/602] rds: drop incoming messages that cross network namespace boundaries Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 176/602] gtp: parse extension headers before reading inner protocol Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 177/602] dpaa2-switch: put MAC endpoint device on disconnect Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 178/602] dpaa2-eth: " Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 179/602] iommu/amd: Wait for completion instead of returning early in iommu_completion_wait() Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 180/602] wifi: mac80211: tear down new links on vif update error path Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 181/602] nfp: Check resource mutex allocation Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 182/602] wan: wanxl: Only reset hardware after BAR mapping Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 183/602] wifi: mwifiex: bound uAP association event IEs to the event buffer Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 184/602] iommu/amd: Bound the early ACPI HID map Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 185/602] iommu/intel: Fix out-of-bounds memset in dmar_latency_disable() Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 186/602] wifi: mac80211: recalculate TIM when a station enters power save Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 187/602] pds_core: reject component parameter in legacy firmware update Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 188/602] amd-xgbe: fix MAC_AUTO_SW handling in CL37 AN Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 189/602] net: txgbe: fix FDIR filter leak on remove Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 190/602] sctp: fix auth_chunk_list capacity check in sctp_auth_ep_add_chunkid Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 191/602] pds_core: fix deadlock between reset thread and remove Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 192/602] pds_core: fix use-after-free on workqueue during remove Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 193/602] pds_core: yield the CPU while waiting for the adminq to drain Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 194/602] pds_core: order completion reads after the ownership check Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 195/602] pds_core: fix auxiliary device add/del races Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 196/602] pds_core: check for workqueue allocation failure Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 197/602] sctp: validate stream count in sctp_process_strreset_inreq() Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 198/602] net: mctp i3c: clean up notifier and buses if driver register fails Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 199/602] tls: device: push pending open record on splice EOF Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 200/602] selftests: af_unix: add USER_NS config Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 201/602] selftests: openvswitch: add config file Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 202/602] gtp: check skb_pull_data() return in gtp1u_send_echo_resp() Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 203/602] nexthop: initialize extack in nh_res_bucket_migrate() Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 204/602] tipc: fix infinite loop in __tipc_nl_compat_dumpit Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 205/602] wifi: mt76: mt7925: guard link STA in decap offload Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 206/602] wifi: mt76: mt7915: guard HE capability lookups Greg Kroah-Hartman
2026-07-30 14:09 ` [PATCH 6.12 207/602] wifi: mt76: connac: fix possible NULL-pointer deref in mt76_connac_mcu_uni_bss_he_tlv() Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 208/602] wifi: mt76: mt7925: fix possible NULL-pointer deref in mt7925_mcu_bss_he_tlv() Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 209/602] wifi: mt76: mt7996: check pointer returned by mt76_connac_get_he_phy_cap() Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 210/602] wifi: mt76: mt7925: fix crash in reset link replay Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 211/602] wifi: mt76: mt7996: fix possible NULL-pointer deref in mt7996_mcu_sta_bfer_eht() Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 212/602] wifi: brcmfmac: fix 802.1X-SHA256 call trace warning Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 213/602] ovl: fix trusted xattr escape prefix matching Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 214/602] amt: re-read skb header pointers after every pull Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 215/602] amt: make the head writable before rewriting the L2 header Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 216/602] net: bridge: vlan: fix vlan range dumps starting with pvid Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 217/602] net: hsr: fix memory leak on slave unregistration by removing synced VLANs Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 218/602] net: dpaa: fix mode setting Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 219/602] sctp: auth: verify auth requirement when auth_chunk is NULL Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 220/602] vmxnet3: fix BUG_ON in vmxnet3_get_hdr_len() for Geneve packets Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 221/602] iomap: correct the range of a partial dirty clear Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 222/602] tipc: fix u16 MTU truncation in media and bearer MTU validation Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 223/602] drm/tests: shmem: Set DMA mask to 64-bit in drm_gem_shmem Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 224/602] net: stmmac: fix l3l4 filter rejecting unsupported offload requests Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 225/602] net: stmmac: reset residual action in L3L4 filters on delete Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 226/602] net: stmmac: enable the MAC on link up for all supported speeds Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 227/602] net: gre: fix lltx regression for GRE tunnels with SEQ/CSUM Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 228/602] octeontx2-vf: set TC flower flag on MCAM entry allocation Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 229/602] ipv4: icmp: fill flow parameters in icmp_route_lookup decoy lookup Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 230/602] ppp: use IFF_NO_QUEUE in virtual interfaces Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 231/602] ppp: convert to percpu netstats Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 232/602] ppp: enable TX scatter-gather Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 233/602] ppp: annotate data races in ppp_generic Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 234/602] hinic: remove unused ethtool RSS user configuration buffers Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 235/602] net: qrtr: restrict socket creation to the initial network namespace Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 236/602] dpll: add clock quality level attribute and op Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 237/602] net/mlx5: DPLL, Add clock quality level op implementation Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 238/602] net/mlx5: Remove newline at the end of a netlink error message Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 239/602] net/mlx5: Refactor EEPROM query error handling to return status separately Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 240/602] net/mlx5: Fix MCIA register buffer overflow on 32 dword reads Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 241/602] net/mlx5: E-Switch, fix zero num_dest in prio_tag egress vlan rule Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 242/602] net/mlx5e: Report zero bandwidth for non-ETS traffic classes Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 243/602] net/mlx5e: Reject unsupported CB Shaper TSA in ETS validation Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 244/602] octeontx2-pf: tc: fix egress ratelimiting Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 245/602] net: ipv6: fix dif and sdif mismatch in raw6_icmp_error Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 246/602] ice: allow creating VFs when !CONFIG_ICE_SWITCHDEV Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 247/602] ice: fix LAG recipe to profile association Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 248/602] rds: tcp: unregister sysctl before tearing down listen socket Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 249/602] net: airoha: fix ETS channel derivation in airoha_tc_setup_qdisc_ets() Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 250/602] bpf, sockmap: Fix cork use-after-free in tcp_bpf_sendmsg() Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 251/602] drm: renesas: rzg2l_mipi_dsi: Increase reset deassertion delay Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 252/602] drm/rockchip: cdn-dp: add missing check in cdn_dp_config_video() Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 253/602] drm/imagination: Count paired job fence as dependency in prepare_job() Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 254/602] drm/bridge: cdns-dsi: Replace deprecated UNIVERSAL_DEV_PM_OPS() Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 255/602] drm/dp/mst: fix OOB reads in remote DPCD/I2C sideband reply parsers Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 256/602] drm/dp/mst: fix buffer overflows in sideband chunk accumulation Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 257/602] drm/imagination: Fit paired fragment job in the correct CCCB Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 258/602] drm/dp/mst: fix OOB reads on 2-byte fields in sideband reply parsers Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 259/602] drm/amdgpu/uvd: Fix forcing MSG, FB BOs into VCPU segment when it isnt at 0 (v2) Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 260/602] drm/amdgpu/uvd: Place VCPU BO only in VRAM for UVD 4.x and older Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 261/602] drm/amdgpu: Fix amdgpu_bo_move() when old_mem and new_mem are both GTT Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 262/602] drm/amdgpu: validate CP_GFX_SHADOW chunk size in CS pass1 Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 263/602] drm/nouveau: fix reversed error cleanup order in ucopy functions Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 264/602] drm/displayid: fix Tiled Display Topology ID size Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 265/602] drm/i915/gem: Add missing nospec on parallel submit slot Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 266/602] drm/nouveau/acr: fix missing nvkm_done() in error path of nvkm_acr_oneinit() Greg Kroah-Hartman
2026-07-30 14:10 ` [PATCH 6.12 267/602] drm/radeon: fix r100_copy_blit for large BOs Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 268/602] drm/xe: Fix PTE index in xe_vm_populate_pgtable() for chunked binds Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 269/602] drm/imagination: Fix double call to drm_sched_entity_fini() Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 270/602] drm/imagination: Fix user array stride in pvr_set_uobj_array() Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 271/602] drm/imagination: fix error checking of pvr_vm_context_lookup() Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 272/602] drm/imagination: acquire vm_ctx->lock before mapping memory to GPU VM Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 273/602] drm/amdkfd: Use kvcalloc to allocate arrays Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 274/602] drm/amdkfd: Check bounds in allocate_event_notification_slot Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 275/602] drm/amdkfd: fix 32-bit overflow in CWSR total size calculation Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 276/602] drm/amd/display: Handle struct drm_plane_state.ignore_damage_clips Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 277/602] drm/amd/display: detect_link_and_local_sink: DP alt mode timeout path leaks prev_sink reference Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 278/602] drm/virtio: bound EDID block reads to the response buffer Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 279/602] drm/amdgpu/sdma7.0: replace BUG_ON() with WARN_ON() Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 280/602] drm/amdgpu/sdma6.0: " Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 281/602] drm/amdgpu/sdma5.2: " Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 282/602] drm/amdgpu/sdma5.0: " Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 283/602] drm/i915: Return NULL on error in active_instance Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 284/602] drm/i915/bios: range check LFP Data Block panel_type2 Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 285/602] drm/amdgpu: fix lifetime issue of amdgpu_vm_get_task_info_pasid() Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 286/602] drm/i915/gem: Do not leak siblings[] on proto context error Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 287/602] drm/i915/gem: Fix NULL deref in I915_CONTEXT_PARAM_SSEU Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 288/602] drm/amd/pm: fix smu14 power limit range calculation Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 289/602] drm/gfx10: Program DB_RING_CONTROL Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 290/602] drm/panthor: return error on truncated firmware Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 291/602] drm/amdgpu: Fix VFCT bus number matching with soft filter Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 292/602] drm/amd/pm/ci: Dont disable MCLK DPM on Bonaire 0x6658 (R7 260X) Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 293/602] drm/amd/display: set new_stream to NULL after release Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 294/602] drm/amd/display: dce100: skip non-DP stream encoders for DP MST Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 295/602] drm/amdgpu: Disable PCIe dynamic speed switching on Ryzen Pinnacle Ridge Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 296/602] drm/amdgpu: fix bo->pin leaking in amdgpu_bo_create_reserved Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 297/602] drm/vmwgfx: Validate vmw_surface_metadata::array_size Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 298/602] drm/vc4: Prevent shader BO mappings from becoming writable Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 299/602] media: airspy: Return queued buffers on start_streaming() failure Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 300/602] media: aspeed: fix missing of_reserved_mem_device_release() on probe failure Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 301/602] media: cec: seco: unregister adapter on IR " Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 302/602] media: cedrus: clean up media device on " Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 303/602] media: cedrus: Fix missing cleanup in error path Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 304/602] media: cedrus: skip invalid H.264 reference list entries Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 305/602] media: chips-media: wave5: Move src_buf Removal to finish_encode Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 306/602] media: cx231xx: fix devres lifetime Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 307/602] media: cx23885: add ioremap return check and cleanup Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 308/602] media: i2c: alvium: fix critical pointer access in alvium_ctrl_init Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 309/602] media: intel/ipu6: Improve DWC PHY HSFREQRANGE band selection for overlapping ranges Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 310/602] media: marvell-cam: fix missing pci_disable_device() on remove Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 311/602] media: meson: vdec: Fix memory leak in error path of vdec_open Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 312/602] media: msi2500: Return queued buffers on start_streaming() failure Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 313/602] media: nuvoton: npcm-video: fix error handling in npcm_video_init() Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 314/602] media: nuvoton: npcm-video: fix memory leaks in probe and remove Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 315/602] media: nxp: imx8-isi: Add missing v4l2_subdev_cleanup() in crossbar and pipe Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 316/602] media: nxp: imx8-isi: Clean up already-initialized pipes on probe failure Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 317/602] media: nxp: imx8-isi: Fix missing v4l2_subdev_cleanup() in pipe init error path Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 318/602] media: nxp: imx8-isi: Fix potential out-of-bounds issues Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 319/602] media: nxp: imx8-isi: Fix scale factor calculation for hardware rounding Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 320/602] media: pci: dm1105: Free allocated workqueue Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 321/602] media: pwc: Drain fill_buf on start_streaming() failure Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 322/602] media: pwc: Return queued buffers " Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 323/602] media: qcom: camss: Fix RDI streaming for CSID GEN2 Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 324/602] media: radio-si476x: Unregister v4l2_device on probe failure Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 325/602] media: rtl2832: fix use-after-free in rtl2832_remove() Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 326/602] media: rtl2832_sdr: Return queued buffers on start_streaming() failure Greg Kroah-Hartman
2026-07-30 14:11 ` [PATCH 6.12 327/602] media: saa7134: Fix a possible memory leak in saa7134_video_init1 Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 328/602] media: stm32: dcmi: unregister notifier on probe failure Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 329/602] media: sun4i-csi: Return queued buffers on start_streaming() failure Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 330/602] media: tegra-video: vi: fix invalid u32 return value in format lookup Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 331/602] media: ti: vpe: unwind v4l2 device registration on probe error Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 332/602] media: v4l2-ctrls-request: add NULL check in v4l2_ctrl_request_complete() Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 333/602] media: v4l2-ctrls: validate HEVC active reference counts Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 334/602] media: v4l2-fwnode: Fix subdev owner overwritten in v4l2_async_register_subdev_sensor() Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 335/602] media: v4l2-subdev: Fail {enable,disable}_streams and s_streaming nicely Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 336/602] media: vb2: use ssize_t for vb2_read/vb2_write Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 337/602] media: vidtv: fix reference leak on failed device registration Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 338/602] media: vimc: " Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 339/602] media: vivid: add vivid_update_reduced_fps() Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 340/602] media: vivid: check for vb2_is_busy() when toggling caps Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 341/602] media: vivid: fix cleanup bugs in vivid_init() Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 342/602] media: vpif_capture: fix OF node reference imbalance Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 343/602] ALSA: seq: close a re-opened queue timer in the destructor Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 344/602] ALSA: timer: drain a slaves callback before its master detaches it Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 345/602] ALSA: timer: dont re-enter an instance callback that is still running Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 346/602] wifi: ath6kl: fix OOB access from firmware ADDBA window size Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 347/602] wifi: mwifiex: fix NULL dereference when the AP has HT-cap but no HT-oper Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 348/602] wifi: wilc1000: validate assoc response length before subtracting header Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 349/602] wifi: mt76: mt7615: drop TXRX_NOTIFY on non-mmio buses Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 350/602] wifi: mt76: mt7921: " Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 351/602] wifi: mt76: mt7925: " Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 352/602] wifi: brcmfmac: make release_scratchbuffers idempotent Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 353/602] staging: rtl8723bs: fix OOB reads in rtw_get_wps_ie() Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 354/602] staging: rtl8723bs: fix inverted HT40 secondary channel offset Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 355/602] Bluetooth: hci_sync: Protect UUID list traversal Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 356/602] Bluetooth: RFCOMM: Fix session UAF in set_termios Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 357/602] exec: fix unsigned loop counter wrap in transfer_args_to_stack() Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 358/602] binfmt_misc: set have_execfd only once the interpreter is opened Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 359/602] platform/loongarch: laptop: Explicitly reset bl_powered state when suspend Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 360/602] rust: allow `clippy::unwrap_or_default` globally Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 361/602] objtool/rust: add one more `noreturn` Rust function for Rust 1.99.0 Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 362/602] LoongArch: Fix oops during single-step debugging Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 363/602] LoongArch: Move jump_label_init() before parse_early_param() Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 364/602] LoongArch: Retrieve CPU package ID from PPTT when available Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 365/602] cdrom: fix stack out-of-bounds read in CDROMVOLCTRL Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 366/602] firmware: stratix10-svc: fix memory leaks and list corruption bugs Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 367/602] x86/boot/compressed: Disable jump tables Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 368/602] comedi: comedi_parport: deal with premature interrupt Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 369/602] uio_hv_generic: Bind to FCopy device by default Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 370/602] serial: sc16is7xx: implement gpio get_direction() callback Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 371/602] serial: 8250_mid: Fix NULL function pointer dereference on DNV/ICX-D/SNR platforms Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 372/602] mei: bus: access mei_device under device_lock on cleanup Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 373/602] intel_th: fix MSC output device reference leak Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 374/602] misc: nsm: only unlock nsm_dev on post-lock error paths Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 375/602] misc: nsm: pin the module while the device is open Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 376/602] tracing: Fix mmiotrace possible NULL dereferencing of hiter->dev Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 377/602] tracing: Fix resource leak on mmiotrace trace_pipe close Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 378/602] tracing/eprobe: Fix exact system name matching in eprobe_dyn_event_match() Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 379/602] tracing/probes: Avoid temporary buffer truncation in trace_probe_match_command_args() Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 380/602] tracing/probes: Fix potential underflow in LEN_OR_ZERO macro Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 381/602] tracing/probes: Prevent out-of-bounds write in __trace_probe_log_err() Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 382/602] arm64: syscall: Ensure saved x0 is kept in-sync with tracer updates Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 383/602] Revert "arm64: syscall: Ensure saved x0 is kept in-sync with tracer updates" Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 384/602] mptcp: decrement subflows counter on failed passive join Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 385/602] mptcp: only set DATA_FIN when a mapping is present Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 386/602] sctp: dont free the ASCONFs own transport in DEL-IP processing Greg Kroah-Hartman
2026-07-30 14:12 ` [PATCH 6.12 387/602] sctp: avoid auth_enable sysctl UAF during netns teardown Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 388/602] sctp: close UDP tunnel sockets " Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 389/602] ceph: add owner/capability checks for CEPH_IOC_SET_LAYOUT* Greg Kroah-Hartman
2026-07-30 17:40 ` Ilya Dryomov
2026-07-30 14:13 ` [PATCH 6.12 390/602] ceph: fix pre-auth out-of-bounds read on snaptrace in ceph_handle_caps() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 391/602] ceph: fix refcount leak in ceph_readdir() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 392/602] libceph: bound get_version reply decode to front len Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 393/602] libceph: Fix multiplication overflow in decode_new_up_state_weight() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 394/602] libceph: guard missing CRUSH type name lookup Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 395/602] libceph: refresh auth->authorizer_buf{,_len} after authorizer update Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 396/602] libceph: Reject monmaps advertising zero monitors Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 397/602] libceph: reject zero bucket types in crush_decode Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 398/602] libceph: remove debugfs files before client teardown Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 399/602] amt: fix use-after-free in AMT delayed works Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 400/602] ASoC: fsl_sai: Fix spurious BCLK on resume by clearing BYP Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 401/602] binfmt_elf_fdpic: only honour the first PT_INTERP Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 402/602] fs: preserve ACL_DONT_CACHE state in forget_cached_acl() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 403/602] fscrypt: Add missing superblock check in find_or_insert_direct_key() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 404/602] ftrace: Add global mutex to serialize trace_parser access Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 405/602] iomap: fix out-of-bounds bitmap_set() with zero-length range Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 406/602] iommu/vt-d: Disallow SVA if page walk is not coherent Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 407/602] phonet: pep: fix use-after-free in pep_get_sb() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 408/602] vxlan: require CAP_NET_ADMIN in the device netns for changelink Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 409/602] net: slip: serialize receive against buffer reallocation Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 410/602] geneve: require CAP_NET_ADMIN in the device netns for changelink Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 411/602] net/af_iucv: fix NULL deref in afiucv_hs_callback_syn() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 412/602] net/iucv: fix use-after-free of a severed iucv_path Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 413/602] net/mlx5e: Use sender devcom for MPV master-up Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 414/602] net/x25: fix use-after-free in x25_kill_by_neigh() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 415/602] net: gro: fix double aggregation of flush-marked skbs Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 416/602] net: hip04: fix RX buffer leak on build_skb failure Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 417/602] proc: Fix broken error paths for namespace links Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 418/602] ice: fix PTP Call Trace during PTP release Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 419/602] selftests/ftrace: Reset triggers at top level before instance loop Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 420/602] rbd: Reset positive result codes to zero in object map update path Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 421/602] ksmbd: defer destroy_previous_session() until after NTLM authentication Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 422/602] ice: reject out-of-range ptype in ice_parser_profile_init Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 423/602] ice: use READ_ONCE() to access cached PHC time Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 424/602] ila: reload IPv6 header after pskb_may_pull in checksum adjust Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 425/602] mac802154: hold an interface reference across the scan worker Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 426/602] mac802154: llsec: reject frames shorter than the authentication tag Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 427/602] mctp: serial: handle zero-length frames to prevent rx buffer overflow Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 428/602] openvswitch: fix GSO userspace truncation underflow Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 429/602] pppoe: reload header pointer after dev_hard_header() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 430/602] rtase: Workaround for TX hang caused by hardware packet parsing Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 431/602] tcp: initialize standalone TCP-AO response padding Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 432/602] tipc: clear sock->sk on the failed-insert path in tipc_sk_create() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 433/602] vsock/virtio: collapse receive queue under memory pressure Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 434/602] vxlan: mdb: Fix source list corruption on a failed replace Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 435/602] drm/amd/pm: fix amdgpu_pm_info power display units Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 436/602] drm/amd/pm: make pp_features read-only when scpm is enabled Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 437/602] drm/amdgpu/gfx10: replace BUG_ON() with WARN_ON() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 438/602] drm/amdgpu/gfx11: " Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 439/602] drm/amdgpu/gfx12: " Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 440/602] drm/amdgpu/gfx8: drop unecessary BUG_ON() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 441/602] drm/amdgpu/gfx9.4.3: replace BUG_ON() with WARN_ON() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 442/602] drm/amdgpu/gfx9: " Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 443/602] drm/amdgpu/sdma4.4.2: " Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 444/602] drm/amdgpu/vce: fix integer overflow in image size Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 445/602] drm/amdgpu/vcn4: avoid rereading IB param length Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 446/602] drm/dp_mst: Handle torn-down topology gracefully in drm_dp_mst_topology_queue_probe() Greg Kroah-Hartman
2026-07-30 14:13 ` [PATCH 6.12 447/602] drm/amdgpu: fix division by zero with invalid uvd dimensions Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 448/602] drm/amdgpu: invoke pm_genpd_remove() before freeing genpd Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 449/602] drm/amdgpu: fix aperture mapping leak Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 450/602] drm/amd/pm: fix smu13 power limit range calculation Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 451/602] bpf: Fix same-register dst/src OOB read and pointer leak in sock_ops Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 452/602] net: qrtr: ns: Raise node count limit to 512 Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 453/602] ksmbd: validate num_subauth when copying ACE in set_ntacl_dacl Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 454/602] ksmbd: restore DACL size on check_add_overflow() to avoid malformed ACL Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 455/602] ksmbd: bound DACL dedup walk to copied ACEs Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 456/602] ksmbd: validate ACE size against SID sub-authorities Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 457/602] fscrypt: Avoid dynamic allocation in fscrypt_get_devices() Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 458/602] drm/amd/display: Fix DTB DTO updates breaking live pixel rate sources Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 459/602] io_uring/rw: fix missing ERESTARTSYS conversion in read paths Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 460/602] net: pcs: xpcs: fix SGMII state reading Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 461/602] gve: fix Rx queue stall on alloc failure Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 462/602] rust: allow `suspicious_runtime_symbol_definitions` lint for Rust >= 1.98 Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 463/602] mm/damon/core: validate ranges in damon_set_regions() Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 464/602] mm/damon/core: disallow overlapping input ranges for damon_set_regions() Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 465/602] iommufd: Reject invalid read count in iommufd_fault_fops_read() Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 466/602] iommufd: Break the loop on failure " Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 467/602] iommufd: Avoid partial fault group delivery " Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 468/602] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region() Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 469/602] i2c: davinci: Unregister cpufreq notifier on probe failure Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 470/602] VFS/audit: introduce kern_path_parent() for audit Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 471/602] audit: widen ino fields to u64 Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 472/602] audit: use unsigned int instead of unsigned Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 473/602] audit: fix recursive locking deadlock in audit_dupe_exe() Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 474/602] i2c: i801: fix hardware state machine corruption in error path Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 475/602] ALSA: hda: conexant: Remove mic bias threshold override Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 476/602] ALSA: hda: Fix cached processing coefficient verbs Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 477/602] rxrpc: Pull out certain app callback funcs into an ops table Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 478/602] rxrpc: serialize kernel accept preallocation with socket teardown Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 479/602] xfs: factor out xfs_attr3_leaf_init Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 480/602] xfs: dont replace the wrong part of the cow fork Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 481/602] fbcon: Rename struct fbcon_ops to struct fbcon_par Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 482/602] fbcon: Use correct type for vc_resize() return value Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 483/602] rxrpc: Fix CPU time starvation in I/O thread Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 484/602] rxrpc: Dont need barrier for ->tx_bottom and ->acks_hard_ack Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 485/602] rxrpc: Use irq-disabling spinlocks between app and I/O thread Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 486/602] rxrpc: Fix notification vs call-release vs recvmsg Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 487/602] rxrpc: Fix socket notification race Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 488/602] tipc: restrict socket queue dumps in enqueue tracepoints Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 489/602] vduse: Use fixed 4KB bounce pages for non-4KB page size Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 490/602] vduse: remove unused vaddr parameter of vduse_domain_free_coherent Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 491/602] vduse: take out allocations from vduse_dev_alloc_coherent Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 492/602] VDUSE: avoid leaking information to userspace Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 493/602] octeontx2: Annotate mmio regions as __iomem Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 494/602] octeontx2-vf: clear stale mailbox IRQ state before request_irq() Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 495/602] octeontx2-pf: " Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 496/602] arm64: dts: qcom: correct RBR opp entry Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 497/602] arm64: dts: qcom: hamoa: Fix OPP tables for all DisplayPort controllers Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 498/602] ASoC: mediatek: mt8192-afe-pcm: Simplify probe() with local dev variable Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 499/602] ASoC: mediatek: mt8192: Check runtime resume during probe Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 500/602] ASoC: mediatek: mt8183-afe-pcm: Shorten memif_data table using macros Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 501/602] ASoC: mediatek: mt8183-afe-pcm: Support >32 bit DMA addresses Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 502/602] ASoC: mediatek: mt8183-afe-pcm: use local `dev` pointer in driver callbacks Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 503/602] ASoC: mediatek: mt8183: Check runtime resume during probe Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 504/602] netfilter: nf_conntrack_sip: remove net variable shadowing Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 505/602] netfilter: nf_conntrack_sip: validate skb_dst() before accessing it Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 506/602] netfilter: bitwise: rename some boolean operation functions Greg Kroah-Hartman
2026-07-30 14:14 ` [PATCH 6.12 507/602] netfilter: nf_tables: Remove unused nft_reduce_is_readonly() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 508/602] netfilter: nf_tables: remove register tracking infrastructure Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 509/602] netfilter: nft_fib: reject fib expression on the netdev egress hook Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 510/602] gpu: Move DRM buddy allocator one level up (part two) Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 511/602] gpu/buddy: bail out of try_harder when alignment cannot be honoured Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 512/602] NFSD: pass nfsd_file to nfsd_iter_read() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 513/602] sunrpc: allocate a separate bvec array for socket sends Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 514/602] SUNRPC: Add helpers to convert xdr_buf byte ranges to scatterlists Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 515/602] SUNRPC: Return an error from xdr_buf_to_bvec() on overflow Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 516/602] remoteproc: xlnx: Check remote core state Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 517/602] mm/hugetlb: fix hugetlb cgroup rsvd charge/uncharge mismatch Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 518/602] mm/sparse-vmemmap: fix vmemmap accounting underflow Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 519/602] landlock: Prepare to use credential instead of domain for fowner Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 520/602] landlock: Fix LANDLOCK_SCOPE_SIGNAL bypass on the SIGIO path Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 521/602] mm/mm_init: fix pageblock migratetype for ZONE_DEVICE compound pages Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 522/602] mtd: maps: vmu-flash: fix fault in unaligned fixup Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 523/602] mm: prepare to move subsection_map_init() to mm/sparse-vmemmap.c Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 524/602] mm/sparse-vmemmap: fix DAX vmemmap accounting with optimization Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 525/602] thunderbolt: Keep XDomain reference during the lifetime of a service Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 526/602] thunderbolt: Remove service debugfs entries during unregister Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 527/602] thunderbolt: Remove XDomain from the bus without holding tb->lock Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 528/602] thunderbolt: Prevent XDomain delayed work use-after-free on disconnect Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 529/602] dma: dw-edma: Fix build warning in dw_edma_pcie_probe() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 530/602] dmaengine: dw-edma: Fix confusing cleanup.h syntax Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 531/602] dmaengine: dw-edma-pcie: Reject devices without driver data Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 532/602] i2c: imx: separate atomic, dma and non-dma use case Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 533/602] i2c: imx: fix locked bus on SMBus block-read of 0 (atomic) Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 534/602] xfrm: Use nested-BH locking for nat_keepalive_sk_ipv[46] Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 535/602] xfrm: nat_keepalive: avoid double free on send error Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 536/602] tcp: defer md5sig_info kfree past RCU grace period in tcp_connect Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 537/602] tcp: Decrement tcp_md5_needed static branch Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 538/602] nvmet: Introduce nvmet_req_transfer_len() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 539/602] nvmet-auth: reject short AUTH_RECEIVE buffers Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 540/602] ovl: use linked upper dentry in copy-up tmpfile Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 541/602] bpf: Refactor {acquire,release}_reference_state Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 542/602] bpf: Refactor check_ctx_access() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 543/602] bpf: Reset register bounds before narrowing retval range in check_mem_access() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 544/602] block: add helper add_disk_final() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 545/602] block: remove redundant GD_NEED_PART_SCAN in add_disk_final() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 546/602] dm-integrity: fix leaking uninitialized kernel memory Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 547/602] cleanup: add a scoped version of CLASS() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 548/602] cleanup: fix scoped_class() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 549/602] cred: add kernel_cred() helper Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 550/602] cred: add scoped_with_kernel_creds() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 551/602] dm: avoid leaking the callers thread keyring via the table device file Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 552/602] wifi: libertas_tf: fix use-after-free in lbtf_free_adapter() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 553/602] mmc: vub300: fix use-after-free on disconnect Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 554/602] mmc: vub300: rename probe error labels Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 555/602] mmc: vub300: fix use-after-free on probe failure Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 556/602] locking/rt: Fix the incorrect RCU protection in rt_spin_unlock() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 557/602] net: mana: Validate the packet length reported by the NIC Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 558/602] net: ip6_tunnel: require CAP_NET_ADMIN in the device netns for changelink Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 559/602] gve: fix header buffer corruption with header-split and HW-GRO Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 560/602] gpio: mt7621: avoid corruption of shared interrupt trigger state Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 561/602] octeontx2-af: cn10k: restrict VF LMTLINE sharing to its own PF Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 562/602] bootconfig: move xbc_snprint_cmdline() to lib/bootconfig.c Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 563/602] bootconfig: fix NULL-pointer arithmetic in xbc_snprint_cmdline() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 564/602] ipmi: fix refcount leak in i_ipmi_request() Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 565/602] net/mlx5: HWS, Rearrange to prevent forward declaration Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 566/602] net/mlx5: HWS, fix matcher leak on resize target setup failure Greg Kroah-Hartman
2026-07-30 14:15 ` [PATCH 6.12 567/602] octeontx2-pf: fix SQB pointer leak on init failure Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 568/602] ata: libata-core: Reject an invalid concurrent positioning ranges count Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 569/602] fs/resctrl: Fix double-add of pseudo-locked regions RMID to free list Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 570/602] net: macb: drop in-flight Tx SKBs on close Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 571/602] net: ipa: fix SMEM state handle leaks in SMP2P init Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 572/602] Bluetooth: Add PA_LINK to distinguish BIG sync and PA sync connections Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 573/602] Bluetooth: hci_core: Fix not accounting for BIS/CIS/PA links separately Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 574/602] afs: Improve server refcount/active count tracing Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 575/602] afs: Make afs_lookup_cell() take a trace note Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 576/602] afs: Drop the net parameter from afs_unuse_cell() Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 577/602] rxrpc: Allow the app to store private data on peer structs Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 578/602] afs: Use the per-peer app data provided by rxrpc Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 579/602] afs: Fix afs_server ref accounting Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 580/602] afs: Simplify cell record handling Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 581/602] afs: Fix dynamic lookup to fail on cell lookup failure Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 582/602] afs: Fix lack of locking around modifications of net->cells_dyn_ino Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 583/602] USB: gadget: Use str_enable_disable-like helpers Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 584/602] USB: gadget: fsl-udc: fix dev_printk() device Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 585/602] usb: musb: omap2430: clean up probe error handling Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 586/602] usb: musb: omap2430: Do not put borrowed of_node in probe Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 587/602] net/mlx5e: Fix NULL pointer dereference in ioctl module EEPROM query Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 588/602] gpu: Fix uninitialized buddy for built-in drivers Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 589/602] rxrpc: Disable IRQ, not BH, to take the lock for ->attend_link Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 590/602] rxrpc: Fix locking issues with the peer record hash Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 591/602] wifi: nl80211: fix nl80211_start_radar_detection return value Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 592/602] net: ethernet: Remove accidental duplication in Kconfig file Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 593/602] afs: Set vllist to NULL if addr parsing fails Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 594/602] dpll: fix clock quality level reporting Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 595/602] afs: Fix delayed allocation of a cells anonymous key Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 596/602] afs: handle CB.InitCallBackState3 requests without a server record Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 597/602] Bluetooth: hci_conn: Fix running bis_cleanup for hci_conn->type PA_LINK Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 598/602] Bluetooth: hci_conn: Fix not cleaning up Broadcaster/Broadcast Source Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 599/602] Bluetooth: hci_conn: Fix not cleaning up PA_LINK connections Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 600/602] Bluetooth: hci_conn: Fix memory leak in hci_le_big_terminate() Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 601/602] afs: Fix uninit var in afs_alloc_anon_key() Greg Kroah-Hartman
2026-07-30 14:16 ` [PATCH 6.12 602/602] KVM: SVM: Bump asid_generation on CPU online to avoid ASID collision after hotplug Greg Kroah-Hartman
2026-07-30 17:37 ` [PATCH 6.12 000/602] 6.12.101-rc1 review Florian Fainelli
2026-07-30 18:47 ` Miguel Ojeda
2026-07-30 19:15 ` Peter Schneider
2026-07-30 20:06 ` Brett A C Sheffield
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).