* [PATCH 5.10 000/235] 5.10.266-rc1 review
@ 2026-08-20 14:53 Greg Kroah-Hartman
2026-08-20 14:53 ` [PATCH 5.10 001/235] media: mtk-vcodec: potential null pointer deference in SCP Greg Kroah-Hartman
` (237 more replies)
0 siblings, 238 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:53 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 5.10.266 release.
There are 235 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, 22 Aug 2026 14:51:11 +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/v5.x/stable-review/patch-5.10.266-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-5.10.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Linux 5.10.266-rc1
Johan Hovold <johan@kernel.org>
USB: serial: keyspan_pda: fix information leak
Zhang Changzhong <zhangchangzhong@huawei.com>
net: ethernet: ti: am65-cpsw: fix error handling in am65_cpsw_nuss_probe()
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
i2c: smbus: Check for parent device before dereference
Robert Mader <robert.mader@collabora.com>
udmabuf: Ensure to perform cache synchronisation in begin_cpu_udmabuf()
Christian Brauner <brauner@kernel.org>
binfmt_misc: use exe_file_deny_write_access() for the interpreter clone
Daming Li <d4n.for.sec@gmail.com>
net: smc: fix splice entry lifetime imbalance in smc_rx_splice
Guangguan Wang <guangguan.wang@linux.alibaba.com>
net/smc: rdma write inline if qp has sufficient inline space
Siddharth Vadapalli <s-vadapalli@ti.com>
net: ethernet: ti: am65-cpsw-nuss: Fix port_id extraction from SRC TAG
Grygorii Strashko <grygorii.strashko@ti.com>
net: ethernet: ti: am65-cpsw: add multi port support in mac-only mode
Grygorii Strashko <grygorii.strashko@ti.com>
net: ethernet: ti: am65-cpsw: move free desc queue mode selection in pdata
Grygorii Strashko <grygorii.strashko@ti.com>
net: ethernet: ti: am65-cpsw: move ale selection in pdata
Eric Dumazet <edumazet@google.com>
af_packet: Don't send zero-byte data in tpacket_snd().
Rosen Penev <rosenp@gmail.com>
ASoC: xilinx: formatter_pcm: pass aud_drv_data to irq handlers
Wei Fang <wei.fang@nxp.com>
net: packet: fix wrong transport_header when sending VLAN-tagged frame
Florian Westphal <fw@strlen.de>
netfilter: ipset: fix list type element drift bug
Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr>
netfilter: flowtable: publish GC-visible tuple last
Alexey Velichayshiy <a.velichayshiy@ispras.ru>
netfilter: nf_tables_offload: suppress WARN_ON_ONCE for ENOMEM in abort path
Xiang Mei (Microsoft) <xmei5@asu.edu>
netfilter: ipset: fix refcount race between list:set GC and swap
Herbert Xu <herbert@gondor.apana.org.au>
crypto: ccm - Set rfc4309 maxauthsize from child
Jon Hunter <jonathanh@nvidia.com>
arm64: tegra: Add EL2 virtual timer interrupt for Tegra194
Yangyu Chen <cyy@cyyself.name>
net: atlantic: free stranded TX buffers on ring deinit
Lorenzo Stoakes (ARM) <ljs@kernel.org>
mm/ptdump: always stabilise against page table freeing using init_mm
Hyunjung Ko <hj351016@gmail.com>
net/sched: act_gact, act_police: range check the fallback control action
Tejun Heo <tj@kernel.org>
sched/psi: Shut down rtpoll_timer in psi_cgroup_free()
Baul Lee <baul.lee@xbow.com>
ALSA: usx2y: bound the hwdep mmap fault offset
Takashi Iwai <tiwai@suse.de>
ALSA: usx2y: Fix potential leaks of uninitialized memory
Yang Wang <kevinyang.wang@amd.com>
drm/amd/pm: fix torn gpu metrics reads
Hongyan Xu <getshell@seu.edu.cn>
hwmon: (npcm750-pwm-fan): stop fan timer on device detach
Marc Kleine-Budde <mkl@pengutronix.de>
can: gs_usb: gs_usb_receive_bulk_callback(): resubmit URB on skb allocation failure
Christian Brauner <brauner@kernel.org>
binfmt_misc: restore write access when removing an entry
Amir Goldstein <amir73il@gmail.com>
fs: don't block write during exec on pre-content watched files
Amir Goldstein <amir73il@gmail.com>
fsnotify: opt-in for permission events at file open time
Jonas Gorski <jonas.gorski@bisdn.de>
i2c: iproc: reset bus after timeout if START_BUSY is stuck
Wolfram Sang <wsa+renesas@sang-engineering.com>
i2c: bcm-iproc: remove printout on handled timeouts
Dawei Feng <dawei.feng@seu.edu.cn>
ice: fix memory leak in ice_lbtest_prepare_rings()
Dawid Osuchowski <dawid.osuchowski@linux.intel.com>
ice: fix VF interrupts cleanup
Ibrahim Hashimov <security@auditcode.ai>
scsi: scsi_debug: Fix REPORT ZONES alloc_len underflow OOB write
Damien Le Moal <damien.lemoal@opensource.wdc.com>
scsi: scsi_debug: Rename zone type constants
Damien Le Moal <damien.lemoal@opensource.wdc.com>
scsi: sd: sd_zbc: Return early in sd_zbc_check_zoned_characteristics()
Damien Le Moal <damien.lemoal@opensource.wdc.com>
scsi: sd: sd_zbc: Use logical blocks as unit when querying zones
Bart Van Assche <bvanassche@acm.org>
scsi: sd: sd_zbc: Improve source code documentation
Chengfeng Ye <nicoyip.dev@gmail.com>
net: pktgen: fix proc entry use-after-free
Peter Seiderer <ps.report@gmx.net>
net: pktgen: fix code style (WARNING: Block comments)
Gregory Price <gourry@gourry.net>
mm/vmstat: fold stranded per-cpu node stats when a node comes online
Sangho Lee <kudo3228@gmail.com>
Bluetooth: HIDP: reject frames without a transaction header
Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
skbuff: introduce skb_pull_data
Tengda Wu <wutengda@huaweicloud.com>
ftrace: Add global mutex to serialize trace_parser access
Christian Brauner <brauner@kernel.org>
super: fix emergency thaw deadlock on frozen block devices
Shiming Cheng <shiming.cheng@mediatek.com>
net: gro: fix double aggregation of flush-marked skbs
Aldo Ariel Panzardo <qwe.aldo@gmail.com>
net/sched: serialize qdisc_rtab_list against concurrent get/put
Max Kellermann <max.kellermann@ionos.com>
ceph: fix hanging __ceph_get_caps() with stale mds_wanted
Xiubo Li <xiubli@redhat.com>
ceph: rename _to_client() to _to_fs_client()
Xiubo Li <xiubli@redhat.com>
libceph: add doutc and *_client debug macros support
Pavitra Jha <jhapavitra98@gmail.com>
libceph: fix two unsafe bare decodes in decode_lockers()
Xiang Mei <xmei5@asu.edu>
libceph: bound pg_{temp,upmap,upmap_items} length to CEPH_PG_MAX_SIZE
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
libceph: Amend checking to fix `make W=1` build breakage
Max Kellermann <max.kellermann@ionos.com>
ceph: avoid fs reclaim while using current->journal_info
Zhiling Zou <roxy520tt@gmail.com>
sctp: avoid auth_enable sysctl UAF during netns teardown
Chenguang Zhao <zhaochenguang@kylinos.cn>
mptcp: decrement subflows counter on failed passive join
Paolo Abeni <pabeni@redhat.com>
mptcp: fix subflow accounting on close
Hugo Villeneuve <hvilleneuve@dimonoff.com>
serial: sc16is7xx: implement gpio get_direction() callback
Hugo Villeneuve <hvilleneuve@dimonoff.com>
serial: sc16is7xx: fix regression with GPIO configuration
Hugo Villeneuve <hvilleneuve@dimonoff.com>
serial: sc16is7xx: remove obsolete out_thread label
Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
serial: sc16is7xx: Fill in rs485_supported
Tomasz Moń <tomasz.mon@camlingroup.com>
sc16is7xx: Properly resume TX after stop
Michael Bommarito <michael.bommarito@gmail.com>
mptcp: only set DATA_FIN when a mapping is present
Jiangshan Yi <yijiangshan@kylinos.cn>
serial: 8250_mid: Fix NULL function pointer dereference on DNV/ICX-D/SNR platforms
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
serial: 8250_mid: Remove unneeded test for ->setup() presence
Norbert Szetei <norbert@doyensec.com>
ALSA: seq: close a re-opened queue timer in the destructor
Fan Wu <fanwu01@zju.edu.cn>
wifi: brcmfmac: drain bus_reset work on device removal
Mirela Rabulea <mirela.rabulea@nxp.com>
media: v4l2-fwnode: Fix subdev owner overwritten in v4l2_async_register_subdev_sensor()
Sakari Ailus <sakari.ailus@linux.intel.com>
media: v4l: async: Set owner for async sub-devices
Daniel Hodges <git@danielhodges.dev>
wifi: ath6kl: fix use-after-free in aggr_reset_state()
Sakari Ailus <sakari.ailus@linux.intel.com>
media: imx219: Fix maximum frame length in lines
Jai Luthra <jai.luthra@ideasonboard.com>
media: i2c: imx219: Rename VTS to FRM_LENGTH
David Plowman <david.plowman@raspberrypi.com>
media: i2c: imx219: Correct the minimum vblanking value
Laurent Pinchart <laurent.pinchart@ideasonboard.com>
media: i2c: imx219: Drop IMX219_VTS_* macros
Guangshuo Li <lgs201920130244@gmail.com>
media: marvell-cam: fix missing pci_disable_device() on remove
Jani Nikula <jani.nikula@intel.com>
drm/i915/hdcp: require monotonically increasing seq_num_v
David Carlier <devnexen@gmail.com>
media: aspeed: fix missing of_reserved_mem_device_release() on probe failure
Bryam Vargas <hexlabsecurity@proton.me>
drm/virtio: bound EDID block reads to the response buffer
Dmitry Osipenko <dmitry.osipenko@collabora.com>
drm/virtio: Return proper error codes instead of -1
Thomas Zimmermann <tzimmermann@suse.de>
drm/tegra: fbdev: Remove offset into framebuffer memory
Jani Nikula <jani.nikula@intel.com>
drm/displayid: fix Tiled Display Topology ID size
Deepanshu Kartikey <kartikey406@gmail.com>
drm/virtio: use uninterruptible resv lock for plane updates
Christian König <christian.koenig@amd.com>
dma-buf/drivers: make reserving a shared slot mandatory v4
Ashutosh Desai <ashutoshdesai993@gmail.com>
drm/dp/mst: fix OOB reads in remote DPCD/I2C sideband reply parsers
Ashutosh Desai <ashutoshdesai993@gmail.com>
drm/dp/mst: fix OOB reads on 2-byte fields in sideband reply parsers
Cen Zhang <zzzccc427@gmail.com>
usb: gadget: f_tcm: synchronize delayed set_alt with teardown
Ashutosh Desai <ashutoshdesai993@gmail.com>
drm/dp/mst: fix buffer overflows in sideband chunk accumulation
Venkatesh Srinivas <venkateshs@chromium.org>
KVM: x86: Only reset TSC Deadline Timer in apic_timer_expired on KVM_RUN
David Matlack <dmatlack@google.com>
KVM: Introduce vcpu->wants_to_run
Sean Christopherson <seanjc@google.com>
KVM: x86: Move "apicv_active" into "struct kvm_lapic"
Sean Christopherson <seanjc@google.com>
KVM: x86: Check for in-kernel xAPIC when querying APICv for directed yield
Sean Christopherson <seanjc@google.com>
KVM: x86: Drop @vcpu parameter from kvm_x86_ops.hwapic_isr_update()
Johan Hovold <johan@kernel.org>
USB: serial: keyspan_pda: fix data loss on receive throttling
Johan Hovold <johan@kernel.org>
USB: serial: keyspan_pda: clean up comments and whitespace
Johan Hovold <johan@kernel.org>
USB: serial: keyspan_pda: add write-fifo support
Johan Hovold <johan@kernel.org>
USB: serial: keyspan_pda: fix write implementation
Johan Hovold <johan@kernel.org>
USB: serial: keyspan_pda: refactor write-room handling
Fan Wu <fanwu01@zju.edu.cn>
usb: gadget: udc: bdc: free IRQ and drain func_wake_notify before teardown
Chunfeng Yun <chunfeng.yun@mediatek.com>
usb: gadget: bdc: fix checkpatch.pl spacing error
Reinette Chatre <reinette.chatre@intel.com>
fs/resctrl: Fix double-add of pseudo-locked region's RMID to free list
Dawei Feng <dawei.feng@seu.edu.cn>
octeontx2-pf: fix SQB pointer leak on init failure
Haoxiang Li <haoxiang_li2024@163.com>
net: ipa: fix SMEM state handle leaks in SMP2P init
Sabrina Dubroca <sd@queasysnail.net>
espintcp: use sk_msg_free_partial to fix partial send
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
Rasmus Villemoes <linux@rasmusvillemoes.dk>
bootconfig: do not put quotes on cmdline items unless necessary
Runyu Xiao <runyu.xiao@seu.edu.cn>
gpio: tegra: do not call pinctrl for GPIO direction
Bryam Vargas <hexlabsecurity@proton.me>
net/sched: sch_taprio: Replace direct dequeue call with peek and qdisc_dequeue_peeked
Vladimir Oltean <vladimir.oltean@nxp.com>
net/sched: taprio: avoid calling child->ops->dequeue(child) twice
Maoyi Xie <maoyixie.tju@gmail.com>
net: ip6_tunnel: require CAP_NET_ADMIN in the device netns for changelink
Maoyi Xie <maoyixie.tju@gmail.com>
net: ipip: require CAP_NET_ADMIN in the device netns for changelink
Liu Jian <liujian56@huawei.com>
net: Add helper function to parse netlink msg of ip_tunnel_encap
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: ims-pcu - fix firmware leak in async update
Dmitry Torokhov <dmitry.torokhov@gmail.com>
firmware_loader: introduce __free() cleanup hanler
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()
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: ims-pcu - fix race condition in reset_device sysfs callback
Mikulas Patocka <mpatocka@redhat.com>
dm-verity: make error counter atomic
Mikulas Patocka <mpatocka@redhat.com>
dm-integrity: don't increment hash_offset twice
Bryam Vargas <hexlabsecurity@proton.me>
scsi: target: Bound PR-OUT TransportID parsing to the received buffer
Maurizio Lombardi <mlombard@redhat.com>
scsi: target: core: Generate correct identifiers for PR OUT transport IDs
Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
scsi: target: core: pr: Initialize arrays at declaration time
Souvik Banerjee <souvik@amlalabs.com>
ovl: use linked upper dentry in copy-up tmpfile
Abdun Nihaal <nihaal@cse.iitm.ac.in>
scsi: lpfc: Fix memory leak in lpfc_sli4_driver_resource_setup()
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: Keep XDomain reference during the lifetime of a service
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
Frank Li <Frank.Li@nxp.com>
dmaengine: dw-edma: Add spinlock to protect DONE_INT_MASK and ABORT_INT_MASK
Frank Li <Frank.Li@nxp.com>
dmaengine: dw-edma: Remove unused irq field in struct dw_edma_chip
Gustavo Pimentel <Gustavo.Pimentel@synopsys.com>
dmaengine: dw-edma: Improve the linked list and data blocks definition
Gustavo Pimentel <Gustavo.Pimentel@synopsys.com>
PCI: Add pci_find_vsec_capability() to find a specific VSEC
Jarkko Sakkinen <jarkko@kernel.org>
tpm: tpm_tis_spi: Use wait_woken() in wait_for_tmp_stat()
Fredric Cover <fredric.cover.lkernel@gmail.com>
smb: client: use kvzalloc() for megabyte buffer in simple fallocate
Miquel Raynal <miquel.raynal@bootlin.com>
mtd: spi-nor: swp: Improve locking user experience
Michael Walle <mwalle@kernel.org>
mtd: spi-nor: Fix spi_nor_try_unlock_all()
Tudor Ambarus <tudor.ambarus@microchip.com>
mtd: spi-nor: Move Software Write Protection logic out of the core
Michael Walle <michael@walle.cc>
mtd: spi-nor: intel: remove global protection flag
Michael Walle <michael@walle.cc>
mtd: spi-nor: sst: remove global protection flag
Yiyang Chen <cyyzero16@gmail.com>
taskstats: retain dead thread stats in TGID queries
Oleg Nesterov <oleg@redhat.com>
taskstats: fill_stats_for_tgid: use for_each_thread()
Maoyi Xie <maoyixie.tju@gmail.com>
net: thunderbolt: Fix frags[] overflow by bounding frame_count
Florian Fuchs <fuchsfl@gmail.com>
mtd: maps: vmu-flash: fix fault in unaligned fixup
Breno Leitao <leitao@debian.org>
9p: skip nlink update in cacheless mode to fix WARN_ON
Vasiliy Kovalev <kovalev@altlinux.org>
net/9p: fix infinite loop in p9_client_rpc on fatal signal
Tristan Madani <tristan@talencesecurity.com>
selinux: avoid sk_socket dereference in selinux_sctp_bind_connect()
Casey Schaufler <casey@schaufler-ca.com>
lsm: infrastructure management of the sock security
Ondrej Mosnacek <omosnace@redhat.com>
lsm: use default hook return value in call_int_hook()
Florian Westphal <fw@strlen.de>
netfilter: nft_set_pipapo: don't leak bad clone into future transaction
Florian Westphal <fw@strlen.de>
netfilter: nft_set_pipapo: move cloning of match info to insert/removal path
Florian Westphal <fw@strlen.de>
netfilter: nft_set_pipapo: prepare pipapo_get helper for on-demand clone
Florian Westphal <fw@strlen.de>
netfilter: nft_set_pipapo: merge deactivate helper into caller
Florian Westphal <fw@strlen.de>
netfilter: nft_set_pipapo: prepare walk function for on-demand clone
Florian Westphal <fw@strlen.de>
netfilter: nft_set_pipapo: make pipapo_clone helper return NULL
Florian Westphal <fw@strlen.de>
netfilter: nft_set_pipapo: use GFP_KERNEL for insertions
Junrui Luo <moonafterrain@outlook.com>
jbd2: fix integer underflow in jbd2_journal_initialize_fast_commit()
Harshad Shirwadkar <harshadshirwadkar@gmail.com>
jbd2: add a helper to find out number of fast commit blocks
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
Runyu Xiao <runyu.xiao@seu.edu.cn>
octeontx2-vf: clear stale mailbox IRQ state before request_irq()
Cássio Gabriel <cassiogabrielcontato@gmail.com>
ASoC: mediatek: mt8183: Check runtime resume during probe
Runyu Xiao <runyu.xiao@seu.edu.cn>
octeontx2-pf: clear stale mailbox IRQ state before request_irq()
Subbaraya Sundeep <sbhatta@marvell.com>
octeontx2: Annotate mmio regions as __iomem
Wentao Liang <vulab@iscas.ac.cn>
mlxsw: fix refcount leak in mlxsw_sp_port_lag_join()
Petr Machata <petrm@nvidia.com>
mlxsw: spectrum: On port enslavement to a LAG, join upper's bridges
Ido Schimmel <idosch@nvidia.com>
mlxsw: spectrum: Apply RIF configuration when joining a LAG
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: Fix recv-recv race of completed call
Li Xiasong <lixiasong1@huawei.com>
tipc: restrict socket queue dumps in enqueue tracepoints
Li Daming <d4n.for.sec@gmail.com>
rxrpc: serialize kernel accept preallocation with socket teardown
Tapio Reijonen <tapio.reijonen@vaisala.com>
serial: max310x: implement gpio_chip::get_direction()
Hugo Villeneuve <hvilleneuve@dimonoff.com>
serial: max310x: replace bare use of 'unsigned' with 'unsigned int' (checkpatch)
Xu Rao <raoxu@uniontech.com>
ALSA: hda: Fix cached processing coefficient verbs
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
Bryam Vargas <hexlabsecurity@proton.me>
Input: mms114 - reject an oversized device packet size
Zhenhao Wan <whi4ed0g@gmail.com>
RDMA/rtrs-srv: Bound RDMA-Write length to chunk size in rdma_write_sg
Akhil R <akhilrajeev@nvidia.com>
i2c: smbus: Use device_*() functions instead of of_*()
Akhil R <akhilrajeev@nvidia.com>
device property: Add fwnode_irq_get_byname
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()
Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com>
dma-buf/udmabuf: skip redundant cpu sync to fix cacheline EEXIST warning
Jason Gunthorpe <jgg@ziepe.ca>
udmabuf: Do not create malformed scatterlists
Matt Bobrowski <mattbobrowski@google.com>
bpf: Reject BPF_MAP_TYPE_INODE_STORAGE creation if BPF LSM is uninitialized
Chao Yu <chao@kernel.org>
f2fs: fix UAF issue in f2fs_merge_page_bio()
Xiang Mei <xmei5@asu.edu>
net/smc: reject CHID-0 ACCEPT that matches an empty ism_dev slot
Christoph Hellwig <hch@lst.de>
xfs: check v5 superblock features early
David Rosca <david.rosca@amd.com>
drm/amdgpu: Fix UVD decode image min size calculation
David Rosca <david.rosca@amd.com>
drm/amdgpu: Implement insert_end for VCE 3
David Rosca <david.rosca@amd.com>
drm/amdgpu: Reject UVD message with dimensions above 4096
Candice Li <candice.li@amd.com>
drm/amdgpu: validate GEM_CREATE domain combinations
David Rosca <david.rosca@amd.com>
drm/amdgpu: Reject UVD message with invalid number of h265 refs
Eric Farman <farman@linux.ibm.com>
s390/vfio_ccw: Fix out of bounds check on CCW array
Guangshuo Li <lgs201920130244@gmail.com>
drm/radeon: fix autosuspend cleanup during teardown
Pei Xiao <xiaopei01@kylinos.cn>
mmc: atmel-mci: Fix use-after-free in atmci_remove due to race condition
Haibo Chen <haibo.chen@nxp.com>
mmc: sdhci: make tuning_err a signed int
Myeonghun Pak <mhun512@gmail.com>
mmc: sdhci: unmap the bounce buffer before device release
Zhan Xusheng <zhanxusheng1024@gmail.com>
mmc: omap_hsmmc: fix busy_timeout overflow in ns conversion on 32-bit
Yiming Zhu <zhuyiming@kuaishou.com>
ceph: fix MDS random selection readiness predicate
Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
libceph: Avoid using invalid osd indices from primary_temp
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: sur40 - fix V4L error path cleanup
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: sur40 - fix input device registration ordering
Ali Ahmet Memis <ali@iusegentoo.com>
openrisc: signal: do not restore privileged SR bits on sigreturn
Josh Poimboeuf <jpoimboe@kernel.org>
ftrace: Fix off-by-one fentry site disable in ftrace_free_mem()
Pavitra Jha <jhapavitra98@gmail.com>
libceph: fix multiple unsafe decodes in decode_locker()
Thorsten Blum <thorsten.blum@linux.dev>
crypto: qce - fix error path in devm_qce_register_algs
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: synaptics-rmi4 - propagate F54 worker errors to V4L2 queue
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: synaptics-rmi4 - block s_input when F54 queue is busy
Bryam Vargas <hexlabsecurity@proton.me>
Input: synaptics-rmi4 - bound the F54 report size to the allocated buffer
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: synaptics-rmi4 - zero report size on F54 work error
George Wilson <gcwilson@linux.ibm.com>
powerpc/pseries: lparcfg - fix kbuf[] underflow
Pengpeng Hou <pengpeng@iscas.ac.cn>
Input: iforce - validate input packet lengths
Zhefu Zhang <a723356@gmail.com>
Input: atkbd - skip deactivate for Xiaomi Book Pro 14's internal keyboard
Linmao Li <lilinmao@kylinos.cn>
Input: psxpad-spi - set driver data before use
Richard Davies <richard@arachsys.com>
Input: focaltech - fix array out-of-bounds in focaltech_process_rel_packet
Dmitry Torokhov <dmitry.torokhov@gmail.com>
Input: synaptics-rmi4 - fix F55 transmitter electrode count typo
George Wilson <gcwilson@linux.ibm.com>
powerpc/pseries: pci - logic bug
Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
ASoC: cs4265: sort the register default table
Hidayath Khan <hidayath@linux.ibm.com>
s390/qeth: validate user buffer length in SNMP and ARP query ioctls
Matthieu Baerts (NGI0) <matttbe@kernel.org>
mptcp: options: reset DSS fields in case of unexpected size
Bryam Vargas <hexlabsecurity@proton.me>
selinux: do not cancel a policy conversion that never started
Bryam Vargas <hexlabsecurity@proton.me>
selinux: reject a class permission count below its inherited common
Bryam Vargas <hexlabsecurity@proton.me>
selinux: require every boolean value to be defined
Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
ipvs: separate destination availability state
Jiasheng Jiang <jiashengjiangcool@gmail.com>
media: mediatek: vcodec: Fix a resource leak related to the scp device in FW initialization
Fullway Wang <fullwaywang@outlook.com>
media: mtk-vcodec: potential null pointer deference in SCP
-------------
Diffstat:
Makefile | 4 +-
arch/arm64/boot/dts/nvidia/tegra194.dtsi | 2 +
arch/arm64/kvm/arm.c | 2 +-
arch/mips/kvm/mips.c | 2 +-
arch/openrisc/include/asm/processor.h | 2 +
arch/openrisc/kernel/signal.c | 5 +-
arch/powerpc/kvm/powerpc.c | 2 +-
arch/powerpc/platforms/pseries/lparcfg.c | 2 +-
arch/powerpc/platforms/pseries/pci.c | 2 +-
arch/s390/kvm/kvm-s390.c | 2 +-
arch/x86/include/asm/kvm_host.h | 3 +-
arch/x86/kernel/cpu/resctrl/rdtgroup.c | 12 +-
arch/x86/kvm/lapic.c | 41 +-
arch/x86/kvm/lapic.h | 3 +-
arch/x86/kvm/svm/avic.c | 4 +-
arch/x86/kvm/svm/svm.h | 2 +-
arch/x86/kvm/vmx/vmx.c | 9 +-
arch/x86/kvm/x86.c | 19 +-
crypto/ccm.c | 2 +-
drivers/base/property.c | 29 ++
drivers/char/tpm/tpm_tis_core.c | 38 +-
drivers/crypto/qce/core.c | 2 +-
drivers/dma-buf/dma-resv.c | 8 +-
drivers/dma-buf/udmabuf.c | 21 +-
drivers/dma/dw-edma/dw-edma-core.c | 77 ++--
drivers/dma/dw-edma/dw-edma-core.h | 20 +-
drivers/dma/dw-edma/dw-edma-pcie.c | 180 ++++++--
drivers/dma/dw-edma/dw-edma-v0-core.c | 76 ++--
drivers/fpga/dfl-afu-main.c | 3 +
drivers/gpio/gpio-tegra.c | 18 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 4 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 21 +
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 11 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 2 +-
drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 26 +-
drivers/gpu/drm/amd/pm/amdgpu_pm.c | 14 +-
drivers/gpu/drm/drm_connector.c | 12 +-
drivers/gpu/drm/drm_dp_mst_topology.c | 32 +-
drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c | 2 +-
drivers/gpu/drm/i915/display/intel_hdcp.c | 7 +-
drivers/gpu/drm/i915/i915_vma.c | 2 +-
drivers/gpu/drm/lima/lima_gem.c | 2 +-
drivers/gpu/drm/msm/msm_gem_submit.c | 2 +-
drivers/gpu/drm/nouveau/nouveau_fence.c | 2 +-
drivers/gpu/drm/qxl/qxl_release.c | 2 +-
drivers/gpu/drm/radeon/radeon_kms.c | 1 +
drivers/gpu/drm/radeon/radeon_vm.c | 2 +-
drivers/gpu/drm/tegra/fb.c | 8 +-
drivers/gpu/drm/ttm/ttm_bo.c | 4 +-
drivers/gpu/drm/ttm/ttm_execbuf_util.c | 4 +-
drivers/gpu/drm/vc4/vc4_gem.c | 2 +-
drivers/gpu/drm/vgem/vgem_fence.c | 2 +-
drivers/gpu/drm/virtio/virtgpu_drv.h | 1 +
drivers/gpu/drm/virtio/virtgpu_gem.c | 17 +
drivers/gpu/drm/virtio/virtgpu_plane.c | 5 +-
drivers/gpu/drm/virtio/virtgpu_vq.c | 9 +-
drivers/hwmon/npcm750-pwm-fan.c | 11 +
drivers/i2c/busses/i2c-bcm-iproc.c | 11 +-
drivers/i2c/busses/i2c-davinci.c | 4 +-
drivers/i2c/busses/i2c-imx.c | 126 +++--
drivers/i2c/i2c-core-base.c | 2 +-
drivers/i2c/i2c-core-smbus.c | 15 +-
drivers/i2c/i2c-smbus.c | 5 +-
drivers/infiniband/ulp/rtrs/rtrs-srv.c | 5 +-
drivers/input/joystick/iforce/iforce-packets.c | 11 +-
drivers/input/joystick/iforce/iforce-usb.c | 3 +
drivers/input/joystick/psxpad-spi.c | 1 +
drivers/input/keyboard/atkbd.c | 8 +
drivers/input/misc/ims-pcu.c | 7 +-
drivers/input/mouse/focaltech.c | 2 +-
drivers/input/rmi4/rmi_f54.c | 43 +-
drivers/input/rmi4/rmi_f55.c | 4 +-
drivers/input/touchscreen/mms114.c | 6 +
drivers/input/touchscreen/sur40.c | 23 +-
drivers/md/dm-integrity.c | 4 -
drivers/md/dm-verity-target.c | 12 +-
drivers/md/dm-verity.h | 2 +-
drivers/media/i2c/imx219.c | 47 +-
drivers/media/platform/aspeed-video.c | 1 +
drivers/media/platform/marvell-ccic/cafe-driver.c | 1 +
.../media/platform/mtk-vcodec/mtk_vcodec_fw_scp.c | 5 +
drivers/media/v4l2-core/v4l2-async.c | 8 +-
drivers/media/v4l2-core/v4l2-fwnode.c | 7 +-
drivers/mmc/host/atmel-mci.c | 2 +
drivers/mmc/host/omap_hsmmc.c | 2 +-
drivers/mmc/host/sdhci.c | 16 +
drivers/mmc/host/sdhci.h | 2 +-
drivers/mmc/host/vub300.c | 36 +-
drivers/mtd/maps/vmu-flash.c | 8 +-
drivers/mtd/spi-nor/Makefile | 2 +-
drivers/mtd/spi-nor/core.c | 406 +----------------
drivers/mtd/spi-nor/core.h | 5 +
drivers/mtd/spi-nor/intel.c | 16 +-
drivers/mtd/spi-nor/sst.c | 30 +-
drivers/mtd/spi-nor/swp.c | 426 +++++++++++++++++
drivers/net/can/usb/gs_usb.c | 2 +-
drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 25 +
drivers/net/ethernet/aquantia/atlantic/aq_ring.h | 1 +
drivers/net/ethernet/aquantia/atlantic/aq_vec.c | 2 +-
drivers/net/ethernet/intel/ice/ice_ethtool.c | 10 +-
drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c | 48 ++
.../net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 13 +-
.../net/ethernet/marvell/octeontx2/nic/otx2_vf.c | 8 +-
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 109 ++++-
drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 4 +
.../net/ethernet/mellanox/mlxsw/spectrum_router.c | 31 +-
drivers/net/ethernet/ti/am65-cpsw-nuss.c | 139 ++++--
drivers/net/ethernet/ti/am65-cpsw-nuss.h | 4 +
drivers/net/ipa/ipa_smp2p.c | 30 +-
drivers/net/thunderbolt.c | 8 +-
drivers/net/wireless/ath/ath6kl/txrx.c | 2 +-
.../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 13 +
.../net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 6 +
.../wireless/broadcom/brcm80211/brcmfmac/core.c | 45 +-
.../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 6 +
.../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 6 +
.../wireless/broadcom/brcm80211/brcmfmac/sdio.h | 1 +
.../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 3 +
drivers/net/wireless/marvell/libertas_tf/main.c | 2 +-
drivers/pci/pci.c | 30 ++
drivers/s390/cio/vfio_ccw_cp.c | 17 +-
drivers/s390/net/qeth_core_main.c | 3 +
drivers/s390/net/qeth_l3_main.c | 5 +
drivers/scsi/lpfc/lpfc_init.c | 3 +-
drivers/scsi/scsi_debug.c | 27 +-
drivers/scsi/sd.h | 5 +-
drivers/scsi/sd_zbc.c | 79 +++-
drivers/target/target_core_fabric_lib.c | 146 ++++--
drivers/target/target_core_internal.h | 5 +-
drivers/target/target_core_pr.c | 54 +--
drivers/thunderbolt/domain.c | 30 ++
drivers/thunderbolt/icm.c | 5 +
drivers/thunderbolt/switch.c | 14 +
drivers/thunderbolt/tb.c | 58 +--
drivers/thunderbolt/tb.h | 2 +
drivers/thunderbolt/xdomain.c | 71 ++-
drivers/tty/serial/8250/8250_mid.c | 6 +-
drivers/tty/serial/max310x.c | 20 +-
drivers/tty/serial/sc16is7xx.c | 192 ++++++--
drivers/usb/gadget/function/f_tcm.c | 192 ++++++--
drivers/usb/gadget/function/tcm.h | 13 +
drivers/usb/gadget/udc/bdc/bdc_core.c | 20 +
drivers/usb/gadget/udc/bdc/bdc_udc.c | 7 +-
drivers/usb/serial/keyspan_pda.c | 471 ++++++++++---------
fs/9p/vfs_inode.c | 9 +
fs/binfmt_elf.c | 4 +-
fs/binfmt_elf_fdpic.c | 4 +-
fs/binfmt_misc.c | 14 +-
fs/ceph/addr.c | 24 +-
fs/ceph/cache.c | 2 +-
fs/ceph/caps.c | 53 ++-
fs/ceph/dir.c | 20 +-
fs/ceph/export.c | 10 +-
fs/ceph/file.c | 33 +-
fs/ceph/inode.c | 20 +-
fs/ceph/ioctl.c | 8 +-
fs/ceph/mds_client.c | 11 +
fs/ceph/mds_client.h | 2 +
fs/ceph/mdsmap.c | 2 +-
fs/ceph/super.c | 22 +-
fs/ceph/super.h | 8 +-
fs/ceph/xattr.c | 8 +-
fs/cifs/smb2ops.c | 4 +-
fs/exec.c | 6 +-
fs/f2fs/data.c | 2 +-
fs/jbd2/journal.c | 10 +-
fs/namei.c | 42 ++
fs/overlayfs/copy_up.c | 14 +-
fs/super.c | 19 +-
fs/xfs/libxfs/xfs_sb.c | 4 +-
include/drm/drm_connector.h | 6 +-
include/drm/drm_displayid.h | 2 +-
include/linux/audit.h | 18 +-
include/linux/bootconfig.h | 3 +
include/linux/bpf_lsm.h | 4 +
include/linux/ceph/ceph_debug.h | 38 ++
include/linux/dma-resv.h | 2 +-
include/linux/dma/edma.h | 2 -
include/linux/firmware.h | 3 +
include/linux/fs.h | 28 ++
include/linux/i2c-smbus.h | 6 +-
include/linux/jbd2.h | 9 +-
include/linux/kvm_host.h | 1 +
include/linux/lsm_hooks.h | 1 +
include/linux/namei.h | 1 +
include/linux/pci.h | 1 +
include/linux/property.h | 1 +
include/linux/skbuff.h | 2 +
include/linux/thunderbolt.h | 3 +
include/media/v4l2-async.h | 9 +-
include/net/act_api.h | 20 +
include/net/ip_tunnels.h | 3 +
include/net/ip_vs.h | 7 +
include/trace/events/rxrpc.h | 2 +
include/uapi/linux/ip_vs.h | 6 -
init/main.c | 39 --
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/bpf_inode_storage.c | 10 +
kernel/sched/psi.c | 6 +
kernel/taskstats.c | 67 +--
kernel/trace/ftrace.c | 21 +-
lib/bootconfig.c | 65 +++
lib/compat_audit.c | 12 +-
mm/memory_hotplug.c | 15 +-
mm/pagewalk.c | 8 +
mm/ptdump.c | 7 +
net/9p/client.c | 2 +
net/bluetooth/hidp/core.c | 25 +-
net/ceph/cls_lock_client.c | 21 +-
net/ceph/osdmap.c | 9 +-
net/core/pktgen.c | 43 +-
net/core/skbuff.c | 28 +-
net/ipv4/ip_tunnel_core.c | 35 ++
net/ipv4/ipip.c | 41 +-
net/ipv6/ip6_tunnel.c | 40 +-
net/ipv6/sit.c | 38 +-
net/mptcp/options.c | 21 +-
net/mptcp/protocol.c | 4 +-
net/mptcp/protocol.h | 14 +
net/mptcp/subflow.c | 12 +-
net/netfilter/ipset/ip_set_core.c | 19 +-
net/netfilter/ipset/ip_set_list_set.c | 7 +-
net/netfilter/ipvs/ip_vs_conn.c | 4 +-
net/netfilter/ipvs/ip_vs_core.c | 6 +-
net/netfilter/ipvs/ip_vs_ctl.c | 4 +-
net/netfilter/ipvs/ip_vs_dh.c | 4 +-
net/netfilter/ipvs/ip_vs_lblc.c | 2 +-
net/netfilter/ipvs/ip_vs_lblcr.c | 8 +-
net/netfilter/nf_conntrack_sip.c | 10 +-
net/netfilter/nf_flow_table_core.c | 7 +-
net/netfilter/nf_tables_offload.c | 2 +-
net/netfilter/nft_set_pipapo.c | 252 ++++++----
net/netfilter/nft_set_pipapo.h | 8 +
net/packet/af_packet.c | 7 +-
net/rxrpc/call_accept.c | 28 +-
net/rxrpc/call_object.c | 27 +-
net/rxrpc/recvmsg.c | 23 +-
net/sched/act_gact.c | 5 +
net/sched/act_police.c | 6 +
net/sched/sch_api.c | 24 +-
net/sched/sch_taprio.c | 12 +-
net/sctp/protocol.c | 20 +-
net/sctp/sysctl.c | 9 +-
net/smc/af_smc.c | 3 +-
net/smc/smc_rx.c | 12 +-
net/smc/smc_tx.c | 17 +-
net/tipc/socket.c | 6 +-
net/xfrm/espintcp.c | 32 +-
security/apparmor/include/net.h | 6 +-
security/apparmor/lsm.c | 38 +-
security/bpf/hooks.c | 3 +
security/security.c | 506 +++++++++++++--------
security/selinux/hooks.c | 91 ++--
security/selinux/include/objsec.h | 5 +
security/selinux/netlabel.c | 23 +-
security/selinux/ss/policydb.c | 31 ++
security/selinux/ss/services.c | 4 +-
security/smack/smack.h | 5 +
security/smack/smack_lsm.c | 66 ++-
security/smack/smack_netfilter.c | 8 +-
sound/core/seq/seq_timer.c | 13 +-
sound/hda/hdac_regmap.c | 4 +-
sound/soc/codecs/cs4265.c | 4 +-
sound/soc/mediatek/mt8183/mt8183-afe-pcm.c | 12 +-
sound/soc/xilinx/xlnx_formatter_pcm.c | 10 +-
sound/usb/usx2y/usX2Yhwdep.c | 10 +-
sound/usb/usx2y/usbus428ctldefs.h | 2 +
sound/usb/usx2y/usbusx2y.c | 2 +-
sound/usb/usx2y/usx2yhwdeppcm.c | 15 +-
virt/kvm/kvm_main.c | 3 +
276 files changed, 4340 insertions(+), 2447 deletions(-)
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 001/235] media: mtk-vcodec: potential null pointer deference in SCP
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
@ 2026-08-20 14:53 ` Greg Kroah-Hartman
2026-08-20 14:53 ` [PATCH 5.10 002/235] media: mediatek: vcodec: Fix a resource leak related to the scp device in FW initialization Greg Kroah-Hartman
` (236 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:53 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Fullway Wang, Mauro Carvalho Chehab,
Andrey Troshin, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fullway Wang <fullwaywang@outlook.com>
[ Upstream commit 53dbe08504442dc7ba4865c09b3bbf5fe849681b ]
The return value of devm_kzalloc() needs to be checked to avoid
NULL pointer deference. This is similar to CVE-2022-3113.
Link: https://lore.kernel.org/linux-media/PH7PR20MB5925094DAE3FD750C7E39E01BF712@PH7PR20MB5925.namprd20.prod.outlook.com
Signed-off-by: Fullway Wang <fullwaywang@outlook.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
[Andrey Troshin: backport fixs from
drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_scp.c
to drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_scp.c]
Signed-off-by: Andrey Troshin <drtrosh@yandex-team.ru>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_scp.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_scp.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_scp.c
index d8e66b645bd8..27f08b1d34d1 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_scp.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_scp.c
@@ -65,6 +65,8 @@ struct mtk_vcodec_fw *mtk_vcodec_fw_scp_init(struct mtk_vcodec_dev *dev)
}
fw = devm_kzalloc(&dev->plat_dev->dev, sizeof(*fw), GFP_KERNEL);
+ if (!fw)
+ return ERR_PTR(-ENOMEM);
fw->type = SCP;
fw->ops = &mtk_vcodec_rproc_msg;
fw->scp = scp;
--
2.53.0
^ permalink raw reply related [flat|nested] 239+ messages in thread
* [PATCH 5.10 002/235] media: mediatek: vcodec: Fix a resource leak related to the scp device in FW initialization
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
2026-08-20 14:53 ` [PATCH 5.10 001/235] media: mtk-vcodec: potential null pointer deference in SCP Greg Kroah-Hartman
@ 2026-08-20 14:53 ` Greg Kroah-Hartman
2026-08-20 14:53 ` [PATCH 5.10 003/235] ipvs: separate destination availability state Greg Kroah-Hartman
` (235 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:53 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jiasheng Jiang, Hans Verkuil,
Andrey Troshin, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiasheng Jiang <jiashengjiangcool@gmail.com>
[ Upstream commit 4936cd5817af35d23e4d283f48fa59a18ef481e4 ]
On Mediatek devices with a system companion processor (SCP) the mtk_scp
structure has to be removed explicitly to avoid a resource leak.
Free the structure in case the allocation of the firmware structure fails
during the firmware initialization.
Fixes: 53dbe0850444 ("media: mtk-vcodec: potential null pointer deference in SCP")
Cc: stable@vger.kernel.org
Signed-off-by: Jiasheng Jiang <jiashengjiangcool@gmail.com>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
[Andrey Troshin: backport fixs from
drivers/media/platform/mediatek/vcodec/common/mtk_vcodec_fw_scp.c
to drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_scp.c]
Signed-off-by: Andrey Troshin <drtrosh@yandex-team.ru>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_scp.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_scp.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_scp.c
index 27f08b1d34d1..199a64c853bc 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_scp.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_scp.c
@@ -65,8 +65,11 @@ struct mtk_vcodec_fw *mtk_vcodec_fw_scp_init(struct mtk_vcodec_dev *dev)
}
fw = devm_kzalloc(&dev->plat_dev->dev, sizeof(*fw), GFP_KERNEL);
- if (!fw)
+ if (!fw) {
+ scp_put(scp);
return ERR_PTR(-ENOMEM);
+ }
+
fw->type = SCP;
fw->ops = &mtk_vcodec_rproc_msg;
fw->scp = scp;
--
2.53.0
^ permalink raw reply related [flat|nested] 239+ messages in thread
* [PATCH 5.10 003/235] ipvs: separate destination availability state
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
2026-08-20 14:53 ` [PATCH 5.10 001/235] media: mtk-vcodec: potential null pointer deference in SCP Greg Kroah-Hartman
2026-08-20 14:53 ` [PATCH 5.10 002/235] media: mediatek: vcodec: Fix a resource leak related to the scp device in FW initialization Greg Kroah-Hartman
@ 2026-08-20 14:53 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 004/235] selinux: require every boolean value to be defined Greg Kroah-Hartman
` (234 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:53 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yizhou Zhao, Yuxiang Yang, Ao Wang,
Xuewei Feng, Qi Li, Ke Xu, Julian Anastasov, Pablo Neira Ayuso,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
commit cdcc4e46180df8161f4d2f3c6fd6beaf6990133d upstream.
IPVS configuration paths update destination availability while connection
accounting updates destination overload state. The two independent states
share dest->flags, so their read-modify-write updates can race and lose one
another.
Keep OVERLOAD in flags, where the preceding patch serializes its updates
with dst_lock, and move AVAILABLE to cflags. This keeps configuration-
controlled availability out of the scheduler hot cacheline until a
scheduler needs to check it. It also prevents availability updates from
clobbering overload state.
The destination status bits are not exposed through the IPVS sockopt or
netlink interfaces, so keep their definitions in the internal IPVS header.
Readers can still observe stale destination state; this does not provide a
cross-field snapshot.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
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>
Link: https://lore.kernel.org/all/8913381c-1e02-35c7-0ec4-61de5a12fd35@ssi.bg/
Assisted-by: Claude-Code:GLM-5.2
Suggested-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Yizhou Zhao <zhaoyz24@mails.tsinghua.edu.cn>
Acked-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit cdcc4e46180df8161f4d2f3c6fd6beaf6990133d)
[ Julian: Backport by removing the hunks from ip_vs_xmit.c ]
Signed-off-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
include/net/ip_vs.h | 7 +++++++
include/uapi/linux/ip_vs.h | 6 ------
net/netfilter/ipvs/ip_vs_conn.c | 4 ++--
net/netfilter/ipvs/ip_vs_core.c | 6 +++---
net/netfilter/ipvs/ip_vs_ctl.c | 4 ++--
net/netfilter/ipvs/ip_vs_dh.c | 4 ++--
net/netfilter/ipvs/ip_vs_lblc.c | 2 +-
net/netfilter/ipvs/ip_vs_lblcr.c | 8 ++++----
8 files changed, 21 insertions(+), 20 deletions(-)
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 9f4224eb18a34..d9a2e1e080fd9 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -33,6 +33,12 @@
#define IP_VS_HDR_INVERSE 1
#define IP_VS_HDR_ICMP 2
+/* Destination Server Flags */
+#define IP_VS_DEST_F_OVERLOAD 0x0002 /* server is overloaded */
+
+/* Destination Server Config Flags */
+#define IP_VS_DEST_CF_AVAILABLE 0x0001 /* server is available */
+
/* Generic access of ipvs struct */
static inline struct netns_ipvs *net_ipvs(struct net* net)
{
@@ -664,6 +670,7 @@ struct ip_vs_dest {
volatile unsigned int flags; /* dest status flags */
atomic_t conn_flags; /* flags to copy to conn */
atomic_t weight; /* server weight */
+ unsigned long cflags; /* config flags */
atomic_t last_weight; /* server latest weight */
__u16 tun_type; /* tunnel type */
__be16 tun_port; /* tunnel port */
diff --git a/include/uapi/linux/ip_vs.h b/include/uapi/linux/ip_vs.h
index 4102ddcb4e14e..9e4a762f31d83 100644
--- a/include/uapi/linux/ip_vs.h
+++ b/include/uapi/linux/ip_vs.h
@@ -28,12 +28,6 @@
#define IP_VS_SVC_F_SCHED_SH_FALLBACK IP_VS_SVC_F_SCHED1 /* SH fallback */
#define IP_VS_SVC_F_SCHED_SH_PORT IP_VS_SVC_F_SCHED2 /* SH use port */
-/*
- * Destination Server Flags
- */
-#define IP_VS_DEST_F_AVAILABLE 0x0001 /* server is available */
-#define IP_VS_DEST_F_OVERLOAD 0x0002 /* server is overloaded */
-
/*
* IPVS sync daemon states
*/
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index f4506bc166cef..90efb3c3760c8 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -759,7 +759,7 @@ int ip_vs_check_template(struct ip_vs_conn *ct, struct ip_vs_dest *cdest)
* Checking the dest server status.
*/
if ((dest == NULL) ||
- !(dest->flags & IP_VS_DEST_F_AVAILABLE) ||
+ !(dest->cflags & IP_VS_DEST_CF_AVAILABLE) ||
expire_quiescent_template(ipvs, dest) ||
(cdest && (dest != cdest))) {
IP_VS_DBG_BUF(9, "check_template: dest not available for "
@@ -1402,7 +1402,7 @@ void ip_vs_expire_nodest_conn_flush(struct netns_ipvs *ipvs)
continue;
dest = cp->dest;
- if (!dest || (dest->flags & IP_VS_DEST_F_AVAILABLE))
+ if (!dest || (dest->cflags & IP_VS_DEST_CF_AVAILABLE))
continue;
if (atomic_read(&cp->n_control))
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index ea9b5f434ec06..c3d2e70bb007b 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -136,7 +136,7 @@ ip_vs_in_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
struct ip_vs_dest *dest = cp->dest;
struct netns_ipvs *ipvs = cp->ipvs;
- if (dest && (dest->flags & IP_VS_DEST_F_AVAILABLE)) {
+ if (dest && (dest->cflags & IP_VS_DEST_CF_AVAILABLE)) {
struct ip_vs_cpu_stats *s;
struct ip_vs_service *svc;
@@ -172,7 +172,7 @@ ip_vs_out_stats(struct ip_vs_conn *cp, struct sk_buff *skb)
struct ip_vs_dest *dest = cp->dest;
struct netns_ipvs *ipvs = cp->ipvs;
- if (dest && (dest->flags & IP_VS_DEST_F_AVAILABLE)) {
+ if (dest && (dest->cflags & IP_VS_DEST_CF_AVAILABLE)) {
struct ip_vs_cpu_stats *s;
struct ip_vs_service *svc;
@@ -2096,7 +2096,7 @@ ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int
}
/* Check the server status */
- if (cp && cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) {
+ if (cp && cp->dest && !(cp->dest->cflags & IP_VS_DEST_CF_AVAILABLE)) {
/* the destination server is not available */
if (sysctl_expire_nodest_conn(ipvs)) {
bool old_ct = ip_vs_conn_uses_old_conntrack(cp, skb);
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 025512d76db06..2ded17b67819a 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -961,7 +961,7 @@ __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest,
}
/* set the dest status flags */
- dest->flags |= IP_VS_DEST_F_AVAILABLE;
+ dest->cflags |= IP_VS_DEST_CF_AVAILABLE;
if (READ_ONCE(dest->u_threshold) != udest->u_threshold ||
READ_ONCE(dest->l_threshold) != udest->l_threshold) {
@@ -1240,7 +1240,7 @@ static void __ip_vs_unlink_dest(struct ip_vs_service *svc,
struct ip_vs_dest *dest,
int svcupd)
{
- dest->flags &= ~IP_VS_DEST_F_AVAILABLE;
+ dest->cflags &= ~IP_VS_DEST_CF_AVAILABLE;
/*
* Remove it from the d-linked destination list.
diff --git a/net/netfilter/ipvs/ip_vs_dh.c b/net/netfilter/ipvs/ip_vs_dh.c
index 5e6ec32aff2b1..6d88bb4bf4ae8 100644
--- a/net/netfilter/ipvs/ip_vs_dh.c
+++ b/net/netfilter/ipvs/ip_vs_dh.c
@@ -220,8 +220,8 @@ ip_vs_dh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
s = (struct ip_vs_dh_state *) svc->sched_data;
dest = ip_vs_dh_get(svc->af, s, &iph->daddr);
- if (!dest
- || !(dest->flags & IP_VS_DEST_F_AVAILABLE)
+ if (!dest ||
+ !(dest->cflags & IP_VS_DEST_CF_AVAILABLE)
|| atomic_read(&dest->weight) <= 0
|| is_overloaded(dest)) {
ip_vs_scheduler_err(svc, "no destination available");
diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c
index 7ac7473e3804c..e2480f33a1963 100644
--- a/net/netfilter/ipvs/ip_vs_lblc.c
+++ b/net/netfilter/ipvs/ip_vs_lblc.c
@@ -503,7 +503,7 @@ ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
*/
dest = en->dest;
- if ((dest->flags & IP_VS_DEST_F_AVAILABLE) &&
+ if ((dest->cflags & IP_VS_DEST_CF_AVAILABLE) &&
atomic_read(&dest->weight) > 0 && !is_overloaded(dest, svc))
goto out;
}
diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c
index 77c323c36a889..7469547c8a440 100644
--- a/net/netfilter/ipvs/ip_vs_lblcr.c
+++ b/net/netfilter/ipvs/ip_vs_lblcr.c
@@ -170,8 +170,8 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set)
if (least->flags & IP_VS_DEST_F_OVERLOAD)
continue;
- if ((atomic_read(&least->weight) > 0)
- && (least->flags & IP_VS_DEST_F_AVAILABLE)) {
+ if ((atomic_read(&least->weight) > 0) &&
+ (least->cflags & IP_VS_DEST_CF_AVAILABLE)) {
loh = ip_vs_dest_conn_overhead(least);
goto nextstage;
}
@@ -187,8 +187,8 @@ static inline struct ip_vs_dest *ip_vs_dest_set_min(struct ip_vs_dest_set *set)
doh = ip_vs_dest_conn_overhead(dest);
if (((__s64)loh * atomic_read(&dest->weight) >
- (__s64)doh * atomic_read(&least->weight))
- && (dest->flags & IP_VS_DEST_F_AVAILABLE)) {
+ (__s64)doh * atomic_read(&least->weight)) &&
+ (dest->cflags & IP_VS_DEST_CF_AVAILABLE)) {
least = dest;
loh = doh;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 239+ messages in thread
* [PATCH 5.10 004/235] selinux: require every boolean value to be defined
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (2 preceding siblings ...)
2026-08-20 14:53 ` [PATCH 5.10 003/235] ipvs: separate destination availability state Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 005/235] selinux: reject a class permission count below its inherited common Greg Kroah-Hartman
` (233 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Bryam Vargas, Stephen Smalley,
Paul Moore
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <hexlabsecurity@proton.me>
commit a93d37a09b863810653f93d371fb197457d59deb upstream.
p_bools.nprim comes from the policy image independently of how many
booleans follow it, and cond_index_bool() fills bool_val_to_struct[] at
value - 1, so a count larger than the values present leaves NULL entries.
Every user of that array then walks it by index and dereferences each
entry: cond_evaluate_expr() on the access-vector path,
security_get_bools() and security_get_bool_value() behind selinuxfs, and
security_set_bools(). A sparse class value is absorbed by
policydb_class_isvalid() and its siblings; booleans have no such
predicate, and no consumer that could use one.
Reject a boolean value that no boolean defines, once, where the array is
built. Conforming policies define every boolean they declare and are
unaffected.
Cc: stable@vger.kernel.org
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
security/selinux/ss/policydb.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -718,6 +718,7 @@ static inline void hash_eval(struct hash
static int policydb_index(struct policydb *p)
{
int i, rc;
+ u32 v;
if (p->mls_enabled)
pr_debug("SELinux: %d users, %d roles, %d types, %d bools, %d sens, %d cats\n",
@@ -775,6 +776,24 @@ static int policydb_index(struct policyd
if (rc)
goto out;
}
+
+ /*
+ * A sparse class value is absorbed by policydb_class_isvalid() and
+ * its siblings, but no such predicate exists for booleans: every
+ * user of bool_val_to_struct[] walks it by index and dereferences
+ * each entry -- cond_evaluate_expr(), the two getters and
+ * security_set_bools() -- so an unclaimed one has no consumer that
+ * can tolerate it.
+ */
+ for (v = 0; v < p->p_bools.nprim; v++) {
+ if (!p->bool_val_to_struct[v]) {
+ pr_err("SELinux: boolean %u is declared but not defined\n",
+ v + 1);
+ rc = -EINVAL;
+ goto out;
+ }
+ }
+
rc = 0;
out:
return rc;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 005/235] selinux: reject a class permission count below its inherited common
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (3 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 004/235] selinux: require every boolean value to be defined Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 006/235] selinux: do not cancel a policy conversion that never started Greg Kroah-Hartman
` (232 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Bryam Vargas, Stephen Smalley,
Paul Moore
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <hexlabsecurity@proton.me>
commit 9a82dcd98b6e6e11cfd162410967951f12152528 upstream.
security_get_permissions() maps an inherited common's permissions into
an array sized by the class's own permissions.nprim, but class_read()
takes that nprim verbatim from the policy image and never checks that it
covers the common. A class that inherits a common of N permissions while
declaring a smaller nprim is accepted, and on load the common's
permissions are written past the class-sized array -- an out-of-bounds
heap write.
Reject a class whose permission count is below its inherited common's.
Well-formed policies, where the class count already includes the
inherited permissions, are unaffected.
Cc: stable@vger.kernel.org
Fixes: 55fcf09b3fe4 ("selinux: add support for querying object classes and permissions from the running policy")
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
security/selinux/ss/policydb.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -1356,6 +1356,18 @@ static int class_read(struct policydb *p
cladatum->comkey);
goto bad;
}
+
+ /*
+ * security_get_permissions() maps the common's permissions
+ * into an array sized by this class's nprim, so a class must
+ * declare at least as many as the common it inherits.
+ */
+ if (cladatum->permissions.nprim <
+ cladatum->comdatum->permissions.nprim) {
+ pr_err("SELinux: class %s has fewer permissions than common %s\n",
+ key, cladatum->comkey);
+ goto bad;
+ }
}
for (i = 0; i < nel; i++) {
rc = perm_read(p, &cladatum->permissions, fp);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 006/235] selinux: do not cancel a policy conversion that never started
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (4 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 005/235] selinux: reject a class permission count below its inherited common Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 007/235] mptcp: options: reset DSS fields in case of unexpected size Greg Kroah-Hartman
` (231 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Bryam Vargas, Stephen Smalley,
Paul Moore
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <hexlabsecurity@proton.me>
commit e5c0235a3c4e9eb047a16cd02323fe4ecf2f570e upstream.
sel_write_load() calls selinux_policy_cancel() when sel_make_policy_nodes()
fails, and that helper dereferences the outgoing policy to cancel its
sidtab conversion. On the first policy load there is no outgoing policy:
security_load_policy() returns early for that case, before it converts
anything, and state->policy is still NULL. A first load that fails while
building the selinuxfs tree therefore takes a NULL dereference in
selinux_policy_cancel(), reached from a write(2) to /sys/fs/selinux/load.
Skip the cancel when there is no old policy, mirroring the check
security_load_policy() already makes before it converts.
Cc: stable@vger.kernel.org
Fixes: 02a52c5c8c3b ("selinux: move policy commit after updating selinuxfs")
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
security/selinux/ss/services.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2194,7 +2194,9 @@ void selinux_policy_cancel(struct selinu
oldpolicy = rcu_dereference_protected(state->policy,
lockdep_is_held(&state->policy_mutex));
- sidtab_cancel_convert(oldpolicy->sidtab);
+ /* a first load has no outgoing policy and converted nothing */
+ if (oldpolicy)
+ sidtab_cancel_convert(oldpolicy->sidtab);
selinux_policy_free(load_state->policy);
kfree(load_state->convert_data);
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 007/235] mptcp: options: reset DSS fields in case of unexpected size
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (5 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 006/235] selinux: do not cancel a policy conversion that never started Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 008/235] s390/qeth: validate user buffer length in SNMP and ARP query ioctls Greg Kroah-Hartman
` (230 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Matthieu Baerts (NGI0),
Jakub Kicinski
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <matttbe@kernel.org>
commit 35772b4981f38ba8059372cde8753e8e477e98ec upstream.
A remote peer could send a malformed DSS with a wrong size, followed by
another DSS or MPC + Data. In this case, the first suboption will be
ignored, but leaving some fields written, which could lead to
inconsistency or access uninitialized data.
Explicitly reset the fields that could have been modified in case of
unexpected size.
Link: https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260728-net-mptcp-misc-fixes-7-2-rc6-v1-0-f7e2d229159d%40kernel.org?part=1
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Cc: stable@vger.kernel.org
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20260803-net-mptcp-misc-fixes-7-2-rc6-v2-1-b8f496d71664@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/mptcp/options.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
--- a/net/mptcp/options.c
+++ b/net/mptcp/options.c
@@ -175,8 +175,14 @@ static void mptcp_parse_option(const str
* the checksum field MUST be ignored.
*/
if (opsize != expected_opsize &&
- opsize != expected_opsize + TCPOLEN_MPTCP_DSS_CHECKSUM)
+ opsize != expected_opsize + TCPOLEN_MPTCP_DSS_CHECKSUM) {
+ mp_opt->dsn64 = 0;
+ mp_opt->use_map = 0;
+ mp_opt->ack64 = 0;
+ mp_opt->use_ack = 0;
+ mp_opt->data_fin = 0;
break;
+ }
mp_opt->dss = 1;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 008/235] s390/qeth: validate user buffer length in SNMP and ARP query ioctls
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (6 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 007/235] mptcp: options: reset DSS fields in case of unexpected size Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 009/235] ASoC: cs4265: sort the register default table Greg Kroah-Hartman
` (229 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Alexandra Winter, Hidayath Khan,
Joe Damato, Jakub Kicinski
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hidayath Khan <hidayath@linux.ibm.com>
commit d141f087b1af656f055d7c5793a3e87817ba0bbe upstream.
qeth_snmp_command() and qeth_l3_arp_query() allocate a buffer sized by
a user-supplied length (udata_len) without checking a lower bound, then
set udata_offset to a fixed non-zero value and pass both to a reply
callback. The callback bounds-checks the copy with
if ((udata_len - udata_offset) < len)
Both fields are u32, so a udata_len smaller than udata_offset makes the
subtraction wrap and the check pass, and the following memcpy() writes
past the allocation. A udata_len of 0 also yields ZERO_SIZE_PTR from
kzalloc(), which the existing NULL check does not catch.
Reject buffers smaller than udata_offset before allocating, so the
callback subtraction can no longer underflow.
Fixes: 4a71df50047f ("qeth: new qeth device driver")
Cc: stable@vger.kernel.org
Reviewed-by: Alexandra Winter <wintera@linux.ibm.com>
Signed-off-by: Hidayath Khan <hidayath@linux.ibm.com>
Reviewed-by: Joe Damato <joe@dama.to>
Link: https://patch.msgid.link/20260730142216.218309-1-hidayath@linux.ibm.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/s390/net/qeth_core_main.c | 3 +++
drivers/s390/net/qeth_l3_main.c | 5 +++++
2 files changed, 8 insertions(+)
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -4748,6 +4748,9 @@ static int qeth_snmp_command(struct qeth
if (req_len > QETH_BUFSIZE)
return -EINVAL;
+ if (qinfo.udata_len < sizeof(struct qeth_snmp_ureq_hdr))
+ return -EINVAL;
+
iob = qeth_get_adapter_cmd(card, IPA_SETADP_SET_SNMP_CONTROL, req_len);
if (!iob)
return -ENOMEM;
--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -1435,6 +1435,11 @@ static int qeth_l3_arp_query(struct qeth
rc = -EFAULT;
goto out;
}
+
+ if (qinfo.udata_len < QETH_QARP_ENTRIES_OFFSET) {
+ rc = -EINVAL;
+ goto out;
+ }
qinfo.udata = kzalloc(qinfo.udata_len, GFP_KERNEL);
if (!qinfo.udata) {
rc = -ENOMEM;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 009/235] ASoC: cs4265: sort the register default table
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (7 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 008/235] s390/qeth: validate user buffer length in SNMP and ARP query ioctls Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 010/235] powerpc/pseries: pci - logic bug Greg Kroah-Hartman
` (228 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Peter Ujfalusi, Charles Keepax,
Richard Fitzgerald, Mark Brown
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
commit e4fe3e046524e5de3c04c6eef3743780cbdc231c upstream.
reg_defaults must be sorted by ascending register address, as
regcache_lookup_reg() locates entries in it with bsearch(). See commit
fd80df352ba1 ("regcache: Add support for sorting defaults arrays").
cs4265_reg_defaults[] lists CS4265_INT_MASK (0x0e),
CS4265_STATUS_MODE_MSB (0x0f) and CS4265_STATUS_MODE_LSB (0x10) after
CS4265_SPDIF_CTL1 (0x11) and CS4265_SPDIF_CTL2 (0x12), so the binary search
does not find those three entries. regcache_reg_needs_sync() then cannot
compare them against their default and reports that a sync is needed, so
they are written to the device on every regcache_sync() even when they were
never touched.
Sort the table by register address.
Fixes: fb6f806967f6 ("ASoC: Add support for the CS4265 CODEC")
Cc: stable@vger.kernel.org
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Charles Keepax <ckeepax@opensource.cirrus.com>
Reviewed-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Link: https://patch.msgid.link/20260805082413.26174-4-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
sound/soc/codecs/cs4265.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/sound/soc/codecs/cs4265.c
+++ b/sound/soc/codecs/cs4265.c
@@ -46,11 +46,11 @@ static const struct reg_default cs4265_r
{ CS4265_DAC_CHA_VOL, 0x00 },
{ CS4265_DAC_CHB_VOL, 0x00 },
{ CS4265_DAC_CTL2, 0xC0 },
- { CS4265_SPDIF_CTL1, 0x00 },
- { CS4265_SPDIF_CTL2, 0x00 },
{ CS4265_INT_MASK, 0x00 },
{ CS4265_STATUS_MODE_MSB, 0x00 },
{ CS4265_STATUS_MODE_LSB, 0x00 },
+ { CS4265_SPDIF_CTL1, 0x00 },
+ { CS4265_SPDIF_CTL2, 0x00 },
};
static bool cs4265_readable_register(struct device *dev, unsigned int reg)
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 010/235] powerpc/pseries: pci - logic bug
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (8 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 009/235] ASoC: cs4265: sort the register default table Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 011/235] Input: synaptics-rmi4 - fix F55 transmitter electrode count typo Greg Kroah-Hartman
` (227 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Nayna Jain, R Nageswara Sastry,
George Wilson, Madhavan Srinivasan
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: George Wilson <gcwilson@linux.ibm.com>
commit 649c10bff5cb7a514bf299094833ec8c9190aac3 upstream.
The checks on num_vfs in pseries_pci_sriov_enable() are ANDed where OR
was apparently intended. Change it to OR.
Fixes: 9a7f6b438664 ("powerpc/pseries/pci: Associate PEs to VFs in configure SR-IOV")
Acked-by: Nayna Jain <nayna@linux.ibm.com>
Tested-by: R Nageswara Sastry <rnsastry@linux.ibm.com>
Cc: stable@vger.kernel.org # 4.16
Signed-off-by: George Wilson <gcwilson@linux.ibm.com>
Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/powerpc/platforms/pseries/pci.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/powerpc/platforms/pseries/pci.c
+++ b/arch/powerpc/platforms/pseries/pci.c
@@ -161,7 +161,7 @@ int pseries_pci_sriov_enable(struct pci_
/* First integer stores max config */
max_config_vfs = of_read_number(&max_vfs[0], 1);
- if (max_config_vfs < num_vfs && num_vfs > MAX_VFS_FOR_MAP_PE) {
+ if (max_config_vfs < num_vfs || num_vfs > MAX_VFS_FOR_MAP_PE) {
dev_err(&pdev->dev,
"Num VFs %x > %x Configurable VFs\n",
num_vfs, (num_vfs > MAX_VFS_FOR_MAP_PE) ?
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 011/235] Input: synaptics-rmi4 - fix F55 transmitter electrode count typo
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (9 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 010/235] powerpc/pseries: pci - logic bug Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 012/235] Input: focaltech - fix array out-of-bounds in focaltech_process_rel_packet Greg Kroah-Hartman
` (226 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, sashiko-bot, Dmitry Torokhov
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
commit 6058f0fea10f3caf63a435677358d1b8e9325114 upstream.
During F55 sensor detection, the transmitter (TX) electrode count was
incorrectly assigned the value of the receiver (RX) electrode count
due to copy-paste typos.
This incorrect value was then propagated to the driver data and used
by F54 to determine the diagnostics report size. On devices with more
RX than TX electrodes, this inflated the perceived TX count, leading
to incorrect report size calculations and potential out-of-bounds
buffer accesses.
Fix the typos by correctly assigning the TX electrode counts.
Fixes: 6adba43fd222 ("Input: synaptics-rmi4 - add support for F55 sensor tuning")
Fixes: c762cc68b6a1 ("Input: synaptics-rmi4 - propagate correct number of rx and tx electrodes to F54")
Reported-by: sashiko-bot@kernel.org
Cc: stable@vger.kernel.org
Assisted-by: Antigravity:gemini-3.5-flash
Link: https://patch.msgid.link/20260626051802.4033172-1-dmitry.torokhov@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/input/rmi4/rmi_f55.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/input/rmi4/rmi_f55.c
+++ b/drivers/input/rmi4/rmi_f55.c
@@ -54,10 +54,10 @@ static int rmi_f55_detect(struct rmi_fun
f55->num_tx_electrodes = f55->qry[F55_NUM_TX_OFFSET];
f55->cfg_num_rx_electrodes = f55->num_rx_electrodes;
- f55->cfg_num_tx_electrodes = f55->num_rx_electrodes;
+ f55->cfg_num_tx_electrodes = f55->num_tx_electrodes;
drv_data->num_rx_electrodes = f55->cfg_num_rx_electrodes;
- drv_data->num_tx_electrodes = f55->cfg_num_rx_electrodes;
+ drv_data->num_tx_electrodes = f55->cfg_num_tx_electrodes;
if (f55->qry[F55_PHYS_CHAR_OFFSET] & F55_CAP_SENSOR_ASSIGN) {
int i, total;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 012/235] Input: focaltech - fix array out-of-bounds in focaltech_process_rel_packet
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (10 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 011/235] Input: synaptics-rmi4 - fix F55 transmitter electrode count typo Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 013/235] Input: psxpad-spi - set driver data before use Greg Kroah-Hartman
` (225 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Richard Davies, Dmitry Torokhov
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Richard Davies <richard@arachsys.com>
commit 296736076b3fd078742651c719555a488624023a upstream.
Make finger2 (and also finger1) unsigned, so that if the finger index in
the packet is 0 then subtracting 1 creates an array index which overflows
above the existing check for FOC_MAX_FINGERS, as the existing comment says
it should, instead of writing to state->fingers[-1].
Fixes: 05be1d079ec0 ("Input: psmouse - support for the FocalTech PS/2 protocol extensions")
Signed-off-by: Richard Davies <richard@arachsys.com>
Link: https://patch.msgid.link/20260701190932.14960-1-richard@arachsys.com
Cc: stable@vger.kernel.org
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/input/mouse/focaltech.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/input/mouse/focaltech.c
+++ b/drivers/input/mouse/focaltech.c
@@ -197,7 +197,7 @@ static void focaltech_process_rel_packet
{
struct focaltech_data *priv = psmouse->private;
struct focaltech_hw_state *state = &priv->state;
- int finger1, finger2;
+ unsigned int finger1, finger2;
state->pressed = packet[0] >> 7;
finger1 = ((packet[0] >> 4) & 0x7) - 1;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 013/235] Input: psxpad-spi - set driver data before use
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (11 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 012/235] Input: focaltech - fix array out-of-bounds in focaltech_process_rel_packet Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 014/235] Input: atkbd - skip deactivate for Xiaomi Book Pro 14s internal keyboard Greg Kroah-Hartman
` (224 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Linmao Li, Dmitry Torokhov
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linmao Li <lilinmao@kylinos.cn>
commit 732f38c36059e68ba3b4b89c56911d777fd3185c upstream.
psxpad_spi_suspend() retrieves the controller state with
spi_get_drvdata(), but probe never stores it, so suspend dereferences a
NULL pointer. Store it during probe.
Fixes: 8be193c7b1f4 ("Input: add support for PlayStation 1/2 joypads connected via SPI")
Signed-off-by: Linmao Li <lilinmao@kylinos.cn>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260721055551.1714965-1-lilinmao@kylinos.cn
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/input/joystick/psxpad-spi.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/input/joystick/psxpad-spi.c
+++ b/drivers/input/joystick/psxpad-spi.c
@@ -366,6 +366,7 @@ static int psxpad_spi_probe(struct spi_d
return err;
}
+ spi_set_drvdata(spi, pad);
pm_runtime_enable(&spi->dev);
return 0;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 014/235] Input: atkbd - skip deactivate for Xiaomi Book Pro 14s internal keyboard
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (12 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 013/235] Input: psxpad-spi - set driver data before use Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 015/235] Input: iforce - validate input packet lengths Greg Kroah-Hartman
` (223 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Zhefu Zhang, Andrew Zhou,
Dmitry Torokhov
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhefu Zhang <a723356@gmail.com>
commit 3a046db33bb9f28b43a951a7a090db771dc0f8b3 upstream.
The internal keyboard of the Xiaomi Book Pro 14 does not work unless
atkbd skips deactivating it at the end of atkbd_probe().
Using 'i8042.dumbkbd=1' also makes the keyboard work, but then the driver
never writes to the keyboard at all, so the Caps Lock LED is lost. The
atkbd_deactivate_fixup quirk fixes both without a boot parameter.
DMI: XIAOMI Xiaomi Book Pro 14/TM2424, BIOS XMAPT4B0P0909 05/06/2026
Signed-off-by: Zhefu Zhang <a723356@gmail.com>
Reviewed-by: Andrew Zhou <zhoulol888@gmail.com>
Link: https://patch.msgid.link/20260802031559.19701-1-a723356@gmail.com
Cc: stable@vger.kernel.org
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/input/keyboard/atkbd.c | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -1954,6 +1954,14 @@ static const struct dmi_system_id atkbd_
},
.callback = atkbd_deactivate_fixup,
},
+ {
+ /* Xiaomi Book Pro 14 (TM2424) */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "XIAOMI"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Xiaomi Book Pro 14"),
+ },
+ .callback = atkbd_deactivate_fixup,
+ },
{ }
};
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 015/235] Input: iforce - validate input packet lengths
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (13 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 014/235] Input: atkbd - skip deactivate for Xiaomi Book Pro 14s internal keyboard Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 016/235] powerpc/pseries: lparcfg - fix kbuf[] underflow Greg Kroah-Hartman
` (222 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Pengpeng Hou, Dmitry Torokhov
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <pengpeng@iscas.ac.cn>
commit 5751c781d3c97ab6ce0e2a966156ed882152c415 upstream.
iforce_process_packet() reads fixed fields from joystick, wheel and
status packets without first checking their lengths. In particular, the
shared hats-and-buttons helper unconditionally reads data[6]. The status
tail is a sequence of 16-bit effect addresses, but an incomplete final
address is also consumed. A successful zero-length USB URB additionally
reads the packet ID before the common parser is called.
Reject the zero-length USB transfer, require the seven-byte joystick and
wheel prefixes and the two-byte status prefix, and consume only complete
status-tail addresses.
Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Link: https://patch.msgid.link/20260720115018.75045-1-pengpeng@iscas.ac.cn
Cc: stable@vger.kernel.org
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/input/joystick/iforce/iforce-packets.c | 11 ++++++++++-
drivers/input/joystick/iforce/iforce-usb.c | 3 +++
2 files changed, 13 insertions(+), 1 deletion(-)
--- a/drivers/input/joystick/iforce/iforce-packets.c
+++ b/drivers/input/joystick/iforce/iforce-packets.c
@@ -161,6 +161,9 @@ void iforce_process_packet(struct iforce
switch (packet_id) {
case 0x01: /* joystick position data */
+ if (len < 7)
+ break;
+
input_report_abs(dev, ABS_X,
(__s16) get_unaligned_le16(data));
input_report_abs(dev, ABS_Y,
@@ -176,6 +179,9 @@ void iforce_process_packet(struct iforce
break;
case 0x03: /* wheel position data */
+ if (len < 7)
+ break;
+
input_report_abs(dev, ABS_WHEEL,
(__s16) get_unaligned_le16(data));
input_report_abs(dev, ABS_GAS, 255 - data[2]);
@@ -187,6 +193,9 @@ void iforce_process_packet(struct iforce
break;
case 0x02: /* status report */
+ if (len < 2)
+ break;
+
input_report_key(dev, BTN_DEAD, data[0] & 0x02);
input_sync(dev);
@@ -206,7 +215,7 @@ void iforce_process_packet(struct iforce
}
}
- for (j = 3; j < len; j += 2)
+ for (j = 3; j + sizeof(u16) <= len; j += sizeof(u16))
mark_core_as_ready(iforce, get_unaligned_le16(data + j));
break;
--- a/drivers/input/joystick/iforce/iforce-usb.c
+++ b/drivers/input/joystick/iforce/iforce-usb.c
@@ -159,6 +159,9 @@ static void iforce_usb_irq(struct urb *u
goto exit;
}
+ if (!urb->actual_length)
+ goto exit;
+
iforce_process_packet(iforce, iforce_usb->data_in[0],
iforce_usb->data_in + 1, urb->actual_length - 1);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 016/235] powerpc/pseries: lparcfg - fix kbuf[] underflow
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (14 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 015/235] Input: iforce - validate input packet lengths Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 017/235] Input: synaptics-rmi4 - zero report size on F54 work error Greg Kroah-Hartman
` (221 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Nayna Jain, R Nageswara Sastry,
George Wilson, Madhavan Srinivasan
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: George Wilson <gcwilson@linux.ibm.com>
commit fb442a6673ff1046bf67754957d95880fdb394b5 upstream.
In lparcfg_write(), a count of 0 results in kbuf[] being indexed at -1.
Check for count == 0 in the existing check for count > sizeof(kbuf) and
return -EINVAL if true.
Fixes: 74422e2b1939 ("powerpc/pseries: Remove VLA from lparcfg_write()")
Acked-by: Nayna Jain <nayna@linux.ibm.com>
Tested-by: R Nageswara Sastry <rnsastry@linux.ibm.com>
Cc: stable@vger.kernel.org # 4.20
Signed-off-by: George Wilson <gcwilson@linux.ibm.com>
Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/powerpc/platforms/pseries/lparcfg.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/powerpc/platforms/pseries/lparcfg.c
+++ b/arch/powerpc/platforms/pseries/lparcfg.c
@@ -639,7 +639,7 @@ static ssize_t lparcfg_write(struct file
if (!firmware_has_feature(FW_FEATURE_SPLPAR))
return -EINVAL;
- if (count > sizeof(kbuf))
+ if (count == 0 || count > sizeof(kbuf))
return -EINVAL;
if (copy_from_user(kbuf, buf, count))
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 017/235] Input: synaptics-rmi4 - zero report size on F54 work error
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (15 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 016/235] powerpc/pseries: lparcfg - fix kbuf[] underflow Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 018/235] Input: synaptics-rmi4 - bound the F54 report size to the allocated buffer Greg Kroah-Hartman
` (220 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, sashiko-bot, Dmitry Torokhov
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
commit dc76c3c8e8ad09362b8c1561f3928288c15cba2e upstream.
In rmi_f54_work(), if an error occurs during report request or command
verification, the code jumped directly to the 'error' label, bypassing
the 'abort' label where f54->report_size was normally zeroed out.
This left f54->report_size containing its previous successful payload
size. If a user then altered the V4L2 format to a smaller size, and a
subsequent run failed, rmi_f54_buffer_queue() would copy the stale,
larger payload size into the shrunken V4L2 buffer, causing a heap
buffer overflow.
Fix this by merging the 'abort' and 'error' labels into a single 'out'
exit path, and ensuring that f54->report_size is always set to 0 on
failure by checking for error and zeroing the local report_size first.
Fixes: 3a762dbd5347 ("[media] Input: synaptics-rmi4 - add support for F54 diagnostics")
Cc: stable@vger.kernel.org
Reported-by: sashiko-bot@kernel.org
Assisted-by: Antigravity:gemini-3.5-flash
Link: https://patch.msgid.link/20260626051802.4033172-2-dmitry.torokhov@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/input/rmi4/rmi_f54.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
--- a/drivers/input/rmi4/rmi_f54.c
+++ b/drivers/input/rmi4/rmi_f54.c
@@ -541,7 +541,7 @@ static void rmi_f54_work(struct work_str
dev_err(&fn->dev, "Bad report size, report type=%d\n",
f54->report_type);
error = -EINVAL;
- goto error; /* retry won't help */
+ goto out; /* retry won't help */
}
/*
@@ -552,7 +552,7 @@ static void rmi_f54_work(struct work_str
&command);
if (error) {
dev_err(&fn->dev, "Failed to read back command\n");
- goto error;
+ goto out;
}
if (command & F54_GET_REPORT) {
if (time_after(jiffies, f54->timeout)) {
@@ -560,7 +560,7 @@ static void rmi_f54_work(struct work_str
error = -ETIMEDOUT;
}
report_size = 0;
- goto error;
+ goto out;
}
rmi_dbg(RMI_DEBUG_FN, &fn->dev, "Get report command completed, reading data\n");
@@ -575,7 +575,7 @@ static void rmi_f54_work(struct work_str
fifo, sizeof(fifo));
if (error) {
dev_err(&fn->dev, "Failed to set fifo start offset\n");
- goto abort;
+ goto out;
}
error = rmi_read_block(fn->rmi_dev, fn->fd.data_base_addr +
@@ -584,16 +584,16 @@ static void rmi_f54_work(struct work_str
if (error) {
dev_err(&fn->dev, "%s: read [%d bytes] returned %d\n",
__func__, size, error);
- goto abort;
+ goto out;
}
}
-abort:
- f54->report_size = error ? 0 : report_size;
-error:
+out:
if (error)
report_size = 0;
+ f54->report_size = report_size;
+
if (report_size == 0 && !error) {
queue_delayed_work(f54->workqueue, &f54->work,
msecs_to_jiffies(1));
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 018/235] Input: synaptics-rmi4 - bound the F54 report size to the allocated buffer
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (16 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 017/235] Input: synaptics-rmi4 - zero report size on F54 work error Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 019/235] Input: synaptics-rmi4 - block s_input when F54 queue is busy Greg Kroah-Hartman
` (219 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Bryam Vargas, Dmitry Torokhov
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <hexlabsecurity@proton.me>
commit 49c5adc2b7d6e43c5cf033e1c86fdb9c16ababb1 upstream.
rmi_f54_work() reads a diagnostics report from the device into
f54->report_data, sizing the transfer with rmi_f54_get_report_size():
report_size = rmi_f54_get_report_size(f54);
...
for (i = 0; i < report_size; i += F54_REPORT_DATA_SIZE) {
int size = min(F54_REPORT_DATA_SIZE, report_size - i);
...
rmi_read_block(.., f54->report_data + i, size);
}
report_data is allocated once at probe from F54's own electrode counts
(array3_size(f54->num_tx_electrodes, f54->num_rx_electrodes, sizeof(u16))),
but rmi_f54_get_report_size() computes the size from
drv_data->num_*_electrodes when those are set, i.e. from the F55
function's electrode counts. Both counts come straight from device
queries (F54 and F55 each report up to 255 electrodes) and nothing
constrains the F55 counts to the F54 ones.
A malicious or malfunctioning RMI4 device that reports larger F55
electrode counts than its F54 counts makes report_size exceed the
allocation, so the read loop writes past report_data (and the V4L2
dequeue memcpy() then reads past it). On conforming hardware the F55
configured electrodes are a subset of the F54 physical electrodes, so
report_size never exceeds the buffer and well-behaved devices are
unaffected.
Record the allocation size and reject a report that does not fit,
mirroring the existing zero-size check.
Fixes: c762cc68b6a1 ("Input: synaptics-rmi4 - propagate correct number of rx and tx electrodes to F54")
Cc: stable@vger.kernel.org
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
Assisted-by: Antigravity:gemini-3.5-flash
Link: https://patch.msgid.link/20260626051802.4033172-3-dmitry.torokhov@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/input/rmi4/rmi_f54.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
--- a/drivers/input/rmi4/rmi_f54.c
+++ b/drivers/input/rmi4/rmi_f54.c
@@ -98,6 +98,7 @@ struct f54_data {
enum rmi_f54_report_type report_type;
u8 *report_data;
+ size_t max_report_size;
int report_size;
bool is_busy;
@@ -544,6 +545,13 @@ static void rmi_f54_work(struct work_str
goto out; /* retry won't help */
}
+ if (report_size > f54->max_report_size) {
+ dev_err(&fn->dev, "Report size %d exceeds buffer size %zu\n",
+ report_size, f54->max_report_size);
+ error = -EINVAL;
+ goto out;
+ }
+
/*
* Need to check if command has completed.
* If not try again later.
@@ -674,8 +682,8 @@ static int rmi_f54_probe(struct rmi_func
rx = f54->num_rx_electrodes;
tx = f54->num_tx_electrodes;
- f54->report_data = devm_kzalloc(&fn->dev,
- array3_size(tx, rx, sizeof(u16)),
+ f54->max_report_size = array3_size(tx, rx, sizeof(u16));
+ f54->report_data = devm_kzalloc(&fn->dev, f54->max_report_size,
GFP_KERNEL);
if (f54->report_data == NULL)
return -ENOMEM;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 019/235] Input: synaptics-rmi4 - block s_input when F54 queue is busy
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (17 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 018/235] Input: synaptics-rmi4 - bound the F54 report size to the allocated buffer Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 020/235] Input: synaptics-rmi4 - propagate F54 worker errors to V4L2 queue Greg Kroah-Hartman
` (218 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Hans Verkuil, Dmitry Torokhov
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
commit fbfd76746adc16d64be29ff113f673b70bc3f5c2 upstream.
Changing the input (diagnostic report type) mid-stream changes the
report size. Since V4L2 buffers are allocated based on the size at
stream start, changing the input while streaming could lead to a
heap buffer overflow if the new size is larger than the allocated
buffers.
Prevent this by blocking VIDIOC_S_INPUT with -EBUSY if the V4L2 queue
is busy (streaming).
Fixes: 3a762dbd5347 ("[media] Input: synaptics-rmi4 - add support for F54 diagnostics")
Cc: stable@vger.kernel.org
Assisted-by: Antigravity:gemini-3.5-flash
Reviewed-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Link: https://patch.msgid.link/20260626051802.4033172-5-dmitry.torokhov@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/input/rmi4/rmi_f54.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
--- a/drivers/input/rmi4/rmi_f54.c
+++ b/drivers/input/rmi4/rmi_f54.c
@@ -441,7 +441,12 @@ static int rmi_f54_set_input(struct f54_
static int rmi_f54_vidioc_s_input(struct file *file, void *priv, unsigned int i)
{
- return rmi_f54_set_input(video_drvdata(file), i);
+ struct f54_data *f54 = video_drvdata(file);
+
+ if (vb2_is_busy(&f54->queue))
+ return -EBUSY;
+
+ return rmi_f54_set_input(f54, i);
}
static int rmi_f54_vidioc_g_input(struct file *file, void *priv,
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 020/235] Input: synaptics-rmi4 - propagate F54 worker errors to V4L2 queue
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (18 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 019/235] Input: synaptics-rmi4 - block s_input when F54 queue is busy Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 021/235] crypto: qce - fix error path in devm_qce_register_algs Greg Kroah-Hartman
` (217 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, sashiko-bot, Dmitry Torokhov
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
commit 8786d74bf50e6797b6f655eb381ef6b25451161f upstream.
Previously, rmi_f54_buffer_queue() waited for the worker thread to
finish but ignored whether it succeeded. If the worker failed (e.g.,
due to a timeout or register read failure), the queue thread would
silently return success, delivering stale or uninitialized memory to
userspace.
Add a 'report_error' field to struct f54_data to store the worker's exit
status. Check this field in rmi_f54_buffer_queue() after the worker
finishes, and mark the buffer as VB2_BUF_STATE_ERROR if an error
occurred.
Fixes: 3a762dbd5347 ("[media] Input: synaptics-rmi4 - add support for F54 diagnostics")
Reported-by: sashiko-bot@kernel.org
Cc: stable@vger.kernel.org
Assisted-by: Antigravity:gemini-3.5-flash
Link: https://patch.msgid.link/20260626051802.4033172-6-dmitry.torokhov@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/input/rmi4/rmi_f54.c | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/drivers/input/rmi4/rmi_f54.c
+++ b/drivers/input/rmi4/rmi_f54.c
@@ -100,6 +100,7 @@ struct f54_data {
u8 *report_data;
size_t max_report_size;
int report_size;
+ int report_error;
bool is_busy;
struct mutex status_mutex;
@@ -334,6 +335,12 @@ static void rmi_f54_buffer_queue(struct
mutex_lock(&f54->data_mutex);
}
+ if (f54->report_error) {
+ dev_err(&f54->fn->dev, "Error acquiring report: %d\n", f54->report_error);
+ state = VB2_BUF_STATE_ERROR;
+ goto data_done;
+ }
+
ptr = vb2_plane_vaddr(vb, 0);
if (!ptr) {
dev_err(&f54->fn->dev, "Error acquiring frame ptr\n");
@@ -606,6 +613,7 @@ out:
report_size = 0;
f54->report_size = report_size;
+ f54->report_error = error;
if (report_size == 0 && !error) {
queue_delayed_work(f54->workqueue, &f54->work,
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 021/235] crypto: qce - fix error path in devm_qce_register_algs
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (19 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 020/235] Input: synaptics-rmi4 - propagate F54 worker errors to V4L2 queue Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 022/235] libceph: fix multiple unsafe decodes in decode_locker() Greg Kroah-Hartman
` (216 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Thorsten Blum, Bartosz Golaszewski,
Herbert Xu
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum <thorsten.blum@linux.dev>
commit 9c75402286409f5e1a75e4a445555c84066f89db upstream.
If ops->register_algs() fails, the error path repeatedly calls the same
ops->unregister_algs() from the failed registration. Use the loop index
to unregister the previously registered algorithms instead.
Fixes: e80cf84b6087 ("crypto: qce - unregister previously registered algos in error path")
Cc: stable@vger.kernel.org
Signed-off-by: Thorsten Blum <thorsten.blum@linux.dev>
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/crypto/qce/core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/crypto/qce/core.c
+++ b/drivers/crypto/qce/core.c
@@ -52,7 +52,7 @@ static int qce_register_algs(struct qce_
ret = ops->register_algs(qce);
if (ret) {
for (j = i - 1; j >= 0; j--)
- ops->unregister_algs(qce);
+ qce_ops[j]->unregister_algs(qce);
return ret;
}
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 022/235] libceph: fix multiple unsafe decodes in decode_locker()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (20 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 021/235] crypto: qce - fix error path in devm_qce_register_algs Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 023/235] ftrace: Fix off-by-one fentry site disable in ftrace_free_mem() Greg Kroah-Hartman
` (215 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Pavitra Jha, Ilya Dryomov
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pavitra Jha <jhapavitra98@gmail.com>
commit 437b6551cfcc235eea1d735a874f9d421f555e17 upstream.
decode_locker() in cls_lock_client.c contains three unsafe decode
operations that allow a malicious or compromised OSD to trigger
slab-out-of-bounds reads:
1. ceph_decode_copy() at the locker_id_t name field has no preceding
bounds check. With p == end after ceph_start_decoding() accepts
struct_len=0, this reads sizeof(ceph_entity_name) = 9 bytes past
the validated buffer boundary.
2. *p += sizeof(struct ceph_timespec) after the locker_info_t header
is an unchecked pointer advance. A malicious OSD can position p
past end, causing all subsequent _safe checks to pass against a
bogus boundary.
3. len = ceph_decode_32(p) has no preceding bounds check, and the
immediately following *p += len is uncapped. A malicious OSD can
send len=0xffffffff, advancing p gigabytes past end and escaping
the decode window entirely.
Fix all three by replacing bare operations with their safe variants:
ceph_decode_copy -> ceph_decode_copy_safe
*p += sizeof(...) -> ceph_decode_skip_n
ceph_decode_32(p) -> ceph_decode_32_safe
*p += len -> ceph_decode_skip_n
A new label is added to return -EINVAL on any bounds violation.
-EINVAL is appropriate here: the data received from the OSD
is structurally malformed, which is an invalid argument to the decode
contract regardless of whether the caller or the wire is at fault.
Attacker model: a malicious or compromised OSD in a multi-tenant Ceph
deployment can trigger this against any kernel client that issues the
lock.get_info class method (e.g. during RBD exclusive lock acquisition)
without any further privileges beyond OSD session establishment.
[ idryomov: use ceph_decode_skip_string() to skip description, trim
changelog ]
Cc: stable@vger.kernel.org
Fixes: d4ed4a530562 ("libceph: support for lock.lock_info")
Signed-off-by: Pavitra Jha <jhapavitra98@gmail.com>
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/cls_lock_client.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
--- a/net/ceph/cls_lock_client.c
+++ b/net/ceph/cls_lock_client.c
@@ -253,7 +253,8 @@ static int decode_locker(void **p, void
if (ret)
return ret;
- ceph_decode_copy(p, &locker->id.name, sizeof(locker->id.name));
+ ceph_decode_copy_safe(p, end, &locker->id.name,
+ sizeof(locker->id.name), bad);
s = ceph_extract_encoded_string(p, end, NULL, GFP_NOIO);
if (IS_ERR(s))
return PTR_ERR(s);
@@ -264,19 +265,23 @@ static int decode_locker(void **p, void
if (ret)
return ret;
- *p += sizeof(struct ceph_timespec); /* skip expiration */
+ /* skip expiration */
+ ceph_decode_skip_n(p, end, sizeof(struct ceph_timespec), bad);
ret = ceph_decode_entity_addr(p, end, &locker->info.addr);
if (ret)
return ret;
- len = ceph_decode_32(p);
- *p += len; /* skip description */
+ /* skip description */
+ ceph_decode_skip_string(p, end, bad);
dout("%s %s%llu cookie %s addr %s\n", __func__,
ENTITY_NAME(locker->id.name), locker->id.cookie,
ceph_pr_addr(&locker->info.addr));
return 0;
+
+bad:
+ return -EINVAL;
}
static int decode_lockers(void **p, void *end, u8 *type, char **tag,
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 023/235] ftrace: Fix off-by-one fentry site disable in ftrace_free_mem()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (21 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 022/235] libceph: fix multiple unsafe decodes in decode_locker() Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 024/235] openrisc: signal: do not restore privileged SR bits on sigreturn Greg Kroah-Hartman
` (214 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Josh Poimboeuf,
Masami Hiramatsu (Google), Steven Rostedt
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Josh Poimboeuf <jpoimboe@kernel.org>
commit 8b8292d6487c81bd57c2605a9b404b1cf8f1edfb upstream.
When a module's init text is freed, do_init_module() calls
ftrace_free_mem() with a half-open [start, end) range. However the
ftrace_cmp_recs() comparator treats the upper bound as inclusive, as all
its other users do, passing 'ip + size - 1'. So ftrace_free_mem() can
delete a record sitting exactly at 'end', which is outside the freed
range.
For a kernel without CFI or IBT, the first record of a function is at
the function start, which for the first function in a module is also the
base of its text allocation. As the module allocator packs its regions,
that address is often the 'end' passed by a neighboring module's
do_init_module(), causing the first function's ftrace location to get
disabled, preventing an attempt to livepatch it:
livepatch: failed to find location for function 'pcspkr_probe'
Convert the exclusive end to the inclusive 'end - 1' the comparator
expects, and return early for an empty range to avoid the subtraction
from underflowing when the init text size is zero.
Cc: stable@vger.kernel.org
Fixes: 42c269c88dc1 ("ftrace: Allow for function tracing to record init functions on boot up")
Link: https://patch.msgid.link/1b5ccfa8095bdb1277f84af1c2c2e2205aca03ae.1785992188.git.jpoimboe@kernel.org
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
kernel/trace/ftrace.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -6844,7 +6844,8 @@ static void add_to_clear_hash_list(struc
void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr)
{
unsigned long start = (unsigned long)(start_ptr);
- unsigned long end = (unsigned long)(end_ptr);
+ /* end is inclusive and end_ptr is exclusive */
+ unsigned long end = (unsigned long)(end_ptr) - 1;
struct ftrace_page **last_pg = &ftrace_pages_start;
struct ftrace_page *tmp_page = NULL;
struct ftrace_page *pg;
@@ -6856,6 +6857,9 @@ void ftrace_free_mem(struct module *mod,
INIT_LIST_HEAD(&clear_hash);
+ if (start_ptr >= end_ptr)
+ return;
+
key.ip = start;
key.flags = end; /* overload flags, as it is unsigned long */
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 024/235] openrisc: signal: do not restore privileged SR bits on sigreturn
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (22 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 023/235] ftrace: Fix off-by-one fentry site disable in ftrace_free_mem() Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 025/235] Input: sur40 - fix input device registration ordering Greg Kroah-Hartman
` (213 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Ali Ahmet Memis, Stafford Horne
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ali Ahmet Memis <ali@iusegentoo.com>
commit 32ef1b30ad736519f7a207bcc2986f3d4129d972 upstream.
restore_sigcontext() copies the whole supervision register (SR) from the
signal frame and only clears SPR_SR_SM before the value is reloaded into
the hardware SR (through ESR and l.rfe) on the return to user space. All
other SR bits are left under user control.
An unprivileged task can thus return from a signal handler through a
crafted sigframe that clears SPR_SR_DME. With the data MMU disabled the
CPU performs no translation or protection on data accesses, so the task
gains read and write access to arbitrary physical memory, a local
privilege escalation. SPR_SR_IME, SPR_SR_SUMRA, SPR_SR_LEE, SPR_SR_EPH
and the cache-enable bits are exposed the same way. The ptrace GPR regset
already refuses any change to SR for exactly this reason.
Restore only the arithmetic flag bits (F, CY, OV) from the signal frame
and take every privileged control bit from the SR the kernel saved on
signal entry.
Verified with qemu-system-or1k -M or1k-sim: before this change an
unprivileged PoC clears SPR_SR_DME in rt_sigreturn and writes a marker to
physical address 0x03000000 (beyond the kernel's mem=32M); afterwards the
same PoC receives SIGSEGV and physical memory is unchanged.
Fixes: ac689eb7f9d4 ("OpenRISC: Signal handling")
Cc: stable@vger.kernel.org
Signed-off-by: Ali Ahmet Memis <ali@iusegentoo.com>
Signed-off-by: Stafford Horne <shorne@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/openrisc/include/asm/processor.h | 2 ++
arch/openrisc/kernel/signal.c | 5 +++--
2 files changed, 5 insertions(+), 2 deletions(-)
--- a/arch/openrisc/include/asm/processor.h
+++ b/arch/openrisc/include/asm/processor.h
@@ -26,6 +26,8 @@
| SPR_SR_DCE | SPR_SR_SM)
#define USER_SR (SPR_SR_DME | SPR_SR_IME | SPR_SR_ICE \
| SPR_SR_DCE | SPR_SR_IEE | SPR_SR_TEE)
+/* SR bits user space may change via sigreturn, the rest stay kernel owned */
+#define SPR_SR_USER_MASK (SPR_SR_F | SPR_SR_CY | SPR_SR_OV)
/*
* User space process size. This is hardcoded into a few places,
--- a/arch/openrisc/kernel/signal.c
+++ b/arch/openrisc/kernel/signal.c
@@ -39,6 +39,7 @@ struct rt_sigframe {
static int restore_sigcontext(struct pt_regs *regs,
struct sigcontext __user *sc)
{
+ unsigned long old_sr = regs->sr;
int err = 0;
/* Always make any pending restarted system calls return -EINTR */
@@ -53,8 +54,8 @@ static int restore_sigcontext(struct pt_
err |= __copy_from_user(®s->pc, &sc->regs.pc, sizeof(unsigned long));
err |= __copy_from_user(®s->sr, &sc->regs.sr, sizeof(unsigned long));
- /* make sure the SM-bit is cleared so user-mode cannot fool us */
- regs->sr &= ~SPR_SR_SM;
+ /* keep the privileged SR bits kernel owned, restore only user flags */
+ regs->sr = (old_sr & ~SPR_SR_USER_MASK) | (regs->sr & SPR_SR_USER_MASK);
regs->orig_gpr11 = -1; /* Avoid syscall restart checks */
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 025/235] Input: sur40 - fix input device registration ordering
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (23 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 024/235] openrisc: signal: do not restore privileged SR bits on sigreturn Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 026/235] Input: sur40 - fix V4L error path cleanup Greg Kroah-Hartman
` (212 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, sashiko-bot, Dmitry Torokhov
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
commit 9da976eb649c9e2f588a4499410e4d8af687925f upstream.
In sur40_probe(), input_register_device() was previously called early before
the V4L2 video device and vb2_queue components were fully initialized. If
userspace opened the input device immediately upon registration, sur40_open()
would trigger and start the sur40_poll() worker thread. This worker thread
invokes sur40_process_video() and accesses the uninitialized vb2_queue
structure, leading to a data race and potential system crash.
Furthermore, if V4L2 or video registration failed after input_register_device()
succeeded, the error path fell through to calling input_free_device() on a
successfully registered device instead of input_unregister_device(), corrupting
input core state.
Move input_register_device() to the very end of sur40_probe(). This ensures
the V4L2 and video queue structures are fully initialized before polling can
start, and naturally resolves the error path bug since input_free_device()
is now only called when input registration has not yet occurred.
To maintain strict LIFO (Last-In, First-Out) teardown ordering, also move
input_unregister_device() to the very beginning of sur40_disconnect(). This
guarantees that the input polling worker thread is stopped before V4L2
video components or control handlers are unregistered.
Reported-by: sashiko-bot@kernel.org
Cc: stable@vger.kernel.org
Assisted-by: Antigravity:gemini-3.5-flash
Link: https://patch.msgid.link/20260616051235.1549517-1-dmitry.torokhov@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/input/touchscreen/sur40.c | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
--- a/drivers/input/touchscreen/sur40.c
+++ b/drivers/input/touchscreen/sur40.c
@@ -725,21 +725,13 @@ static int sur40_probe(struct usb_interf
goto err_free_input;
}
- /* register the polled input device */
- error = input_register_device(input);
- if (error) {
- dev_err(&interface->dev,
- "Unable to register polled input device.");
- goto err_free_buffer;
- }
-
/* register the video master device */
snprintf(sur40->v4l2.name, sizeof(sur40->v4l2.name), "%s", DRIVER_LONG);
error = v4l2_device_register(sur40->dev, &sur40->v4l2);
if (error) {
dev_err(&interface->dev,
"Unable to register video master device.");
- goto err_unreg_v4l2;
+ goto err_free_buffer;
}
/* initialize the lock and subdevice */
@@ -798,6 +790,14 @@ static int sur40_probe(struct usb_interf
goto err_unreg_video;
}
+ /* register the polled input device */
+ error = input_register_device(input);
+ if (error) {
+ dev_err(&interface->dev,
+ "Unable to register polled input device.");
+ goto err_unreg_video;
+ }
+
/* we can register the device now, as it is ready */
usb_set_intfdata(interface, sur40);
dev_dbg(&interface->dev, "%s is now attached\n", DRIVER_DESC);
@@ -823,11 +823,12 @@ static void sur40_disconnect(struct usb_
{
struct sur40_state *sur40 = usb_get_intfdata(interface);
+ input_unregister_device(sur40->input);
+
v4l2_ctrl_handler_free(&sur40->hdl);
video_unregister_device(&sur40->vdev);
v4l2_device_unregister(&sur40->v4l2);
- input_unregister_device(sur40->input);
kfree(sur40->bulk_in_buffer);
kfree(sur40);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 026/235] Input: sur40 - fix V4L error path cleanup
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (24 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 025/235] Input: sur40 - fix input device registration ordering Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 027/235] libceph: Avoid using invalid osd indices from primary_temp Greg Kroah-Hartman
` (211 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, sashiko-bot, Dmitry Torokhov
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
commit 062dc4693e2c10d77de06f61e6f3faf37c0a8383 upstream.
In sur40_probe(), if video_register_device() fails, the error path jumps to
err_unreg_video. This incorrectly attempts to unregister a video device
that was never successfully registered, and fails to free the V4L2 control
handler (v4l2_ctrl_handler_free) that was initialized immediately prior.
Fix this by introducing an err_free_ctrl label to properly free the V4L2
control handler and bypass video_unregister_device() when video device
registration fails.
Reported-by: sashiko-bot@kernel.org
Cc: stable@vger.kernel.org
Assisted-by: Antigravity:gemini-3.5-flash
Link: https://patch.msgid.link/20260616051235.1549517-2-dmitry.torokhov@gmail.com
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/input/touchscreen/sur40.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/drivers/input/touchscreen/sur40.c
+++ b/drivers/input/touchscreen/sur40.c
@@ -787,7 +787,7 @@ static int sur40_probe(struct usb_interf
if (error) {
dev_err(&interface->dev,
"Unable to register video subdevice.");
- goto err_unreg_video;
+ goto err_free_ctrl;
}
/* register the polled input device */
@@ -806,6 +806,8 @@ static int sur40_probe(struct usb_interf
err_unreg_video:
video_unregister_device(&sur40->vdev);
+err_free_ctrl:
+ v4l2_ctrl_handler_free(&sur40->hdl);
err_unreg_v4l2:
v4l2_device_unregister(&sur40->v4l2);
err_free_buffer:
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 027/235] libceph: Avoid using invalid osd indices from primary_temp
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (25 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 026/235] Input: sur40 - fix V4L error path cleanup Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 028/235] ceph: fix MDS random selection readiness predicate Greg Kroah-Hartman
` (210 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Raphael Zimmer, Ilya Dryomov
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Raphael Zimmer <raphael.zimmer@tu-ilmenau.de>
commit 3660b98d1204b419f6a77e9a295f148dcf38d042 upstream.
A corrupted osdmap received from a Ceph monitor or OSD may contain osd
indices in its pg_temp, primary_temp, pg_upmap, and pg_upmap_items parts
that don't exist, i.e., that are greater than max_osd or smaller than
CEPH_HOMELESS_OSD (-1). These indices are used to create the up and
acting set in ceph_pg_to_up_acting_osds(), called from calc_target().
While most of these osd indices are checked, the one from primary_temp
is not. Subsequently, this may lead to calc_target() returning this
(potentially invalid) index as target osd for a (linger) request.
Because the osd_state, osd_weight, and osd_addr arrays only contain
max_osd entries (with indices 0 to max_osd -1), this leads to
out-of-bounds accesses when trying to read values from these arrays.
This patch fixes the issue by adding a check to get_temp_osds(), so that
only valid osd indices from primary_temp are used, and it falls back to
using the primary from pg_temp or the up set if it is invalid.
[ idryomov: changelog ]
Cc: stable@vger.kernel.org
Fixes: 5e8d4d36bf23 ("libceph: add support for primary_temp mappings")
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/osdmap.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
--- a/net/ceph/osdmap.c
+++ b/net/ceph/osdmap.c
@@ -2772,9 +2772,10 @@ static void get_temp_osds(struct ceph_os
}
}
- /* primary_temp? */
+ /* primary_temp? (shouldn't ever be a nonexistent or down OSD) */
pg = lookup_pg_mapping(&osdmap->primary_temp, pgid);
- if (pg)
+ if (pg && !WARN_ON_ONCE(ceph_osd_is_down(osdmap,
+ pg->primary_temp.osd)))
temp->primary = pg->primary_temp.osd;
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 028/235] ceph: fix MDS random selection readiness predicate
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (26 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 027/235] libceph: Avoid using invalid osd indices from primary_temp Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 029/235] mmc: omap_hsmmc: fix busy_timeout overflow in ns conversion on 32-bit Greg Kroah-Hartman
` (209 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yiming Zhu, Viacheslav Dubeyko,
Ilya Dryomov
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yiming Zhu <zhuyiming@kuaishou.com>
commit 2c11c4bfdb7bd2808b3b3ac228e1f2d9bcf25457 upstream.
CEPH_MDS_IS_READY() is parsed so that the ternary expression can
return true for an MDS entry with state 0 when it is not laggy. This
allows the random selector to choose a down/DNE rank.
Group the ternary expression under the state check so zero-state ranks
are not treated as ready.
Cc: stable@vger.kernel.org
Fixes: b38c9eb4757d ("ceph: add possible_max_rank and make the code more readable")
Link: https://tracker.ceph.com/issues/78648
Signed-off-by: Yiming Zhu <zhuyiming@kuaishou.com>
Reviewed-by: Viacheslav Dubeyko <slava@dubeyko.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/ceph/mdsmap.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/fs/ceph/mdsmap.c
+++ b/fs/ceph/mdsmap.c
@@ -14,7 +14,7 @@
#include "super.h"
#define CEPH_MDS_IS_READY(i, ignore_laggy) \
- (m->m_info[i].state > 0 && ignore_laggy ? true : !m->m_info[i].laggy)
+ (m->m_info[i].state > 0 && (ignore_laggy ? true : !m->m_info[i].laggy))
static int __mdsmap_get_random_mds(struct ceph_mdsmap *m, bool ignore_laggy)
{
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 029/235] mmc: omap_hsmmc: fix busy_timeout overflow in ns conversion on 32-bit
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (27 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 028/235] ceph: fix MDS random selection readiness predicate Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 030/235] mmc: sdhci: unmap the bounce buffer before device release Greg Kroah-Hartman
` (208 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Zhan Xusheng, Ulf Hansson
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhan Xusheng <zhanxusheng1024@gmail.com>
commit f64ea900e4bda3055ef24a2c906f8d049cf1c3bd upstream.
omap_hsmmc_prepare_data() converts the command busy timeout to nanoseconds
with:
timeout = req->cmd->busy_timeout * NSEC_PER_MSEC;
busy_timeout is an unsigned int (milliseconds) and timeout is a u64, but
NSEC_PER_MSEC is 1000000L. On 32-bit builds the multiplication is
performed in 32-bit arithmetic and wraps for busy_timeout values above
~4294 ms, before the result is assigned to the u64.
The driver does not set mmc->max_busy_timeout, so the core does not cap the
busy timeout, and commands such as erase or SANITIZE (MMC_SANITIZE_TIMEOUT_MS
is 240000 ms) can pass a busy_timeout far larger than 4294 ms. The wrapped,
much smaller ns value is then programmed via set_data_timeout(), so the data
timeout is set too short and the operation can time out prematurely.
Cast busy_timeout to u64 before the multiplication so the conversion is done
in 64-bit arithmetic.
Fixes: 8cc9a3e73de1 ("mmc: host: omap_hsmmc: use generic_cmd6_time to program timeout value for CMD6")
Cc: stable@vger.kernel.org
Signed-off-by: Zhan Xusheng <zhanxusheng@xiaomi.com>
Signed-off-by: Ulf Hansson <ulfh@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/mmc/host/omap_hsmmc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -1363,7 +1363,7 @@ omap_hsmmc_prepare_data(struct omap_hsmm
if (req->data == NULL) {
OMAP_HSMMC_WRITE(host->base, BLK, 0);
if (req->cmd->flags & MMC_RSP_BUSY) {
- timeout = req->cmd->busy_timeout * NSEC_PER_MSEC;
+ timeout = (u64)req->cmd->busy_timeout * NSEC_PER_MSEC;
/*
* Set an arbitrary 100ms data timeout for commands with
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 030/235] mmc: sdhci: unmap the bounce buffer before device release
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (28 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 029/235] mmc: omap_hsmmc: fix busy_timeout overflow in ns conversion on 32-bit Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 031/235] mmc: sdhci: make tuning_err a signed int Greg Kroah-Hartman
` (207 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Ijae Kim, Myeonghun Pak,
Linus Walleij, Ulf Hansson
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Myeonghun Pak <mhun512@gmail.com>
commit 9e9f561269dff35e6f84ed21776ec37fd6360b03 upstream.
sdhci_allocate_bounce_buffer() allocates its buffer with devm_kmalloc()
but maps it with dma_map_single(). The buffer is therefore released by
devres without the streaming DMA mapping being unmapped.
Register a managed action after dma_map_single() succeeds so the mapping
is removed before devres releases the buffer. The action is registered
only for buffers allocated and mapped by the SDHCI core, leaving buffers
provided by host drivers under their existing ownership.
Fixes: bd9b902798ab ("mmc: sdhci: Implement an SDHCI-specific bounce buffer")
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: Linus Walleij <linusw@kernel.org>
Signed-off-by: Ulf Hansson <ulfh@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/mmc/host/sdhci.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -4103,6 +4103,14 @@ void __sdhci_read_caps(struct sdhci_host
}
EXPORT_SYMBOL_GPL(__sdhci_read_caps);
+static void sdhci_unmap_bounce_buffer(void *data)
+{
+ struct sdhci_host *host = data;
+
+ dma_unmap_single(mmc_dev(host->mmc), host->bounce_addr,
+ host->bounce_buffer_size, DMA_BIDIRECTIONAL);
+}
+
static void sdhci_allocate_bounce_buffer(struct sdhci_host *host)
{
struct mmc_host *mmc = host->mmc;
@@ -4153,6 +4161,14 @@ static void sdhci_allocate_bounce_buffer
/* Again fall back to max_segs == 1 */
return;
host->bounce_buffer_size = bounce_size;
+ ret = devm_add_action_or_reset(mmc_dev(mmc),
+ sdhci_unmap_bounce_buffer, host);
+ if (ret) {
+ devm_kfree(mmc_dev(mmc), host->bounce_buffer);
+ host->bounce_buffer = NULL;
+ host->bounce_buffer_size = 0;
+ return;
+ }
/* Lie about this since we're bouncing */
mmc->max_segs = max_blocks;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 031/235] mmc: sdhci: make tuning_err a signed int
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (29 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 030/235] mmc: sdhci: unmap the bounce buffer before device release Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 032/235] mmc: atmel-mci: Fix use-after-free in atmci_remove due to race condition Greg Kroah-Hartman
` (206 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Haibo Chen, Frank Li, Ulf Hansson
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haibo Chen <haibo.chen@nxp.com>
commit ae31bcc92bb42502bb7c9029e6dc7a824cf6cd14 upstream.
Coverity report INTEGER_OVERFLOW for host->tuning_err.
The tuning_err field in struct sdhci_host is used to store an error
code for re-tuning, but it was declared as unsigned int. Several call
sites store negative error codes into it and later compare against
negative values:
- sdhci.c, sdhci-of-dwcmshc.c and sdhci-pci-gli.c assign it the
return value of __sdhci_execute_tuning()/__sdhci_execute_tuning_9750(),
both of which return a signed int (possibly a negative errno);
- sdhci-of-esdhc.c assigns host->tuning_err = -EAGAIN and later does
"ret = host->tuning_err; if (ret == -EAGAIN ...)";
- sdhci-of-dwcmshc.c prints it with the %d (signed) conversion.
Storing a negative errno in an unsigned int and reading it back as a
signed int only happens to work because of two's-complement, same-width
integer conversions. It is misleading and triggers sign-conversion
warnings. All users treat the value either as a signed error code or as
a boolean (zero / non-zero), so changing the type to a signed int is
safe and makes the intent explicit.
Fixes: 7d8bb1f46e13 ("mmc: sdhci: add tuning error codes")
Assisted-by: Cline:claude-sonnet [read_file, search_files, git]
Signed-off-by: Haibo Chen <haibo.chen@nxp.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Cc: stable@vger.kernel.org
Signed-off-by: Ulf Hansson <ulfh@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/mmc/host/sdhci.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -594,7 +594,7 @@ struct sdhci_host {
unsigned int tuning_count; /* Timer count for re-tuning */
unsigned int tuning_mode; /* Re-tuning mode supported by host */
- unsigned int tuning_err; /* Error code for re-tuning */
+ int tuning_err; /* Error code for re-tuning */
#define SDHCI_TUNING_MODE_1 0
#define SDHCI_TUNING_MODE_2 1
#define SDHCI_TUNING_MODE_3 2
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 032/235] mmc: atmel-mci: Fix use-after-free in atmci_remove due to race condition
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (30 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 031/235] mmc: sdhci: make tuning_err a signed int Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 033/235] drm/radeon: fix autosuspend cleanup during teardown Greg Kroah-Hartman
` (205 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Pei Xiao, Ulf Hansson
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pei Xiao <xiaopei01@kylinos.cn>
commit c125ee35a49a0518521b52b27631eef061b8719a upstream.
In atmci_probe, &host->bh_work is bound with atmci_work_func, and
atmci_interrupt, atmci_timeout_timer and atmci_dma_complete can all
queue this work on system_bh_wq.
If we remove the module, atmci_remove makes cleanup and the memory
allocated for host with devm_kzalloc() is released after the remove
callback returns, while the work mentioned above may still be pending
or running. The sequence of operations that may lead to a UAF bug is
as follows:
CPU0 CPU1
| atmci_interrupt
| queue_work(system_bh_wq,
| &host->bh_work)
atmci_remove |
atmci_cleanup_slot(...) |
atmci_writel(host, ATMCI_IDR, ~0UL) |
timer_delete_sync(&host->timer) |
dma_release_channel(host->dma.chan) |
free_irq(platform_get_irq(pdev, 0), host) |
| atmci_work_func
| // use host
// devm resources released after |
// remove returns, host is freed |
| // use host (use-after-free)
Fix it by canceling the work after all the sources that can schedule
it (IRQ handler, timeout timer and DMA completion callback) have been
stopped, and before proceeding with the remaining cleanup in
atmci_remove.
Fixes: 7d2be0749a59 ("atmel-mci: Driver for Atmel on-chip MMC controllers")
Assisted-by: Codex:deepseek-v4-flash
Signed-off-by: Pei Xiao <xiaopei01@kylinos.cn>
Cc: stable@vger.kernel.org
Signed-off-by: Ulf Hansson <ulfh@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/mmc/host/atmel-mci.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -2629,6 +2629,8 @@ static int atmci_remove(struct platform_
free_irq(platform_get_irq(pdev, 0), host);
+ cancel_work_sync(&host->bh_work);
+
clk_disable_unprepare(host->mck);
pm_runtime_disable(&pdev->dev);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 033/235] drm/radeon: fix autosuspend cleanup during teardown
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (31 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 032/235] mmc: atmel-mci: Fix use-after-free in atmci_remove due to race condition Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 034/235] s390/vfio_ccw: Fix out of bounds check on CCW array Greg Kroah-Hartman
` (204 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Guangshuo Li, Alex Deucher
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <lgs201920130244@gmail.com>
commit 587be7a17358ef8c0106775fcedae5a7bef50735 upstream.
radeon_driver_load_kms() calls pm_runtime_use_autosuspend() for PX
devices, but radeon_driver_unload_kms() does not call the matching
pm_runtime_dont_use_autosuspend() during teardown.
If the autosuspend delay is set to a negative value while autosuspend
is enabled, the runtime PM core increments usage_count to prevent
runtime suspend. Without calling pm_runtime_dont_use_autosuspend()
during teardown, this reference is not dropped.
The documentation for pm_runtime_use_autosuspend() also notes that it
is important to undo it with pm_runtime_dont_use_autosuspend() at
driver exit time, unless runtime PM was initially enabled with
devm_pm_runtime_enable().
Add the missing pm_runtime_dont_use_autosuspend() call to the driver
unload path.
This issue was found by manual code inspection.
Fixes: 10ebc0bc0934 ("drm/radeon: add runtime PM support (v2)")
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 0fdc1ff82ea14844c22795e9e0813c3ca03235e1)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/radeon/radeon_kms.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -71,6 +71,7 @@ void radeon_driver_unload_kms(struct drm
if (radeon_is_px(dev)) {
pm_runtime_get_sync(dev->dev);
pm_runtime_forbid(dev->dev);
+ pm_runtime_dont_use_autosuspend(dev->dev);
}
radeon_acpi_fini(rdev);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 034/235] s390/vfio_ccw: Fix out of bounds check on CCW array
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (32 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 033/235] drm/radeon: fix autosuspend cleanup during teardown Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 035/235] drm/amdgpu: Reject UVD message with invalid number of h265 refs Greg Kroah-Hartman
` (203 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Matthew Rosato, Eric Farman,
Christian Borntraeger
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Farman <farman@linux.ibm.com>
commit a005b7f1a491ffda61bff0fd0f6548f8986fb977 upstream.
The routine ccwchain_calc_length() counts the number of channel
command words (CCWs) that are chained together in a single channel
program, and rejects anything larger than CCWCHAIN_LEN_MAX (256) CCWs.
The loop itself is "do..while (count < 257)", and while the logic in
is_cpa_within_range() correctly adjusts between the 0-index array of
CCWs and the count of CCWs starting at 1, this means it would look
at a possible 257th CCW before ending the loop and (correctly)
returning an error.
Fix this by restructuring the loop to break as soon as 256 CCWs
(thus indexes 0-255) are examined, without looking at memory
outside the range.
Fixes: 0a19e61e6d4c ("vfio: ccw: introduce channel program interfaces")
Cc: stable@vger.kernel.org
Reviewed-by: Matthew Rosato <mjrosato@linux.ibm.com>
Signed-off-by: Eric Farman <farman@linux.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@linux.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/s390/cio/vfio_ccw_cp.c | 17 +++++------------
1 file changed, 5 insertions(+), 12 deletions(-)
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -371,11 +371,9 @@ static void ccwchain_cda_free(struct ccw
static int ccwchain_calc_length(u64 iova, struct channel_program *cp)
{
struct ccw1 *ccw = cp->guest_cp;
- int cnt = 0;
-
- do {
- cnt++;
+ int cnt;
+ for (cnt = 1; cnt <= CCWCHAIN_LEN_MAX; cnt++, ccw++) {
/*
* As we don't want to fail direct addressing even if the
* orb specified one of the unsupported formats, we defer
@@ -393,15 +391,10 @@ static int ccwchain_calc_length(u64 iova
* after the TIC, depending on the results of its operation.
*/
if (!ccw_is_chain(ccw) && !is_tic_within_range(ccw, iova, cnt))
- break;
-
- ccw++;
- } while (cnt < CCWCHAIN_LEN_MAX + 1);
-
- if (cnt == CCWCHAIN_LEN_MAX + 1)
- cnt = -EINVAL;
+ return cnt;
+ }
- return cnt;
+ return -EINVAL;
}
static int tic_target_chain_exists(struct ccw1 *tic, struct channel_program *cp)
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 035/235] drm/amdgpu: Reject UVD message with invalid number of h265 refs
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (33 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 034/235] s390/vfio_ccw: Fix out of bounds check on CCW array Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 036/235] drm/amdgpu: validate GEM_CREATE domain combinations Greg Kroah-Hartman
` (202 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, David Rosca, Leo Liu, Alex Deucher
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Rosca <david.rosca@amd.com>
commit 9fca434208f1f9ab977feac62df8ebb1cc7ce893 upstream.
Same change as for h264, avoids overflow later when calculating
min dpb size.
Signed-off-by: David Rosca <david.rosca@amd.com>
Reviewed-by: Leo Liu <leo.liu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit a4b0720e4f1601f97f59a2be9c1b4b94fa6527d5)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -715,6 +715,9 @@ static int amdgpu_uvd_cs_msg_decode(stru
image_size = ALIGN(image_size, 256);
num_dpb_buffer = (le32_to_cpu(msg[59]) & 0xff) + 2;
+ if (num_dpb_buffer > 17)
+ return -EINVAL;
+
min_dpb_size = image_size * num_dpb_buffer;
min_ctx_size = ((width + 255) / 16) * ((height + 255) / 16)
* 16 * num_dpb_buffer + 52 * 1024;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 036/235] drm/amdgpu: validate GEM_CREATE domain combinations
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (34 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 035/235] drm/amdgpu: Reject UVD message with invalid number of h265 refs Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 037/235] drm/amdgpu: Reject UVD message with dimensions above 4096 Greg Kroah-Hartman
` (201 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Candice Li, Christian König,
Alex Deucher
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Candice Li <candice.li@amd.com>
commit 5e9d136ad74df4edec67e502ce267597064d8f86 upstream.
AMDGPU_GEM_CREATE checked domain bits against AMDGPU_GEM_DOMAIN_MASK,
but did not validate domain combinations. Userspace could combine
CPU|GTT|VRAM with DOORBELL, GDS, GWS, or OA, making
amdgpu_bo_placement_from_domain() exceed AMDGPU_BO_MAX_PLACEMENTS and
hit BUG_ON().
Allow combinations only within CPU/GTT/VRAM, and require non-CPU/GTT/
VRAM domains to be specified one at a time. Return -EINVAL for invalid
combinations in amdgpu_gem_create_ioctl().
v2: Rename helper from amdgpu_gem_domain_valid() to
amdgpu_gem_are_domains_valid() (Christian)
Signed-off-by: Candice Li <candice.li@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit db39852d0c39843cb02048dfb47e4b8c703e9080)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -197,6 +197,25 @@ out_unlock:
ttm_eu_backoff_reservation(&ticket, &list);
}
+static bool amdgpu_gem_are_domains_valid(u32 domains)
+{
+ u32 normal = AMDGPU_GEM_DOMAIN_CPU |
+ AMDGPU_GEM_DOMAIN_GTT |
+ AMDGPU_GEM_DOMAIN_VRAM;
+ /* Treat all non CPU/GTT/VRAM domains as special domains. */
+ u32 special = AMDGPU_GEM_DOMAIN_MASK & ~normal;
+ u32 normal_mask = domains & normal;
+ u32 special_mask = domains & special;
+
+ if (!special_mask)
+ return true;
+
+ if (normal_mask)
+ return false;
+
+ return !(special_mask & (special_mask - 1));
+}
+
/*
* GEM ioctls.
*/
@@ -228,6 +247,8 @@ int amdgpu_gem_create_ioctl(struct drm_d
/* reject invalid gem domains */
if (args->in.domains & ~AMDGPU_GEM_DOMAIN_MASK)
return -EINVAL;
+ if (!amdgpu_gem_are_domains_valid(args->in.domains))
+ return -EINVAL;
if (!amdgpu_is_tmz(adev) && (flags & AMDGPU_GEM_CREATE_ENCRYPTED)) {
DRM_NOTE_ONCE("Cannot allocate secure buffer since TMZ is disabled\n");
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 037/235] drm/amdgpu: Reject UVD message with dimensions above 4096
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (35 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 036/235] drm/amdgpu: validate GEM_CREATE domain combinations Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 038/235] drm/amdgpu: Implement insert_end for VCE 3 Greg Kroah-Hartman
` (200 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Rosca, Leo Liu, Ruijing Dong,
Alex Deucher
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Rosca <david.rosca@amd.com>
commit 8c9aebcdd9f46f7a14b98d6ab18574b7a48fbb08 upstream.
Fixes potential overflow in DPB size calculations.
Signed-off-by: David Rosca <david.rosca@amd.com>
Acked-by: Leo Liu <leo.liu@amd.com>
Reviewed-by: Ruijing Dong <ruijing.dong@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 05e1387d151f71569fbe122d2c89f9db0c21dc10)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -567,8 +567,8 @@ static int amdgpu_uvd_cs_msg_decode(stru
unsigned image_size, tmp, min_dpb_size, num_dpb_buffer;
unsigned min_ctx_size = ~0;
- /* Reject invalid dimensions to prevent division by zero */
- if (width < 16 || height < 16) {
+ /* Reject invalid dimensions */
+ if (width < 16 || height < 16 || width > 4096 || height > 4096) {
dev_WARN_ONCE(adev->dev, 1,
"Invalid UVD decoding dimensions (%dx%d)!\n",
width, height);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 038/235] drm/amdgpu: Implement insert_end for VCE 3
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (36 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 037/235] drm/amdgpu: Reject UVD message with dimensions above 4096 Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 039/235] drm/amdgpu: Fix UVD decode image min size calculation Greg Kroah-Hartman
` (199 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, David Rosca, Alex Deucher
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Rosca <david.rosca@amd.com>
commit d5ab4c6a64efef2d143a96df5357f59703cd703d upstream.
After a recent change VCE now hangs when VCE_CMD_END is emitted
after a pipeline sync without VM flush.
Implement insert_end to correctly insert only one VCE_CMD_END per job.
Fixes: bc639a9eadc7 ("drm/amdgpu: always emit the job vm fence")
Signed-off-by: David Rosca <david.rosca@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit 8897ea8c761b856f02061848a7908040a1fe5e68)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 26 ++++++++++++++++++++++----
1 file changed, 22 insertions(+), 4 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
@@ -846,6 +846,23 @@ static void vce_v3_0_ring_emit_ib(struct
amdgpu_ring_write(ring, ib->length_dw);
}
+static void vce_v3_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
+ u64 seq, unsigned flags)
+{
+ WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT);
+
+ amdgpu_ring_write(ring, VCE_CMD_FENCE);
+ amdgpu_ring_write(ring, addr);
+ amdgpu_ring_write(ring, upper_32_bits(addr));
+ amdgpu_ring_write(ring, seq);
+ amdgpu_ring_write(ring, VCE_CMD_TRAP);
+}
+
+static void vce_v3_0_ring_insert_end(struct amdgpu_ring *ring)
+{
+ amdgpu_ring_write(ring, VCE_CMD_END);
+}
+
static void vce_v3_0_emit_vm_flush(struct amdgpu_ring *ring,
unsigned int vmid, uint64_t pd_addr)
{
@@ -855,7 +872,6 @@ static void vce_v3_0_emit_vm_flush(struc
amdgpu_ring_write(ring, VCE_CMD_FLUSH_TLB);
amdgpu_ring_write(ring, vmid);
- amdgpu_ring_write(ring, VCE_CMD_END);
}
static void vce_v3_0_emit_pipeline_sync(struct amdgpu_ring *ring)
@@ -925,17 +941,19 @@ static const struct amdgpu_ring_funcs vc
.set_wptr = vce_v3_0_ring_set_wptr,
.parse_cs = amdgpu_vce_ring_parse_cs_vm,
.emit_frame_size =
- 6 + /* vce_v3_0_emit_vm_flush */
+ 5 + /* vce_v3_0_emit_vm_flush */
4 + /* vce_v3_0_emit_pipeline_sync */
- 6 + 6, /* amdgpu_vce_ring_emit_fence x2 vm fence */
+ 5 + 5 + /* vce_v3_0_ring_emit_fence x2 vm fence */
+ 1, /* vce_v3_0_ring_insert_end */
.emit_ib_size = 5, /* vce_v3_0_ring_emit_ib */
.emit_ib = vce_v3_0_ring_emit_ib,
.emit_vm_flush = vce_v3_0_emit_vm_flush,
.emit_pipeline_sync = vce_v3_0_emit_pipeline_sync,
- .emit_fence = amdgpu_vce_ring_emit_fence,
+ .emit_fence = vce_v3_0_ring_emit_fence,
.test_ring = amdgpu_vce_ring_test_ring,
.test_ib = amdgpu_vce_ring_test_ib,
.insert_nop = amdgpu_ring_insert_nop,
+ .insert_end = vce_v3_0_ring_insert_end,
.pad_ib = amdgpu_ring_generic_pad_ib,
.begin_use = amdgpu_vce_ring_begin_use,
.end_use = amdgpu_vce_ring_end_use,
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 039/235] drm/amdgpu: Fix UVD decode image min size calculation
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (37 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 038/235] drm/amdgpu: Implement insert_end for VCE 3 Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 040/235] xfs: check v5 superblock features early Greg Kroah-Hartman
` (198 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Rosca, Leo Liu, Ruijing Dong,
Alex Deucher
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Rosca <david.rosca@amd.com>
commit b8bb9ba3f101a1b0011f785a577a4a0a38371174 upstream.
This needs to use pitch instead of width. Also reject pitch
over 4096 to avoid overflow.
Signed-off-by: David Rosca <david.rosca@amd.com>
Acked-by: Leo Liu <leo.liu@amd.com>
Reviewed-by: Ruijing Dong <ruijing.dong@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
(cherry picked from commit b41c8cb12e202b220353332ab87dc01a11f69304)
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -728,7 +728,7 @@ static int amdgpu_uvd_cs_msg_decode(stru
return -EINVAL;
}
- if (width > pitch) {
+ if (width > pitch || pitch > 4096) {
DRM_ERROR("Invalid UVD decoding target pitch!\n");
return -EINVAL;
}
@@ -740,7 +740,7 @@ static int amdgpu_uvd_cs_msg_decode(stru
}
buf_sizes[0x1] = dpb_size;
- buf_sizes[0x2] = image_size;
+ buf_sizes[0x2] = (pitch * height) * 3 / 2;
buf_sizes[0x4] = min_ctx_size;
/* store image width to adjust nb memory pstate */
adev->uvd.decode_image_width = width;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 040/235] xfs: check v5 superblock features early
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (38 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 039/235] drm/amdgpu: Fix UVD decode image min size calculation Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 041/235] net/smc: reject CHID-0 ACCEPT that matches an empty ism_dev slot Greg Kroah-Hartman
` (197 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Christoph Hellwig, Darrick J. Wong,
Carlos Maiolino
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christoph Hellwig <hch@lst.de>
commit eb6b2cc1fc8ad566d746d128a559989ff0bba5cc upstream.
When working on a new features that reuses the existing pad in the
superblock, I noticed that mounting such a file system on an old kernel
logs a rather confusing warning:
XFS (vdc): Metadir superblock padding fields must be zero.
This is because we only validate the various feature fields in v5
superblocks after the common superblock validation helper is called.
Fix this by calling the feature validation first.
Fixes: eca383fcd63b ("xfs: refactor superblock verifiers")
Cc: <stable@vger.kernel.org> # v4.19
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/xfs/libxfs/xfs_sb.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/fs/xfs/libxfs/xfs_sb.c
+++ b/fs/xfs/libxfs/xfs_sb.c
@@ -804,10 +804,10 @@ xfs_sb_read_verify(
* because _verify_common checks the on-disk values.
*/
__xfs_sb_from_disk(&sb, dsb, false);
- error = xfs_validate_sb_common(mp, bp, &sb);
+ error = xfs_validate_sb_read(mp, &sb);
if (error)
goto out_error;
- error = xfs_validate_sb_read(mp, &sb);
+ error = xfs_validate_sb_common(mp, bp, &sb);
out_error:
if (error == -EFSCORRUPTED || error == -EFSBADCRC)
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 041/235] net/smc: reject CHID-0 ACCEPT that matches an empty ism_dev slot
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (39 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 040/235] xfs: check v5 superblock features early Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 042/235] f2fs: fix UAF issue in f2fs_merge_page_bio() Greg Kroah-Hartman
` (196 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Weiming Shi, Xiang Mei, Paolo Abeni,
Andrey Troshin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei <xmei5@asu.edu>
commit 277740023def559a4a2ddc3e8e784ee37a0f16a9 upstream.
On the SMC-D client, slot 0 of ini->ism_dev[]/ini->ism_chid[] is
reserved for an SMC-Dv1 device. smc_find_ism_v2_device_clnt()
populates V2 entries starting at index 1, so when no V1 device is
selected slot 0 is left in its kzalloc()'ed state with ism_dev[0] ==
NULL and ism_chid[0] == 0.
smc_v2_determine_accepted_chid() then matches the peer's CHID against
the array starting from index 0 using the CHID alone. A malicious
peer replying to a SMC-Dv2-only proposal with d1.chid == 0 matches
the empty slot, ini->ism_selected becomes 0, and the subsequent
ism_dev[0]->lgr_lock dereference in smc_conn_create() faults at
offsetof(struct smcd_dev, lgr_lock) == 0x68:
BUG: KASAN: null-ptr-deref in _raw_spin_lock_bh+0x79/0xe0
Write of size 4 at addr 0000000000000068 by task exploit/144
Call Trace:
_raw_spin_lock_bh
smc_conn_create (net/smc/smc_core.c:1997)
__smc_connect (net/smc/af_smc.c:1447)
smc_connect (net/smc/af_smc.c:1720)
__sys_connect
__x64_sys_connect
do_syscall_64
Require ism_dev[i] to be non-NULL before accepting a CHID match.
Fixes: a7c9c5f4af7f ("net/smc: CLC accept / confirm V2")
Reported-by: Weiming Shi <bestswngs@gmail.com>
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Xiang Mei <xmei5@asu.edu>
Link: https://patch.msgid.link/20260511062138.2839584-1-xmei5@asu.edu
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Andrey Troshin <drtrosh@yandex-team.ru>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/smc/af_smc.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -863,7 +863,8 @@ smc_v2_determine_accepted_chid(struct sm
int i;
for (i = 0; i < ini->ism_offered_cnt + 1; i++) {
- if (ini->ism_chid[i] == ntohs(aclc->chid)) {
+ if (ini->ism_dev[i] &&
+ ini->ism_chid[i] == ntohs(aclc->chid)) {
ini->ism_selected = i;
return 0;
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 042/235] f2fs: fix UAF issue in f2fs_merge_page_bio()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (40 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 041/235] net/smc: reject CHID-0 ACCEPT that matches an empty ism_dev slot Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 043/235] bpf: Reject BPF_MAP_TYPE_INODE_STORAGE creation if BPF LSM is uninitialized Greg Kroah-Hartman
` (195 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, JY, Chao Yu, Jaegeuk Kim,
Jiucheng Xu
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chao Yu <chao@kernel.org>
commit edf7e9040fc52c922db947f9c6c36f07377c52ea upstream.
As JY reported in bugzilla [1],
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
pc : [0xffffffe51d249484] f2fs_is_cp_guaranteed+0x70/0x98
lr : [0xffffffe51d24adbc] f2fs_merge_page_bio+0x520/0x6d4
CPU: 3 UID: 0 PID: 6790 Comm: kworker/u16:3 Tainted: P B W OE 6.12.30-android16-5-maybe-dirty-4k #1 5f7701c9cbf727d1eebe77c89bbbeb3371e895e5
Tainted: [P]=PROPRIETARY_MODULE, [B]=BAD_PAGE, [W]=WARN, [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
Workqueue: writeback wb_workfn (flush-254:49)
Call trace:
f2fs_is_cp_guaranteed+0x70/0x98
f2fs_inplace_write_data+0x174/0x2f4
f2fs_do_write_data_page+0x214/0x81c
f2fs_write_single_data_page+0x28c/0x764
f2fs_write_data_pages+0x78c/0xce4
do_writepages+0xe8/0x2fc
__writeback_single_inode+0x4c/0x4b4
writeback_sb_inodes+0x314/0x540
__writeback_inodes_wb+0xa4/0xf4
wb_writeback+0x160/0x448
wb_workfn+0x2f0/0x5dc
process_scheduled_works+0x1c8/0x458
worker_thread+0x334/0x3f0
kthread+0x118/0x1ac
ret_from_fork+0x10/0x20
[1] https://bugzilla.kernel.org/show_bug.cgi?id=220575
The panic was caused by UAF issue w/ below race condition:
kworker
- writepages
- f2fs_write_cache_pages
- f2fs_write_single_data_page
- f2fs_do_write_data_page
- f2fs_inplace_write_data
- f2fs_merge_page_bio
- add_inu_page
: cache page #1 into bio & cache bio in
io->bio_list
- f2fs_write_single_data_page
- f2fs_do_write_data_page
- f2fs_inplace_write_data
- f2fs_merge_page_bio
- add_inu_page
: cache page #2 into bio which is linked
in io->bio_list
write
- f2fs_write_begin
: write page #1
- f2fs_folio_wait_writeback
- f2fs_submit_merged_ipu_write
- f2fs_submit_write_bio
: submit bio which inclues page #1 and #2
software IRQ
- f2fs_write_end_io
- fscrypt_free_bounce_page
: freed bounced page which belongs to page #2
- inc_page_count( , WB_DATA_TYPE(data_folio), false)
: data_folio points to fio->encrypted_page
the bounced page can be freed before
accessing it in f2fs_is_cp_guarantee()
It can reproduce w/ below testcase:
Run below script in shell #1:
for ((i=1;i>0;i++)) do xfs_io -f /mnt/f2fs/enc/file \
-c "pwrite 0 32k" -c "fdatasync"
Run below script in shell #2:
for ((i=1;i>0;i++)) do xfs_io -f /mnt/f2fs/enc/file \
-c "pwrite 0 32k" -c "fdatasync"
So, in f2fs_merge_page_bio(), let's avoid using fio->encrypted_page after
commit page into internal ipu cache.
Fixes: 0b20fcec8651 ("f2fs: cache global IPU bio")
Reported-by: JY <JY.Ho@mediatek.com>
Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Signed-off-by: Jiucheng Xu <jiucheng.xu@amlogic.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/f2fs/data.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -968,7 +968,7 @@ alloc_new:
if (fio->io_wbc)
wbc_account_cgroup_owner(fio->io_wbc, fio->page, PAGE_SIZE);
- inc_page_count(fio->sbi, WB_DATA_TYPE(page));
+ inc_page_count(fio->sbi, WB_DATA_TYPE(fio->page));
*fio->last_block = fio->new_blkaddr;
*fio->bio = bio;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 043/235] bpf: Reject BPF_MAP_TYPE_INODE_STORAGE creation if BPF LSM is uninitialized
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (41 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 042/235] f2fs: fix UAF issue in f2fs_merge_page_bio() Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 044/235] udmabuf: Do not create malformed scatterlists Greg Kroah-Hartman
` (194 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, oxsignal, Matt Bobrowski,
Daniel Borkmann, Emil Tsalapatis, Amery Hung, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matt Bobrowski <mattbobrowski@google.com>
[ Upstream commit a6f0643e4f63cfaa0d5d4a69de4f132eac4b8fe4 ]
When CONFIG_BPF_LSM=y is set, BPF inode storage maps
(BPF_MAP_TYPE_INODE_STORAGE) are compiled into the kernel. However,
if the BPF LSM is not explicitly enabled at boot time (e.g. omitted
from the "lsm=" boot parameter), lsm_prepare() is never executed for
the BPF LSM.
Consequently, the BPF inode security blob offset
(bpf_lsm_blob_sizes.lbs_inode) is never initialized and remains at
its default compiled size of 8 bytes instead of being updated to a
valid offset past the reserved struct rcu_head (typically 16 bytes
or more).
When a privileged user creates and updates a BPF_MAP_TYPE_INODE_STORAGE
map, bpf_inode() evaluates inode->i_security + 8. This erroneously
aliases the struct rcu_head.func callback pointer at the beginning
of the inode->i_security blob. During subsequent map element cleanup
or inode destruction, writing NULL to owner_storage clears the queued
RCU callback pointer. When rcu_do_batch() later executes the queued
callback, it attempts an instruction fetch at address 0x0, triggering
an immediate kernel panic.
Fix this by introducing a global bpf_lsm_initialized boolean flag
marked with __ro_after_init. Set this flag to true inside bpf_lsm_init()
when the LSM framework successfully registers the BPF LSM. Gate map
allocation in inode_storage_map_alloc() on this flag, returning
-EOPNOTSUPP if the BPF LSM is in turn uninitialized.
This fail-fast approach prevents userspace from allocating inode
storage maps when the supporting BPF LSM infrastructure is absent,
avoiding zombie map states.
Fixes: 8ea636848aca ("bpf: Implement bpf_local_storage for inodes")
Reported-by: oxsignal <awo@kakao.com>
Signed-off-by: Matt Bobrowski <mattbobrowski@google.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
Reviewed-by: Amery Hung <ameryhung@gmail.com>
Link: https://lore.kernel.org/bpf/20260628201103.3624525-1-mattbobrowski@google.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/bpf_lsm.h | 4 ++++
kernel/bpf/bpf_inode_storage.c | 10 ++++++++++
security/bpf/hooks.c | 3 +++
3 files changed, 17 insertions(+)
--- a/include/linux/bpf_lsm.h
+++ b/include/linux/bpf_lsm.h
@@ -12,6 +12,8 @@
#ifdef CONFIG_BPF_LSM
+extern bool bpf_lsm_initialized __ro_after_init;
+
#define LSM_HOOK(RET, DEFAULT, NAME, ...) \
RET bpf_lsm_##NAME(__VA_ARGS__);
#include <linux/lsm_hook_defs.h>
@@ -41,6 +43,8 @@ void bpf_inode_storage_free(struct inode
#else /* !CONFIG_BPF_LSM */
+#define bpf_lsm_initialized false
+
static inline int bpf_lsm_verify_prog(struct bpf_verifier_log *vlog,
const struct bpf_prog *prog)
{
--- a/kernel/bpf/bpf_inode_storage.c
+++ b/kernel/bpf/bpf_inode_storage.c
@@ -223,6 +223,16 @@ static struct bpf_map *inode_storage_map
{
struct bpf_local_storage_map *smap;
+ /*
+ * Do not allow allocation of BPF_MAP_TYPE_INODE_STORAGE if the BPF LSM
+ * was not initialized by the LSM framework at boot. Without proper
+ * initialization, the BPF inode security blob offset remains unprepared,
+ * causing bpf_inode() to calculate an invalid memory offset and corrupt
+ * inode->i_security.
+ */
+ if (!bpf_lsm_initialized)
+ return ERR_PTR(-EOPNOTSUPP);
+
smap = bpf_local_storage_map_alloc(attr);
if (IS_ERR(smap))
return ERR_CAST(smap);
--- a/security/bpf/hooks.c
+++ b/security/bpf/hooks.c
@@ -6,6 +6,8 @@
#include <linux/lsm_hooks.h>
#include <linux/bpf_lsm.h>
+bool bpf_lsm_initialized __ro_after_init;
+
static struct security_hook_list bpf_lsm_hooks[] __lsm_ro_after_init = {
#define LSM_HOOK(RET, DEFAULT, NAME, ...) \
LSM_HOOK_INIT(NAME, bpf_lsm_##NAME),
@@ -17,6 +19,7 @@ static struct security_hook_list bpf_lsm
static int __init bpf_lsm_init(void)
{
security_add_hooks(bpf_lsm_hooks, ARRAY_SIZE(bpf_lsm_hooks), "bpf");
+ bpf_lsm_initialized = true;
pr_info("LSM support for eBPF active\n");
return 0;
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 044/235] udmabuf: Do not create malformed scatterlists
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (42 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 043/235] bpf: Reject BPF_MAP_TYPE_INODE_STORAGE creation if BPF LSM is uninitialized Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 045/235] dma-buf/udmabuf: skip redundant cpu sync to fix cacheline EEXIST warning Greg Kroah-Hartman
` (193 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Julian Orth, Jason Gunthorpe,
Vivek Kasireddy, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Gunthorpe <jgg@nvidia.com>
[ Upstream commit 5bf888673e0dda5a53220fa0c4956271a46c353c ]
Using a sg_set_folio() loop for every 4K results in a malformed scatterlist
because sg_set_folio() has an issue with offsets > PAGE_SIZE and because
scatterlist expects the creator to build a list which consolidates any
physical contiguity.
sg_alloc_table_from_pages() creates a valid scatterlist directly from a
struct page array, so go back to that.
Remove the offsets allocation and just store an array of tail pages as it
did before the below commit. Everything wants that anyhow.
Fixes: 0c8b91ef5100 ("udmabuf: add back support for mapping hugetlb pages")
Reported-by: Julian Orth <ju.orth@gmail.com>
Closes: https://lore.kernel.org/all/20260308-scatterlist-v1-1-39c4566b0bba@gmail.com/
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
Link: https://patch.msgid.link/0-v1-42779f29381a+4b9-udmabuf_sg_jgg@nvidia.com
Stable-dep-of: 504e2b4ab97a ("dma-buf/udmabuf: skip redundant cpu sync to fix cacheline EEXIST warning")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/dma-buf/udmabuf.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
--- a/drivers/dma-buf/udmabuf.c
+++ b/drivers/dma-buf/udmabuf.c
@@ -66,14 +66,16 @@ static struct sg_table *get_sg_table(str
0, ubuf->pagecount << PAGE_SHIFT,
GFP_KERNEL);
if (ret < 0)
- goto err;
+ goto err_alloc;
+
ret = dma_map_sgtable(dev, sg, direction, 0);
if (ret < 0)
- goto err;
+ goto err_map;
return sg;
-err:
+err_map:
sg_free_table(sg);
+err_alloc:
kfree(sg);
return ERR_PTR(ret);
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 045/235] dma-buf/udmabuf: skip redundant cpu sync to fix cacheline EEXIST warning
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (43 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 044/235] udmabuf: Do not create malformed scatterlists Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 046/235] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region() Greg Kroah-Hartman
` (192 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Mikhail Gavrilov, Vivek Kasireddy,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com>
[ Upstream commit 504e2b4ab97a51d56d966cd36d0997ad30b65b2d ]
When CONFIG_DMA_API_DEBUG_SG is enabled, importing a udmabuf into a DRM
driver (e.g. amdgpu for video playback in GNOME Videos / Showtime)
triggers a spurious warning:
DMA-API: amdgpu 0000:03:00.0: cacheline tracking EEXIST, \
overlapping mappings aren't supported
WARNING: kernel/dma/debug.c:619 at add_dma_entry+0x473/0x5f0
The call chain is:
amdgpu_cs_ioctl
-> amdgpu_ttm_backend_bind
-> dma_buf_map_attachment
-> [udmabuf] map_udmabuf -> get_sg_table
-> dma_map_sgtable(dev, sg, direction, 0) // attrs=0
-> debug_dma_map_sg -> add_dma_entry -> EEXIST
This happens because udmabuf builds a per-page scatter-gather list via
sg_set_folio(). When begin_cpu_udmabuf() has already created an sg
table mapped for the misc device, and an importer such as amdgpu maps
the same pages for its own device via map_udmabuf(), the DMA debug
infrastructure sees two active mappings whose physical addresses share
cacheline boundaries and warns about the overlap.
The DMA_ATTR_SKIP_CPU_SYNC flag suppresses this check in
add_dma_entry() because it signals that no CPU cache maintenance is
performed at map/unmap time, making the cacheline overlap harmless.
All other major dma-buf exporters already pass this flag:
- drm_gem_map_dma_buf() passes DMA_ATTR_SKIP_CPU_SYNC
- amdgpu_dma_buf_map() passes DMA_ATTR_SKIP_CPU_SYNC
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.
Pass DMA_ATTR_SKIP_CPU_SYNC to dma_map_sgtable() and
dma_unmap_sgtable() in udmabuf to suppress the spurious warning and
skip the redundant sync.
Fixes: 284562e1f348 ("udmabuf: implement begin_cpu_access/end_cpu_access hooks")
Cc: stable@vger.kernel.org
Signed-off-by: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com>
Acked-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
Link: https://patch.msgid.link/20260331061657.79983-1-mikhail.v.gavrilov@gmail.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/dma-buf/udmabuf.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/dma-buf/udmabuf.c
+++ b/drivers/dma-buf/udmabuf.c
@@ -68,7 +68,7 @@ static struct sg_table *get_sg_table(str
if (ret < 0)
goto err_alloc;
- ret = dma_map_sgtable(dev, sg, direction, 0);
+ ret = dma_map_sgtable(dev, sg, direction, DMA_ATTR_SKIP_CPU_SYNC);
if (ret < 0)
goto err_map;
return sg;
@@ -83,7 +83,7 @@ err_alloc:
static void put_sg_table(struct device *dev, struct sg_table *sg,
enum dma_data_direction direction)
{
- dma_unmap_sgtable(dev, sg, direction, 0);
+ dma_unmap_sgtable(dev, sg, direction, DMA_ATTR_SKIP_CPU_SYNC);
sg_free_table(sg);
kfree(sg);
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 046/235] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (44 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 045/235] dma-buf/udmabuf: skip redundant cpu sync to fix cacheline EEXIST warning Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 047/235] i2c: davinci: Unregister cpufreq notifier on probe failure Greg Kroah-Hartman
` (191 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sebastian Alba Vives, Xu Yilun,
Xu Yilun, Sasha Levin
5.10-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
@@ -707,6 +707,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] 239+ messages in thread
* [PATCH 5.10 047/235] i2c: davinci: Unregister cpufreq notifier on probe failure
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (45 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 046/235] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region() Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 048/235] device property: Add fwnode_irq_get_byname Greg Kroah-Hartman
` (190 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Haoxiang Li, Bartosz Golaszewski,
Andi Shyti, Sasha Levin
5.10-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
@@ -877,13 +877,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] 239+ messages in thread
* [PATCH 5.10 048/235] device property: Add fwnode_irq_get_byname
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (46 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 047/235] i2c: davinci: Unregister cpufreq notifier on probe failure Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 049/235] i2c: smbus: Use device_*() functions instead of of_*() Greg Kroah-Hartman
` (189 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Akhil R, Andy Shevchenko,
Rafael J. Wysocki, Wolfram Sang, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Akhil R <akhilrajeev@nvidia.com>
[ Upstream commit ca0acb511c21738b32386ce0f85c284b351d919e ]
Add fwnode_irq_get_byname() to get an interrupt by name from either
ACPI table or Device Tree, whichever is used for enumeration.
In the ACPI case, this allow us to use 'interrupt-names' in
_DSD which can be mapped to Interrupt() resource by index.
The implementation is similar to 'interrupt-names' in the
Device Tree.
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Wolfram Sang <wsa@kernel.org>
Stable-dep-of: 158efa411c57 ("i2c: core: fix adapter probe deferral loop")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/base/property.c | 29 +++++++++++++++++++++++++++++
include/linux/property.h | 1 +
2 files changed, 30 insertions(+)
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -1043,6 +1043,35 @@ int fwnode_irq_get(const struct fwnode_h
EXPORT_SYMBOL(fwnode_irq_get);
/**
+ * fwnode_irq_get_byname - Get IRQ from a fwnode using its name
+ * @fwnode: Pointer to the firmware node
+ * @name: IRQ name
+ *
+ * Description:
+ * Find a match to the string @name in the 'interrupt-names' string array
+ * in _DSD for ACPI, or of_node for Device Tree. Then get the Linux IRQ
+ * number of the IRQ resource corresponding to the index of the matched
+ * string.
+ *
+ * Return:
+ * Linux IRQ number on success, or negative errno otherwise.
+ */
+int fwnode_irq_get_byname(const struct fwnode_handle *fwnode, const char *name)
+{
+ int index;
+
+ if (!name)
+ return -EINVAL;
+
+ index = fwnode_property_match_string(fwnode, "interrupt-names", name);
+ if (index < 0)
+ return index;
+
+ return fwnode_irq_get(fwnode, index);
+}
+EXPORT_SYMBOL(fwnode_irq_get_byname);
+
+/**
* fwnode_graph_get_next_endpoint - Get next endpoint firmware node
* @fwnode: Pointer to the parent firmware node
* @prev: Previous endpoint node or %NULL to get the first
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -120,6 +120,7 @@ struct fwnode_handle *fwnode_handle_get(
void fwnode_handle_put(struct fwnode_handle *fwnode);
int fwnode_irq_get(const struct fwnode_handle *fwnode, unsigned int index);
+int fwnode_irq_get_byname(const struct fwnode_handle *fwnode, const char *name);
unsigned int device_get_child_node_count(struct device *dev);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 049/235] i2c: smbus: Use device_*() functions instead of of_*()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (47 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 048/235] device property: Add fwnode_irq_get_byname Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 050/235] RDMA/rtrs-srv: Bound RDMA-Write length to chunk size in rdma_write_sg Greg Kroah-Hartman
` (188 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Akhil R, Andy Shevchenko,
Wolfram Sang, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Akhil R <akhilrajeev@nvidia.com>
[ Upstream commit a263a84088f689bf0c1552a510b25d0bcc45fcae ]
Change of_*() functions to device_*() for firmware agnostic usage.
This allows to have the smbus_alert interrupt without any changes
in the controller drivers using the ACPI table.
Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Wolfram Sang <wsa@kernel.org>
Stable-dep-of: 158efa411c57 ("i2c: core: fix adapter probe deferral loop")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/i2c/i2c-core-base.c | 2 +-
drivers/i2c/i2c-core-smbus.c | 11 ++++++-----
drivers/i2c/i2c-smbus.c | 5 +++--
include/linux/i2c-smbus.h | 6 +++---
4 files changed, 13 insertions(+), 11 deletions(-)
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -1478,7 +1478,7 @@ static int i2c_register_adapter(struct i
goto err_put_adap;
}
- res = of_i2c_setup_smbus_alert(adap);
+ res = i2c_setup_smbus_alert(adap);
if (res)
goto out_reg;
--- a/drivers/i2c/i2c-core-smbus.c
+++ b/drivers/i2c/i2c-core-smbus.c
@@ -14,6 +14,7 @@
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/i2c-smbus.h>
+#include <linux/property.h>
#include <linux/slab.h>
#include "i2c-core.h"
@@ -699,13 +700,13 @@ struct i2c_client *i2c_new_smbus_alert_d
}
EXPORT_SYMBOL_GPL(i2c_new_smbus_alert_device);
-#if IS_ENABLED(CONFIG_I2C_SMBUS) && IS_ENABLED(CONFIG_OF)
-int of_i2c_setup_smbus_alert(struct i2c_adapter *adapter)
+#if IS_ENABLED(CONFIG_I2C_SMBUS)
+int i2c_setup_smbus_alert(struct i2c_adapter *adapter)
{
int irq;
- irq = of_property_match_string(adapter->dev.of_node, "interrupt-names",
- "smbus_alert");
+ irq = device_property_match_string(adapter->dev.parent, "interrupt-names",
+ "smbus_alert");
if (irq == -EINVAL || irq == -ENODATA)
return 0;
else if (irq < 0)
@@ -713,5 +714,5 @@ int of_i2c_setup_smbus_alert(struct i2c_
return PTR_ERR_OR_ZERO(i2c_new_smbus_alert_device(adapter, NULL));
}
-EXPORT_SYMBOL_GPL(of_i2c_setup_smbus_alert);
+EXPORT_SYMBOL_GPL(i2c_setup_smbus_alert);
#endif
--- a/drivers/i2c/i2c-smbus.c
+++ b/drivers/i2c/i2c-smbus.c
@@ -13,7 +13,7 @@
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/of_irq.h>
+#include <linux/property.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
@@ -178,7 +178,8 @@ static int smbalert_probe(struct i2c_cli
if (setup) {
irq = setup->irq;
} else {
- irq = of_irq_get_byname(adapter->dev.of_node, "smbus_alert");
+ irq = fwnode_irq_get_byname(dev_fwnode(adapter->dev.parent),
+ "smbus_alert");
if (irq <= 0)
return irq;
}
--- a/include/linux/i2c-smbus.h
+++ b/include/linux/i2c-smbus.h
@@ -30,10 +30,10 @@ struct i2c_client *i2c_new_smbus_alert_d
struct i2c_smbus_alert_setup *setup);
int i2c_handle_smbus_alert(struct i2c_client *ara);
-#if IS_ENABLED(CONFIG_I2C_SMBUS) && IS_ENABLED(CONFIG_OF)
-int of_i2c_setup_smbus_alert(struct i2c_adapter *adap);
+#if IS_ENABLED(CONFIG_I2C_SMBUS)
+int i2c_setup_smbus_alert(struct i2c_adapter *adap);
#else
-static inline int of_i2c_setup_smbus_alert(struct i2c_adapter *adap)
+static inline int i2c_setup_smbus_alert(struct i2c_adapter *adap)
{
return 0;
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 050/235] RDMA/rtrs-srv: Bound RDMA-Write length to chunk size in rdma_write_sg
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (48 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 049/235] i2c: smbus: Use device_*() functions instead of of_*() Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 051/235] Input: mms114 - reject an oversized device packet size Greg Kroah-Hartman
` (187 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yuhao Jiang, Zhenhao Wan,
Md Haris Iqbal, Jason Gunthorpe, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhenhao Wan <whi4ed0g@gmail.com>
[ Upstream commit 963af8d97a8c6a117134a8d0db1415e0489200b1 ]
When the server answers an RTRS READ, rdma_write_sg() builds the source
scatter/gather entry for the IB_WR_RDMA_WRITE that returns data to the
peer. Its length is taken directly from the wire descriptor:
plist->length = le32_to_cpu(id->rd_msg->desc[0].len);
rd_msg points into the chunk buffer that the remote peer filled via
RDMA-WRITE-WITH-IMM (rtrs_srv_rdma_done() -> process_io_req() ->
process_read()), so desc[0].len is attacker-controlled and, before this
change, was only rejected when zero. The source address is the fixed
chunk start (dma_addr[msg_id]) and the source lkey is the PD-wide
local_dma_lkey, which is not tied to the chunk's MR mapping, so the verbs
layer does not constrain the transfer length to max_chunk_size. msg_id
and off are bounded against queue_depth and max_chunk_size in
rtrs_srv_rdma_done(), but desc[0].len is a separate field that was not
checked against the chunk size.
A peer that advertises desc[0].len larger than max_chunk_size can make
the posted RDMA write read past the chunk's mapped region. The resulting
behaviour depends on the IOMMU configuration: with no IOMMU or in
passthrough mode the read may extend into memory adjacent to the chunk
and be returned to the peer, which can disclose host memory; with a
translating IOMMU the out-of-range access is expected to fault and abort
the connection. In either case the transfer exceeds what the protocol
permits and is driven by a remote peer.
Reject a descriptor length above max_chunk_size, mirroring the existing
off >= max_chunk_size bound in rtrs_srv_rdma_done(). Legitimate clients
do not exceed it: the client sets desc[0].len to its MR length, which is
capped at the negotiated max_io_size (max_chunk_size - MAX_HDR_SIZE).
Fixes: 9cb837480424 ("RDMA/rtrs: server: main functionality")
Link: https://patch.msgid.link/r/20260612-master-v1-1-70cde5c6fdc9@gmail.com
Reported-by: Yuhao Jiang <danisjiang@gmail.com>
Cc: stable@vger.kernel.org
Signed-off-by: Zhenhao Wan <whi4ed0g@gmail.com>
Reviewed-by: Md Haris Iqbal <haris.iqbal@ionos.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/infiniband/ulp/rtrs/rtrs-srv.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
--- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c
+++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c
@@ -258,8 +258,9 @@ static int rdma_write_sg(struct rtrs_srv
/* WR will fail with length error
* if this is 0
*/
- if (unlikely(plist->length == 0)) {
- rtrs_err(s, "Invalid RDMA-Write sg list length 0\n");
+ if (unlikely(plist->length == 0 || plist->length > max_chunk_size)) {
+ rtrs_err(s, "Invalid RDMA-Write sg list length %u\n",
+ plist->length);
return -EINVAL;
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 051/235] Input: mms114 - reject an oversized device packet size
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (49 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 050/235] RDMA/rtrs-srv: Bound RDMA-Write length to chunk size in rdma_write_sg Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 052/235] VFS/audit: introduce kern_path_parent() for audit Greg Kroah-Hartman
` (186 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Bryam Vargas, Dmitry Torokhov,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <hexlabsecurity@proton.me>
[ Upstream commit 66725039f7090afe14c31bd259e2059a68f04023 ]
mms114_interrupt() reads a packet of touch data from the device into a
fixed-size on-stack buffer
struct mms114_touch touch[MMS114_MAX_TOUCH];
which holds MMS114_MAX_TOUCH (10) events of MMS114_EVENT_SIZE (8) bytes,
i.e. 80 bytes. The length of the I2C read into it is taken verbatim from
the device:
packet_size = mms114_read_reg(data, MMS114_PACKET_SIZE);
if (packet_size <= 0)
goto out;
...
error = __mms114_read_reg(data, MMS114_INFORMATION, packet_size,
(u8 *)touch);
packet_size is a single device register byte (0x0F) and the only check
is the lower bound packet_size <= 0; it is never bounded against the
size of touch[]. A malfunctioning, malicious or counterfeit controller
(or an attacker tampering with the I2C bus) can report a packet_size of
up to 255, so __mms114_read_reg() writes up to 175 bytes past the end of
touch[] on the IRQ-thread stack: a stack out-of-bounds write that can
overwrite the stack canary, saved registers and the return address.
A well-formed device never reports more than the buffer holds, so reject
an oversized packet and drop the report, consistent with the handler's
other error paths, rather than reading past the buffer.
Fixes: 07b8481d4aff ("Input: add MELFAS mms114 touchscreen driver")
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260612-b4-disp-dc4b8dc4-v1-1-d7cb0a828d92@proton.me
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/input/touchscreen/mms114.c | 6 ++++++
1 file changed, 6 insertions(+)
--- a/drivers/input/touchscreen/mms114.c
+++ b/drivers/input/touchscreen/mms114.c
@@ -209,6 +209,12 @@ static irqreturn_t mms114_interrupt(int
if (packet_size <= 0)
goto out;
+ if (packet_size > sizeof(touch)) {
+ dev_err(&data->client->dev, "Invalid packet size %d (max %zu)\n",
+ packet_size, sizeof(touch));
+ goto out;
+ }
+
touch_size = packet_size / MMS114_PACKET_NUM;
error = __mms114_read_reg(data, MMS114_INFORMATION, packet_size,
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 052/235] VFS/audit: introduce kern_path_parent() for audit
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (50 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 051/235] Input: mms114 - reject an oversized device packet size Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 053/235] audit: widen ino fields to u64 Greg Kroah-Hartman
` (185 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, NeilBrown, Christian Brauner,
Sasha Levin
5.10-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 | 42 ++++++++++++++++++++++++++++++++++++++++++
include/linux/namei.h | 1 +
kernel/audit.h | 4 ++--
kernel/audit_fsnotify.c | 11 ++++-------
kernel/audit_watch.c | 9 ++++++---
5 files changed, 55 insertions(+), 12 deletions(-)
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2439,6 +2439,48 @@ static struct filename *filename_parenta
return name;
}
+/**
+ * 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;
+ struct path parent_path;
+ struct dentry *d;
+ struct qstr last;
+ int type;
+
+ filename = filename_parentat(AT_FDCWD, getname_kernel(name), 0,
+ &parent_path, &last, &type);
+ if (IS_ERR(filename))
+ return ERR_CAST(filename);
+ 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;
+}
+
/* does lookup, returns the object with parent locked */
struct dentry *kern_path_locked(const char *name, struct path *path)
{
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -61,6 +61,7 @@ static inline int user_path_at(int dfd,
}
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
@@ -271,8 +271,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 (void *)dentry; /* returning an error */
- inode = path.dentry->d_inode;
- inode_unlock(inode);
+ return ERR_CAST(dentry); /* returning an error */
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
@@ -243,7 +243,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;
@@ -346,15 +346,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] 239+ messages in thread
* [PATCH 5.10 053/235] audit: widen ino fields to u64
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (51 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 052/235] VFS/audit: introduce kern_path_parent() for audit Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 054/235] audit: use unsigned int instead of unsigned Greg Kroah-Hartman
` (184 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jeff Layton, Paul Moore,
Christian Brauner, Sasha Levin
5.10-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
@@ -14,7 +14,7 @@
#include <uapi/linux/audit.h>
#include <uapi/linux/netfilter/nf_tables.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
@@ -71,7 +71,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;
@@ -209,9 +209,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. */
@@ -263,8 +263,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) &&
@@ -284,7 +284,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
@@ -438,7 +438,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);
@@ -526,7 +526,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
@@ -837,7 +837,7 @@ static enum audit_state audit_filter_sys
static int audit_filter_inode_name(struct task_struct *tsk,
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];
struct audit_entry *e;
enum audit_state state;
@@ -1431,7 +1431,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] 239+ messages in thread
* [PATCH 5.10 054/235] audit: use unsigned int instead of unsigned
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (52 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 053/235] audit: widen ino fields to u64 Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 055/235] audit: fix recursive locking deadlock in audit_dupe_exe() Greg Kroah-Hartman
` (183 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Ricardo Robaina, Paul Moore,
Sasha Levin
5.10-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 | 16 ++++++++--------
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 ++++++------
7 files changed, 22 insertions(+), 22 deletions(-)
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -120,17 +120,17 @@ enum audit_nfcfgop {
extern int is_audit_feature_set(int which);
-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);
/* 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[];
-extern int audit_classify_compat_syscall(int abi, unsigned syscall);
+extern int audit_classify_compat_syscall(int abi, unsigned int syscall);
/* audit_names->type values */
#define AUDIT_TYPE_UNKNOWN 0 /* we don't know yet */
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1989,7 +1989,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
@@ -217,7 +217,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 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[];
};
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -162,13 +162,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;
@@ -183,7 +183,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;
@@ -234,7 +234,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
@@ -161,7 +161,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;
n = ctx->major;
--- a/lib/compat_audit.c
+++ b/lib/compat_audit.c
@@ -3,32 +3,32 @@
#include <linux/types.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] 239+ messages in thread
* [PATCH 5.10 055/235] audit: fix recursive locking deadlock in audit_dupe_exe()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (53 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 054/235] audit: use unsigned int instead of unsigned Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 056/235] ALSA: hda: Fix cached processing coefficient verbs Greg Kroah-Hartman
` (182 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, stable, Waiman Long,
Richard Guy Briggs, Nathan Chancellor, Ricardo Robaina,
Paul Moore, Sasha Levin
5.10-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
@@ -242,8 +242,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);
@@ -266,13 +271,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);
@@ -303,13 +310,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)
#define audit_remove_mark_rule(k)
#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
@@ -243,7 +243,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;
@@ -279,7 +280,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");
@@ -478,10 +479,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);
@@ -504,7 +512,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;
@@ -513,7 +522,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
@@ -582,7 +582,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);
@@ -809,7 +809,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;
@@ -868,7 +869,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) {
@@ -1400,7 +1401,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] 239+ messages in thread
* [PATCH 5.10 056/235] ALSA: hda: Fix cached processing coefficient verbs
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (54 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 055/235] audit: fix recursive locking deadlock in audit_dupe_exe() Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 057/235] serial: max310x: replace bare use of unsigned with unsigned int (checkpatch) Greg Kroah-Hartman
` (181 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Xu Rao, Takashi Iwai, Sasha Levin
5.10-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
@@ -215,7 +215,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);
}
@@ -233,7 +233,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] 239+ messages in thread
* [PATCH 5.10 057/235] serial: max310x: replace bare use of unsigned with unsigned int (checkpatch)
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (55 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 056/235] ALSA: hda: Fix cached processing coefficient verbs Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 058/235] serial: max310x: implement gpio_chip::get_direction() Greg Kroah-Hartman
` (180 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Andy Shevchenko, Hugo Villeneuve,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
[ Upstream commit 79b69eb09cf5b6a77e621b2838b7e0d38113debb ]
Fixes the following checkpatch warnings:
WARNING: Prefer 'unsigned int' to bare use of 'unsigned'
With this change, the affected functions now match the prototypes in
struct gpio_chip.
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Link: https://lore.kernel.org/r/20240118152213.2644269-16-hugo@hugovil.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Stable-dep-of: a483b1a91b33 ("serial: max310x: implement gpio_chip::get_direction()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/tty/serial/max310x.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -1215,7 +1215,7 @@ static int __maybe_unused max310x_resume
static SIMPLE_DEV_PM_OPS(max310x_pm_ops, max310x_suspend, max310x_resume);
#ifdef CONFIG_GPIOLIB
-static int max310x_gpio_get(struct gpio_chip *chip, unsigned offset)
+static int max310x_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
unsigned int val;
struct max310x_port *s = gpiochip_get_data(chip);
@@ -1226,7 +1226,7 @@ static int max310x_gpio_get(struct gpio_
return !!((val >> 4) & (1 << (offset % 4)));
}
-static void max310x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+static void max310x_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
{
struct max310x_port *s = gpiochip_get_data(chip);
struct uart_port *port = &s->p[offset / 4].port;
@@ -1235,7 +1235,7 @@ static void max310x_gpio_set(struct gpio
value ? 1 << (offset % 4) : 0);
}
-static int max310x_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+static int max310x_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
{
struct max310x_port *s = gpiochip_get_data(chip);
struct uart_port *port = &s->p[offset / 4].port;
@@ -1246,7 +1246,7 @@ static int max310x_gpio_direction_input(
}
static int max310x_gpio_direction_output(struct gpio_chip *chip,
- unsigned offset, int value)
+ unsigned int offset, int value)
{
struct max310x_port *s = gpiochip_get_data(chip);
struct uart_port *port = &s->p[offset / 4].port;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 058/235] serial: max310x: implement gpio_chip::get_direction()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (56 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 057/235] serial: max310x: replace bare use of unsigned with unsigned int (checkpatch) Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 059/235] rxrpc: serialize kernel accept preallocation with socket teardown Greg Kroah-Hartman
` (179 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, stable, Tapio Reijonen,
Linus Walleij, Bartosz Golaszewski, Hugo Villeneuve, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tapio Reijonen <tapio.reijonen@vaisala.com>
[ Upstream commit a483b1a91b33b7533280e7c3efd2bc1275caef18 ]
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.
The MAX310X keeps the GPIO direction in the GPIOCFG register (a set bit
selects output), which the existing direction_input/output callbacks
already program, so the current direction can be read back directly.
Fixes: f65444187a66 ("serial: New serial driver MAX310X")
Cc: stable <stable@kernel.org>
Signed-off-by: Tapio Reijonen <tapio.reijonen@vaisala.com>
Reviewed-by: Linus Walleij <linusw@kernel.org>
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Reviewed-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Link: https://patch.msgid.link/20260615-b4-serial-max310x-gpio-get-direction-v2-1-4704ba2b181a@vaisala.com
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/tty/serial/max310x.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -1235,6 +1235,17 @@ static void max310x_gpio_set(struct gpio
value ? 1 << (offset % 4) : 0);
}
+static int max310x_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
+{
+ struct max310x_port *s = gpiochip_get_data(chip);
+ struct uart_port *port = &s->p[offset / 4].port;
+ unsigned int val;
+
+ val = max310x_port_read(port, MAX310X_GPIOCFG_REG);
+
+ return val & BIT(offset % 4) ? GPIO_LINE_DIRECTION_OUT : GPIO_LINE_DIRECTION_IN;
+}
+
static int max310x_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
{
struct max310x_port *s = gpiochip_get_data(chip);
@@ -1441,6 +1452,7 @@ static int max310x_probe(struct device *
s->gpio.owner = THIS_MODULE;
s->gpio.parent = dev;
s->gpio.label = devtype->name;
+ s->gpio.get_direction = max310x_gpio_get_direction;
s->gpio.direction_input = max310x_gpio_direction_input;
s->gpio.get = max310x_gpio_get;
s->gpio.direction_output= max310x_gpio_direction_output;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 059/235] rxrpc: serialize kernel accept preallocation with socket teardown
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (57 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 058/235] serial: max310x: implement gpio_chip::get_direction() Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 060/235] tipc: restrict socket queue dumps in enqueue tracepoints Greg Kroah-Hartman
` (178 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 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
5.10-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>
[ kept 6.1's extra user_attach_call argument in the rxrpc_service_prealloc_one() call ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/rxrpc/call_accept.c | 27 ++++++++++++++++++++-------
1 file changed, 20 insertions(+), 7 deletions(-)
--- a/net/rxrpc/call_accept.c
+++ b/net/rxrpc/call_accept.c
@@ -481,14 +481,27 @@ 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_attach_call, 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_attach_call, user_call_ID,
+ gfp, debug_id);
+
+out:
+ release_sock(sk);
+ return ret;
}
EXPORT_SYMBOL(rxrpc_kernel_charge_accept);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 060/235] tipc: restrict socket queue dumps in enqueue tracepoints
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (58 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 059/235] rxrpc: serialize kernel accept preallocation with socket teardown Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 061/235] rxrpc: Fix recv-recv race of completed call Greg Kroah-Hartman
` (177 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Li Xiasong, Tung Nguyen,
Jakub Kicinski, Sasha Levin
5.10-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
@@ -2455,17 +2455,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] 239+ messages in thread
* [PATCH 5.10 061/235] rxrpc: Fix recv-recv race of completed call
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (59 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 060/235] tipc: restrict socket queue dumps in enqueue tracepoints Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 062/235] rxrpc: Fix notification vs call-release vs recvmsg Greg Kroah-Hartman
` (176 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Junvyyang, Tencent Zhuque Lab,
David Howells, Jeffrey Altman, LePremierHomme, Marc Dionne,
Simon Horman, linux-afs, Jakub Kicinski, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <dhowells@redhat.com>
[ Upstream commit 962fb1f651c2cf2083e0c3ef53ba69e3b96d3fbc ]
If a call receives an event (such as incoming data), the call gets placed
on the socket's queue and a thread in recvmsg can be awakened to go and
process it. Once the thread has picked up the call off of the queue,
further events will cause it to be requeued, and once the socket lock is
dropped (recvmsg uses call->user_mutex to allow the socket to be used in
parallel), a second thread can come in and its recvmsg can pop the call off
the socket queue again.
In such a case, the first thread will be receiving stuff from the call and
the second thread will be blocked on call->user_mutex. The first thread
can, at this point, process both the event that it picked call for and the
event that the second thread picked the call for and may see the call
terminate - in which case the call will be "released", decoupling the call
from the user call ID assigned to it (RXRPC_USER_CALL_ID in the control
message).
The first thread will return okay, but then the second thread will wake up
holding the user_mutex and, if it sees that the call has been released by
the first thread, it will BUG thusly:
kernel BUG at net/rxrpc/recvmsg.c:474!
Fix this by just dequeuing the call and ignoring it if it is seen to be
already released. We can't tell userspace about it anyway as the user call
ID has become stale.
Fixes: 248f219cb8bc ("rxrpc: Rewrite the data and ack handling code")
Reported-by: Junvyyang, Tencent Zhuque Lab <zhuque@tencent.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Jeffrey Altman <jaltman@auristor.com>
cc: LePremierHomme <kwqcheii@proton.me>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: Simon Horman <horms@kernel.org>
cc: linux-afs@lists.infradead.org
Link: https://patch.msgid.link/20250717074350.3767366-3-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/call_accept.c | 1 +
net/rxrpc/recvmsg.c | 19 +++++++++++++++++--
3 files changed, 20 insertions(+), 2 deletions(-)
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -134,6 +134,7 @@ enum rxrpc_recvmsg_trace {
rxrpc_recvmsg_return,
rxrpc_recvmsg_terminal,
rxrpc_recvmsg_to_be_accepted,
+ rxrpc_recvmsg_unqueue,
rxrpc_recvmsg_wait,
};
@@ -333,6 +334,7 @@ enum rxrpc_tx_point {
EM(rxrpc_recvmsg_return, "RETN") \
EM(rxrpc_recvmsg_terminal, "TERM") \
EM(rxrpc_recvmsg_to_be_accepted, "TBAC") \
+ EM(rxrpc_recvmsg_unqueue, "UNQU") \
E_(rxrpc_recvmsg_wait, "WAIT")
#define rxrpc_rtt_tx_traces \
--- a/net/rxrpc/call_accept.c
+++ b/net/rxrpc/call_accept.c
@@ -220,6 +220,7 @@ void rxrpc_discard_prealloc(struct rxrpc
tail = b->call_backlog_tail;
while (CIRC_CNT(head, tail, size) > 0) {
struct rxrpc_call *call = b->call_backlog[tail];
+ rxrpc_see_call(call);
rcu_assign_pointer(call->socket, rx);
if (rx->discard_new_call) {
_debug("discard %lx", call->user_call_ID);
--- a/net/rxrpc/recvmsg.c
+++ b/net/rxrpc/recvmsg.c
@@ -546,6 +546,16 @@ try_again:
write_lock_bh(&rx->recvmsg_lock);
l = rx->recvmsg_q.next;
call = list_entry(l, struct rxrpc_call, recvmsg_link);
+
+ rxrpc_see_call(call);
+ if (test_bit(RXRPC_CALL_RELEASED, &call->flags)) {
+ list_del_init(&call->recvmsg_link);
+ write_unlock_bh(&rx->recvmsg_lock);
+ release_sock(&rx->sk);
+ trace_rxrpc_recvmsg(call, rxrpc_recvmsg_unqueue, 0, 0, 0, 0);
+ rxrpc_put_call(call, rxrpc_call_put);
+ goto try_again;
+ }
if (!(flags & MSG_PEEK))
list_del_init(&call->recvmsg_link);
else
@@ -568,8 +578,13 @@ try_again:
release_sock(&rx->sk);
- if (test_bit(RXRPC_CALL_RELEASED, &call->flags))
- BUG();
+ if (test_bit(RXRPC_CALL_RELEASED, &call->flags)) {
+ rxrpc_see_call(call);
+ mutex_unlock(&call->user_mutex);
+ if (!(flags & MSG_PEEK))
+ rxrpc_put_call(call, rxrpc_call_put);
+ goto try_again;
+ }
if (test_bit(RXRPC_CALL_HAS_USERID, &call->flags)) {
if (flags & MSG_CMSG_COMPAT) {
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 062/235] rxrpc: Fix notification vs call-release vs recvmsg
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (60 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 061/235] rxrpc: Fix recv-recv race of completed call Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 063/235] rxrpc: Fix socket notification race Greg Kroah-Hartman
` (175 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 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
5.10-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>
---
net/rxrpc/call_object.c | 27 +++++++++++----------------
net/rxrpc/recvmsg.c | 4 ++++
2 files changed, 15 insertions(+), 16 deletions(-)
--- a/net/rxrpc/call_object.c
+++ b/net/rxrpc/call_object.c
@@ -529,7 +529,6 @@ void rxrpc_release_call(struct rxrpc_soc
{
const void *here = __builtin_return_address(0);
struct rxrpc_connection *conn = call->conn;
- bool put = false;
_enter("{%d,%d}", call->debug_id, refcount_read(&call->ref));
@@ -547,23 +546,13 @@ void rxrpc_release_call(struct rxrpc_soc
rxrpc_put_call_slot(call);
rxrpc_delete_call_timer(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.
+ */
write_lock_bh(&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;
-
write_unlock_bh(&rx->recvmsg_lock);
- if (put)
- rxrpc_put_call(call, rxrpc_call_put);
write_lock(&rx->call_lock);
@@ -612,6 +601,12 @@ void rxrpc_release_calls_on_socket(struc
rxrpc_put_call(call, rxrpc_call_put);
}
+ 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);
+ }
+
_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);
+ return;
+ }
rcu_read_lock();
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 063/235] rxrpc: Fix socket notification race
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (61 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 062/235] rxrpc: Fix notification vs call-release vs recvmsg Greg Kroah-Hartman
@ 2026-08-20 14:54 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 064/235] mlxsw: spectrum: Apply RIF configuration when joining a LAG Greg Kroah-Hartman
` (174 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:54 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
5.10-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);
return;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 064/235] mlxsw: spectrum: Apply RIF configuration when joining a LAG
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (62 preceding siblings ...)
2026-08-20 14:54 ` [PATCH 5.10 063/235] rxrpc: Fix socket notification race Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 065/235] mlxsw: spectrum: On port enslavement to a LAG, join uppers bridges Greg Kroah-Hartman
` (173 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Ido Schimmel, Jiri Pirko,
David S. Miller, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ido Schimmel <idosch@nvidia.com>
[ Upstream commit 31e1de4f1242f338eaa62cc53d582116c83b9dd0 ]
In case a router interface (RIF) is configured for a LAG, make sure its
configuration is applied on the new LAG member.
Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Stable-dep-of: 41c8c1d65b32 ("mlxsw: fix refcount leak in mlxsw_sp_port_lag_join()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 17 ++++++++-
drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 4 ++
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 31 +++++++++++++++---
3 files changed, 45 insertions(+), 7 deletions(-)
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -3550,7 +3550,8 @@ static int mlxsw_sp_port_lag_index_get(s
}
static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port,
- struct net_device *lag_dev)
+ struct net_device *lag_dev,
+ struct netlink_ext_ack *extack)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
struct mlxsw_sp_upper *lag;
@@ -3586,8 +3587,20 @@ static int mlxsw_sp_port_lag_join(struct
if (mlxsw_sp_port->default_vlan->fid)
mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port->default_vlan);
+ /* Join a router interface configured on the LAG, if exists */
+ err = mlxsw_sp_port_vlan_router_join(mlxsw_sp_port->default_vlan,
+ lag_dev, extack);
+ if (err)
+ goto err_router_join;
+
return 0;
+err_router_join:
+ lag->ref_count--;
+ mlxsw_sp_port->lagged = 0;
+ mlxsw_core_lag_mapping_clear(mlxsw_sp->core, lag_id,
+ mlxsw_sp_port->local_port);
+ mlxsw_sp_lag_col_port_remove(mlxsw_sp_port, lag_id);
err_col_port_add:
if (!lag->ref_count)
mlxsw_sp_lag_destroy(mlxsw_sp, lag_id);
@@ -3920,7 +3933,7 @@ static int mlxsw_sp_netdevice_port_upper
} else if (netif_is_lag_master(upper_dev)) {
if (info->linking) {
err = mlxsw_sp_port_lag_join(mlxsw_sp_port,
- upper_dev);
+ upper_dev, extack);
} else {
mlxsw_sp_port_lag_col_dist_disable(mlxsw_sp_port);
mlxsw_sp_port_lag_leave(mlxsw_sp_port,
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -665,6 +665,10 @@ mlxsw_sp_netdevice_ipip_ul_event(struct
struct net_device *l3_dev,
unsigned long event,
struct netdev_notifier_info *info);
+int
+mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
+ struct net_device *l3_dev,
+ struct netlink_ext_ack *extack);
void
mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan);
void mlxsw_sp_rif_destroy_by_dev(struct mlxsw_sp *mlxsw_sp,
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -6676,9 +6676,9 @@ static void mlxsw_sp_rif_subport_put(str
}
static int
-mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
- struct net_device *l3_dev,
- struct netlink_ext_ack *extack)
+__mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
+ struct net_device *l3_dev,
+ struct netlink_ext_ack *extack)
{
struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
@@ -6743,6 +6743,27 @@ __mlxsw_sp_port_vlan_router_leave(struct
mlxsw_sp_rif_subport_put(rif);
}
+int
+mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
+ struct net_device *l3_dev,
+ struct netlink_ext_ack *extack)
+{
+ struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port_vlan->mlxsw_sp_port->mlxsw_sp;
+ struct mlxsw_sp_rif *rif;
+ int err = 0;
+
+ mutex_lock(&mlxsw_sp->router->lock);
+ rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
+ if (!rif)
+ goto out;
+
+ err = __mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan, l3_dev,
+ extack);
+out:
+ mutex_unlock(&mlxsw_sp->router->lock);
+ return err;
+}
+
void
mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
{
@@ -6767,8 +6788,8 @@ static int mlxsw_sp_inetaddr_port_vlan_e
switch (event) {
case NETDEV_UP:
- return mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan,
- l3_dev, extack);
+ return __mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan,
+ l3_dev, extack);
case NETDEV_DOWN:
__mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan);
break;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 065/235] mlxsw: spectrum: On port enslavement to a LAG, join uppers bridges
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (63 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 064/235] mlxsw: spectrum: Apply RIF configuration when joining a LAG Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 066/235] mlxsw: fix refcount leak in mlxsw_sp_port_lag_join() Greg Kroah-Hartman
` (172 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Petr Machata, Danielle Ratson,
David S. Miller, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Petr Machata <petrm@nvidia.com>
[ Upstream commit 987c7782f0627e1c87617458806a7e6c1995678a ]
Currently it never happens that a netdevice that is already a bridge slave
would suddenly become mlxsw upper. The only case where this might be
possible as far as mlxsw is concerned, is with LAG netdevices. But if a LAG
already has an upper, enslaving mlxsw port to that LAG is forbidden. Thus
the only way to install a LAG between a bridge and a mlxsw port is by first
enslaving the port to the LAG, and then enslaving that LAG to a bridge.
However in the following patches, the requirement that ports be only
enslaved to masters without uppers, is going to be relaxed. It will
therefore be necessary to join bridges of LAG uppers. Without this replay,
the mlxsw bridge_port objects are not instantiated, which causes issues
later, as a lot of code relies on their presence.
Therefore in this patch, when the first mlxsw physical netdevice is
enslaved to a LAG, consider bridges upper to the LAG (both the direct
master, if any, and any bridge masters of VLAN uppers), and have the
relevant netdevices join their bridges.
Signed-off-by: Petr Machata <petrm@nvidia.com>
Reviewed-by: Danielle Ratson <danieller@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Stable-dep-of: 41c8c1d65b32 ("mlxsw: fix refcount leak in mlxsw_sp_port_lag_join()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 90 +++++++++++++++++++++++++
1 file changed, 90 insertions(+)
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -3549,6 +3549,88 @@ static int mlxsw_sp_port_lag_index_get(s
return -EBUSY;
}
+static int mlxsw_sp_lag_uppers_bridge_join(struct mlxsw_sp_port *mlxsw_sp_port,
+ struct net_device *lag_dev,
+ struct netlink_ext_ack *extack)
+{
+ struct net_device *upper_dev;
+ struct net_device *master;
+ struct list_head *iter;
+ int done = 0;
+ int err;
+
+ master = netdev_master_upper_dev_get(lag_dev);
+ if (master && netif_is_bridge_master(master)) {
+ err = mlxsw_sp_port_bridge_join(mlxsw_sp_port, lag_dev, master,
+ extack);
+ if (err)
+ return err;
+ }
+
+ netdev_for_each_upper_dev_rcu(lag_dev, upper_dev, iter) {
+ if (!is_vlan_dev(upper_dev))
+ continue;
+
+ master = netdev_master_upper_dev_get(upper_dev);
+ if (master && netif_is_bridge_master(master)) {
+ err = mlxsw_sp_port_bridge_join(mlxsw_sp_port,
+ upper_dev, master,
+ extack);
+ if (err)
+ goto err_port_bridge_join;
+ }
+
+ ++done;
+ }
+
+ return 0;
+
+err_port_bridge_join:
+ netdev_for_each_upper_dev_rcu(lag_dev, upper_dev, iter) {
+ if (!is_vlan_dev(upper_dev))
+ continue;
+
+ master = netdev_master_upper_dev_get(upper_dev);
+ if (!master || !netif_is_bridge_master(master))
+ continue;
+
+ if (!done--)
+ break;
+
+ mlxsw_sp_port_bridge_leave(mlxsw_sp_port, upper_dev, master);
+ }
+
+ master = netdev_master_upper_dev_get(lag_dev);
+ if (master && netif_is_bridge_master(master))
+ mlxsw_sp_port_bridge_leave(mlxsw_sp_port, lag_dev, master);
+
+ return err;
+}
+
+static void
+mlxsw_sp_lag_uppers_bridge_leave(struct mlxsw_sp_port *mlxsw_sp_port,
+ struct net_device *lag_dev)
+{
+ struct net_device *upper_dev;
+ struct net_device *master;
+ struct list_head *iter;
+
+ netdev_for_each_upper_dev_rcu(lag_dev, upper_dev, iter) {
+ if (!is_vlan_dev(upper_dev))
+ continue;
+
+ master = netdev_master_upper_dev_get(upper_dev);
+ if (!master)
+ continue;
+
+ mlxsw_sp_port_bridge_leave(mlxsw_sp_port, upper_dev, master);
+ }
+
+ master = netdev_master_upper_dev_get(lag_dev);
+ if (master)
+ mlxsw_sp_port_bridge_leave(mlxsw_sp_port, lag_dev, master);
+}
+
static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port,
struct net_device *lag_dev,
struct netlink_ext_ack *extack)
@@ -3573,6 +3655,12 @@ static int mlxsw_sp_port_lag_join(struct
err = mlxsw_sp_port_lag_index_get(mlxsw_sp, lag_id, &port_index);
if (err)
return err;
+
+ err = mlxsw_sp_lag_uppers_bridge_join(mlxsw_sp_port, lag_dev,
+ extack);
+ if (err)
+ goto err_lag_uppers_bridge_join;
+
err = mlxsw_sp_lag_col_port_add(mlxsw_sp_port, lag_id, port_index);
if (err)
goto err_col_port_add;
@@ -3602,6 +3690,8 @@ err_router_join:
mlxsw_sp_port->local_port);
mlxsw_sp_lag_col_port_remove(mlxsw_sp_port, lag_id);
err_col_port_add:
+ mlxsw_sp_lag_uppers_bridge_leave(mlxsw_sp_port, lag_dev);
+err_lag_uppers_bridge_join:
if (!lag->ref_count)
mlxsw_sp_lag_destroy(mlxsw_sp, lag_id);
return err;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 066/235] mlxsw: fix refcount leak in mlxsw_sp_port_lag_join()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (64 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 065/235] mlxsw: spectrum: On port enslavement to a LAG, join uppers bridges Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 067/235] octeontx2: Annotate mmio regions as __iomem Greg Kroah-Hartman
` (171 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Wentao Liang, Ido Schimmel,
Jakub Kicinski, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wentao Liang <vulab@iscas.ac.cn>
[ Upstream commit 41c8c1d65b32beacd8d916a22457b4f6e47f45af ]
When mlxsw_sp_port_lag_index_get() fails, mlxsw_sp_port_lag_join()
returns an error without releasing the lag reference obtained by
the earlier mlxsw_sp_lag_get(). All other error paths in the
function jump to the cleanup label that ends with
mlxsw_sp_lag_put(), so this is a single missed release.
Fix the leak by replacing the bare 'return err' with a goto to the
existing error cleanup label, which will drop the reference safely.
Cc: stable@vger.kernel.org
Fixes: 0d65fc13042f ("mlxsw: spectrum: Implement LAG port join/leave")
Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20260609083709.209743-1-vulab@iscas.ac.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/mellanox/mlxsw/spectrum.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -3654,7 +3654,7 @@ static int mlxsw_sp_port_lag_join(struct
err = mlxsw_sp_port_lag_index_get(mlxsw_sp, lag_id, &port_index);
if (err)
- return err;
+ goto err_lag_uppers_bridge_join;
err = mlxsw_sp_lag_uppers_bridge_join(mlxsw_sp_port, lag_dev,
extack);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 067/235] octeontx2: Annotate mmio regions as __iomem
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (65 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 066/235] mlxsw: fix refcount leak in mlxsw_sp_port_lag_join() Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 068/235] octeontx2-pf: clear stale mailbox IRQ state before request_irq() Greg Kroah-Hartman
` (170 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Subbaraya Sundeep, Jakub Kicinski,
Sasha Levin
5.10-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: f918554fb724 ("octeontx2-pf: 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/nic/otx2_pf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -593,7 +593,7 @@ static int otx2_pfvf_mbox_init(struct ot
if (!pf->mbox_pfvf_wq)
return -ENOMEM;
- 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] 239+ messages in thread
* [PATCH 5.10 068/235] octeontx2-pf: clear stale mailbox IRQ state before request_irq()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (66 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 067/235] octeontx2: Annotate mmio regions as __iomem Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 069/235] ASoC: mediatek: mt8183: Check runtime resume during probe Greg Kroah-Hartman
` (169 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Runyu Xiao, Simon Horman,
Ratheesh Kannoth, Jakub Kicinski, Sasha Levin
5.10-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
@@ -979,6 +979,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");
@@ -990,10 +993,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] 239+ messages in thread
* [PATCH 5.10 069/235] ASoC: mediatek: mt8183: Check runtime resume during probe
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (67 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 068/235] octeontx2-pf: clear stale mailbox IRQ state before request_irq() Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 070/235] octeontx2-vf: clear stale mailbox IRQ state before request_irq() Greg Kroah-Hartman
` (168 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Cássio Gabriel, Mark Brown,
Sasha Levin
5.10-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
@@ -1143,17 +1143,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(&pdev->dev);
+ ret = pm_runtime_resume_and_get(dev);
+ if (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;
}
- pm_runtime_put_sync(&pdev->dev);
- afe_priv->pm_runtime_bypass_reg_ctl = false;
-
regcache_cache_only(afe->regmap, true);
regcache_mark_dirty(afe->regmap);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 070/235] octeontx2-vf: clear stale mailbox IRQ state before request_irq()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (68 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 069/235] ASoC: mediatek: mt8183: Check runtime resume during probe Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 071/235] netfilter: nf_conntrack_sip: remove net variable shadowing Greg Kroah-Hartman
` (167 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Runyu Xiao, Simon Horman,
Ratheesh Kannoth, Jakub Kicinski, Sasha Levin
5.10-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 | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
@@ -230,6 +230,9 @@ static int otx2vf_register_mbox_intr(str
char *irq_name;
int err;
+ /* Clear stale mailbox interrupt state before installing the handler. */
+ otx2_write64(vf, RVU_VF_INT, BIT_ULL(0));
+
/* Register mailbox interrupt handler */
irq_name = &hw->irq_name[RVU_VF_INT_VEC_MBOX * NAME_SIZE];
snprintf(irq_name, NAME_SIZE, "RVUVFAF Mbox");
@@ -241,10 +244,7 @@ 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));
+ /* Enable mailbox interrupt for msgs coming from PF. */
otx2_write64(vf, RVU_VF_INT_ENA_W1S, BIT_ULL(0));
if (!probe_pf)
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 071/235] netfilter: nf_conntrack_sip: remove net variable shadowing
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (69 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 070/235] octeontx2-vf: clear stale mailbox IRQ state before request_irq() Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 072/235] netfilter: nf_conntrack_sip: validate skb_dst() before accessing it Greg Kroah-Hartman
` (166 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Florian Westphal, Sasha Levin
5.10-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] 239+ messages in thread
* [PATCH 5.10 072/235] netfilter: nf_conntrack_sip: validate skb_dst() before accessing it
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (70 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 071/235] netfilter: nf_conntrack_sip: remove net variable shadowing Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 073/235] jbd2: add a helper to find out number of fast commit blocks Greg Kroah-Hartman
` (165 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Ren Wei, Pablo Neira Ayuso,
Florian Westphal, Sasha Levin
5.10-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] 239+ messages in thread
* [PATCH 5.10 073/235] jbd2: add a helper to find out number of fast commit blocks
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (71 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 072/235] netfilter: nf_conntrack_sip: validate skb_dst() before accessing it Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 074/235] jbd2: fix integer underflow in jbd2_journal_initialize_fast_commit() Greg Kroah-Hartman
` (164 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Harshad Shirwadkar, Theodore Tso,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Harshad Shirwadkar <harshadshirwadkar@gmail.com>
[ Upstream commit 9bd23c31f392bda88618008f27fd52ee9e0fac38 ]
Add a helper to read number of fast commit blocks from jbd2 superblock
and also rename the JBD2_MIN_FC_BLKS to
JBD2_DEFAULT_FAST_COMMIT_BLOCKS since this constant is just the
default number of fast commit blocks to use in case number of fast
commit blocks isn't set in jbd2 superblock.
Signed-off-by: Harshad Shirwadkar <harshadshirwadkar@gmail.com>
Link: https://lore.kernel.org/r/20201120202232.2240293-2-harshadshirwadkar@gmail.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Stable-dep-of: 289a2ca0c9b7 ("jbd2: fix integer underflow in jbd2_journal_initialize_fast_commit()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/jbd2/journal.c | 8 ++------
include/linux/jbd2.h | 9 ++++++++-
2 files changed, 10 insertions(+), 7 deletions(-)
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -1884,9 +1884,7 @@ static int load_superblock(journal_t *jo
if (jbd2_has_feature_fast_commit(journal)) {
journal->j_fc_last = be32_to_cpu(sb->s_maxlen);
- num_fc_blocks = be32_to_cpu(sb->s_num_fc_blks);
- if (!num_fc_blocks)
- num_fc_blocks = JBD2_MIN_FC_BLOCKS;
+ num_fc_blocks = jbd2_journal_get_num_fc_blks(sb);
if (journal->j_last - num_fc_blocks >= JBD2_MIN_JOURNAL_BLOCKS)
journal->j_last = journal->j_fc_last - num_fc_blocks;
journal->j_fc_first = journal->j_last + 1;
@@ -2117,9 +2115,7 @@ jbd2_journal_initialize_fast_commit(jour
journal_superblock_t *sb = journal->j_superblock;
unsigned long long num_fc_blks;
- num_fc_blks = be32_to_cpu(sb->s_num_fc_blks);
- if (num_fc_blks == 0)
- num_fc_blks = JBD2_MIN_FC_BLOCKS;
+ num_fc_blks = jbd2_journal_get_num_fc_blks(sb);
if (journal->j_last - num_fc_blks < JBD2_MIN_JOURNAL_BLOCKS)
return -ENOSPC;
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -68,7 +68,7 @@ extern void *jbd2_alloc(size_t size, gfp
extern void jbd2_free(void *ptr, size_t size);
#define JBD2_MIN_JOURNAL_BLOCKS 1024
-#define JBD2_MIN_FC_BLOCKS 256
+#define JBD2_DEFAULT_FAST_COMMIT_BLOCKS 256
#ifdef __KERNEL__
@@ -1686,6 +1686,13 @@ static inline int jbd2_journal_has_csum_
return journal->j_chksum_driver != NULL;
}
+static inline int jbd2_journal_get_num_fc_blks(journal_superblock_t *jsb)
+{
+ int num_fc_blocks = be32_to_cpu(jsb->s_num_fc_blks);
+
+ return num_fc_blocks ? num_fc_blocks : JBD2_DEFAULT_FAST_COMMIT_BLOCKS;
+}
+
/*
* Return number of free blocks in the log. Must be called under j_state_lock.
*/
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 074/235] jbd2: fix integer underflow in jbd2_journal_initialize_fast_commit()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (72 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 073/235] jbd2: add a helper to find out number of fast commit blocks Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 075/235] netfilter: nft_set_pipapo: use GFP_KERNEL for insertions Greg Kroah-Hartman
` (163 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yuhao Jiang, Junrui Luo, Baokun Li,
Zhang Yi, Jan Kara, Theodore Tso, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Junrui Luo <moonafterrain@outlook.com>
[ Upstream commit 289a2ca0c9b7eae74f93fc213b0b971669b8683d ]
jbd2_journal_initialize_fast_commit() validates journal capacity by
checking (journal->j_last - num_fc_blks < JBD2_MIN_JOURNAL_BLOCKS).
Both j_last and num_fc_blks are unsigned, so when num_fc_blks exceeds
j_last the subtraction wraps to a large value, bypassing the bounds
check.
The resulting underflow corrupts j_last, j_fc_first, and j_free,
leading to journal abort.
Fix by checking num_fc_blks against j_last before the subtraction,
returning -EFSCORRUPTED.
Fixes: 6866d7b3f2bb ("ext4 / jbd2: add fast commit initialization")
Reported-by: Yuhao Jiang <danisjiang@gmail.com>
Cc: stable@vger.kernel.org
Signed-off-by: Junrui Luo <moonafterrain@outlook.com>
Fixes: e029c5f27987 ("ext4: make num of fast commit blocks configurable")
Reviewed-by: Baokun Li <libaokun@linux.alibaba.com>
Fixes: e029c5f279872 ("ext4: make num of fast commit blocks configurable")
Reviewed-by: Zhang Yi <yi.zhang@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Link: https://patch.msgid.link/SYBPR01MB7881663C927DE9D7BBF4D1DFAF062@SYBPR01MB7881.ausprd01.prod.outlook.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/jbd2/journal.c | 2 ++
1 file changed, 2 insertions(+)
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -2116,6 +2116,8 @@ jbd2_journal_initialize_fast_commit(jour
unsigned long long num_fc_blks;
num_fc_blks = jbd2_journal_get_num_fc_blks(sb);
+ if (num_fc_blks > journal->j_last)
+ return -EFSCORRUPTED;
if (journal->j_last - num_fc_blks < JBD2_MIN_JOURNAL_BLOCKS)
return -ENOSPC;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 075/235] netfilter: nft_set_pipapo: use GFP_KERNEL for insertions
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (73 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 074/235] jbd2: fix integer underflow in jbd2_journal_initialize_fast_commit() Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 076/235] netfilter: nft_set_pipapo: make pipapo_clone helper return NULL Greg Kroah-Hartman
` (162 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Pablo Neira Ayuso, Florian Westphal,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <fw@strlen.de>
[ Upstream commit 5b651783d80b97167ecd27dc6a4408c694873902 ]
An earlier attempt changed this to GFP_KERNEL, but the get helper is
also called for get requests from userspace, which uses rcu.
Let the caller pass in the kmalloc flags to allow insertions
to schedule if needed.
Suggested-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Florian Westphal <fw@strlen.de>
Stable-dep-of: 47e65eff5069 ("netfilter: nft_set_pipapo: don't leak bad clone into future transaction")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/netfilter/nft_set_pipapo.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
--- a/net/netfilter/nft_set_pipapo.c
+++ b/net/netfilter/nft_set_pipapo.c
@@ -505,6 +505,7 @@ out:
* @data: Key data to be matched against existing elements
* @genmask: If set, check that element is active in given genmask
* @tstamp: timestamp to check for expired elements
+ * @gfp: the type of memory to allocate (see kmalloc).
*
* This is essentially the same as the lookup function, except that it matches
* key data against the uncommitted copy and doesn't use preallocated maps for
@@ -515,7 +516,7 @@ out:
static struct nft_pipapo_elem *pipapo_get(const struct net *net,
const struct nft_set *set,
const u8 *data, u8 genmask,
- u64 tstamp)
+ u64 tstamp, gfp_t gfp)
{
struct nft_pipapo_elem *ret = ERR_PTR(-ENOENT);
struct nft_pipapo *priv = nft_set_priv(set);
@@ -527,13 +528,13 @@ static struct nft_pipapo_elem *pipapo_ge
if (m->bsize_max == 0)
return ret;
- res_map = kmalloc_array(m->bsize_max, sizeof(*res_map), GFP_ATOMIC);
+ res_map = kmalloc_array(m->bsize_max, sizeof(*res_map), gfp);
if (!res_map) {
ret = ERR_PTR(-ENOMEM);
goto out;
}
- fill_map = kcalloc(m->bsize_max, sizeof(*res_map), GFP_ATOMIC);
+ fill_map = kcalloc(m->bsize_max, sizeof(*res_map), gfp);
if (!fill_map) {
ret = ERR_PTR(-ENOMEM);
goto out;
@@ -608,7 +609,7 @@ static void *nft_pipapo_get(const struct
const struct nft_set_elem *elem, unsigned int flags)
{
return pipapo_get(net, set, (const u8 *)elem->key.val.data,
- nft_genmask_cur(net), get_jiffies_64());
+ nft_genmask_cur(net), get_jiffies_64(), GFP_ATOMIC);
}
/**
@@ -1217,7 +1218,7 @@ static int nft_pipapo_insert(const struc
else
end = start;
- dup = pipapo_get(net, set, start, genmask, tstamp);
+ dup = pipapo_get(net, set, start, genmask, tstamp, GFP_KERNEL);
if (!IS_ERR(dup)) {
/* Check if we already have the same exact entry */
const struct nft_data *dup_key, *dup_end;
@@ -1239,7 +1240,8 @@ static int nft_pipapo_insert(const struc
if (PTR_ERR(dup) == -ENOENT) {
/* Look for partially overlapping entries */
- dup = pipapo_get(net, set, end, nft_genmask_next(net), tstamp);
+ dup = pipapo_get(net, set, end, nft_genmask_next(net), tstamp,
+ GFP_KERNEL);
}
if (PTR_ERR(dup) != -ENOENT) {
@@ -1814,7 +1816,8 @@ static void *pipapo_deactivate(const str
{
struct nft_pipapo_elem *e;
- e = pipapo_get(net, set, data, nft_genmask_next(net), nft_net_tstamp(net));
+ e = pipapo_get(net, set, data, nft_genmask_next(net),
+ nft_net_tstamp(net), GFP_KERNEL);
if (IS_ERR(e))
return NULL;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 076/235] netfilter: nft_set_pipapo: make pipapo_clone helper return NULL
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (74 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 075/235] netfilter: nft_set_pipapo: use GFP_KERNEL for insertions Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 077/235] netfilter: nft_set_pipapo: prepare walk function for on-demand clone Greg Kroah-Hartman
` (161 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Florian Westphal, Stefano Brivio,
Pablo Neira Ayuso, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <fw@strlen.de>
[ Upstream commit 80efd2997fb9343a0283cf3cac5524a4595c8ff4 ]
Currently it returns an error pointer, but the only possible failure
is ENOMEM.
After a followup patch, we'd need to discard the errno code, i.e.
x = pipapo_clone()
if (IS_ERR(x))
return NULL
or make more changes to fix up callers to expect IS_ERR() code
from set->ops->deactivate().
So simplify this and make it return ptr-or-null.
Signed-off-by: Florian Westphal <fw@strlen.de>
Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Stable-dep-of: 47e65eff5069 ("netfilter: nft_set_pipapo: don't leak bad clone into future transaction")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/netfilter/nft_set_pipapo.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
--- a/net/netfilter/nft_set_pipapo.c
+++ b/net/netfilter/nft_set_pipapo.c
@@ -1318,7 +1318,7 @@ static int nft_pipapo_insert(const struc
* pipapo_clone() - Clone matching data to create new working copy
* @old: Existing matching data
*
- * Return: copy of matching data passed as 'old', error pointer on failure
+ * Return: copy of matching data passed as 'old' or NULL.
*/
static struct nft_pipapo_match *pipapo_clone(struct nft_pipapo_match *old)
{
@@ -1329,7 +1329,7 @@ static struct nft_pipapo_match *pipapo_c
new = kmalloc(sizeof(*new) + sizeof(*dst) * old->field_count,
GFP_KERNEL);
if (!new)
- return ERR_PTR(-ENOMEM);
+ return NULL;
new->field_count = old->field_count;
new->bsize_max = old->bsize_max;
@@ -1403,7 +1403,7 @@ out_scratch:
free_percpu(new->scratch);
kfree(new);
- return ERR_PTR(-ENOMEM);
+ return NULL;
}
/**
@@ -1743,7 +1743,7 @@ static void nft_pipapo_commit(const stru
goto out;
new_clone = pipapo_clone(priv->clone);
- if (IS_ERR(new_clone))
+ if (!new_clone)
goto out;
priv->dirty = false;
@@ -1769,7 +1769,7 @@ static void nft_pipapo_abort(const struc
m = rcu_dereference(priv->match);
new_clone = pipapo_clone(m);
- if (IS_ERR(new_clone))
+ if (!new_clone)
return;
priv->dirty = false;
@@ -2214,8 +2214,8 @@ static int nft_pipapo_init(const struct
/* Create an initial clone of matching data for next insertion */
priv->clone = pipapo_clone(m);
- if (IS_ERR(priv->clone)) {
- err = PTR_ERR(priv->clone);
+ if (!priv->clone) {
+ err = -ENOMEM;
goto out_free;
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 077/235] netfilter: nft_set_pipapo: prepare walk function for on-demand clone
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (75 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 076/235] netfilter: nft_set_pipapo: make pipapo_clone helper return NULL Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 078/235] netfilter: nft_set_pipapo: merge deactivate helper into caller Greg Kroah-Hartman
` (160 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Florian Westphal, Stefano Brivio,
Pablo Neira Ayuso, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <fw@strlen.de>
[ Upstream commit 6c108d9bee448a850b03e682836bfe91fca645cb ]
The existing code uses iter->type to figure out what data is needed, the
live copy (READ) or clone (UPDATE).
Without pending updates, priv->clone and priv->match will point to
different memory locations, but they have identical content.
Future patch will make priv->clone == NULL if there are no pending changes,
in this case we must copy the live data for the UPDATE case.
Currently this would require GFP_ATOMIC allocation. Split the walk
function in two parts: one that does the walk and one that decides which
data is needed.
In the UPDATE case, callers hold the transaction mutex so we do not need
the rcu read lock. This allows to use GFP_KERNEL allocation while
cloning.
Signed-off-by: Florian Westphal <fw@strlen.de>
Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Stable-dep-of: 47e65eff5069 ("netfilter: nft_set_pipapo: don't leak bad clone into future transaction")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/netfilter/nft_set_pipapo.c | 64 ++++++++++++++++++++++++++---------------
1 file changed, 41 insertions(+), 23 deletions(-)
--- a/net/netfilter/nft_set_pipapo.c
+++ b/net/netfilter/nft_set_pipapo.c
@@ -2054,34 +2054,22 @@ static void nft_pipapo_remove(const stru
}
/**
- * nft_pipapo_walk() - Walk over elements
+ * nft_pipapo_do_walk() - Walk over elements in m
* @ctx: nftables API context
* @set: nftables API set representation
+ * @m: matching data pointing to key mapping array
* @iter: Iterator
*
* As elements are referenced in the mapping array for the last field, directly
* scan that array: there's no need to follow rule mappings from the first
- * field.
+ * field. @m is protected either by RCU read lock or by transaction mutex.
*/
-static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set,
- struct nft_set_iter *iter)
+static void nft_pipapo_do_walk(const struct nft_ctx *ctx, struct nft_set *set,
+ const struct nft_pipapo_match *m,
+ struct nft_set_iter *iter)
{
- struct nft_pipapo *priv = nft_set_priv(set);
- struct nft_pipapo_match *m;
- struct nft_pipapo_field *f;
- int i, r;
-
- WARN_ON_ONCE(iter->type != NFT_ITER_READ &&
- iter->type != NFT_ITER_UPDATE);
-
- rcu_read_lock();
- if (iter->type == NFT_ITER_READ)
- m = rcu_dereference(priv->match);
- else
- m = priv->clone;
-
- if (unlikely(!m))
- goto out;
+ const struct nft_pipapo_field *f;
+ unsigned int i, r;
for (i = 0, f = m->f; i < m->field_count - 1; i++, f++)
;
@@ -2105,14 +2093,44 @@ static void nft_pipapo_walk(const struct
iter->err = iter->fn(ctx, set, iter, &elem);
if (iter->err < 0)
- goto out;
+ return;
cont:
iter->count++;
}
+}
-out:
- rcu_read_unlock();
+/**
+ * nft_pipapo_walk() - Walk over elements
+ * @ctx: nftables API context
+ * @set: nftables API set representation
+ * @iter: Iterator
+ *
+ * Test if destructive action is needed or not, clone active backend if needed
+ * and call the real function to work on the data.
+ */
+static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set,
+ struct nft_set_iter *iter)
+{
+ struct nft_pipapo *priv = nft_set_priv(set);
+ const struct nft_pipapo_match *m;
+
+ switch (iter->type) {
+ case NFT_ITER_UPDATE:
+ m = priv->clone;
+ nft_pipapo_do_walk(ctx, set, m, iter);
+ break;
+ case NFT_ITER_READ:
+ rcu_read_lock();
+ m = rcu_dereference(priv->match);
+ nft_pipapo_do_walk(ctx, set, m, iter);
+ rcu_read_unlock();
+ break;
+ default:
+ iter->err = -EINVAL;
+ WARN_ON_ONCE(1);
+ break;
+ }
}
/**
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 078/235] netfilter: nft_set_pipapo: merge deactivate helper into caller
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (76 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 077/235] netfilter: nft_set_pipapo: prepare walk function for on-demand clone Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 079/235] netfilter: nft_set_pipapo: prepare pipapo_get helper for on-demand clone Greg Kroah-Hartman
` (159 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Florian Westphal, Stefano Brivio,
Pablo Neira Ayuso, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <fw@strlen.de>
[ Upstream commit c5444786d0ea2417a5e2cee7bd67137fc8bad687 ]
Its the only remaining call site so there is no need for this to
be separated anymore.
Signed-off-by: Florian Westphal <fw@strlen.de>
Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Stable-dep-of: 47e65eff5069 ("netfilter: nft_set_pipapo: don't leak bad clone into future transaction")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/netfilter/nft_set_pipapo.c | 39 +++++++++------------------------------
1 file changed, 9 insertions(+), 30 deletions(-)
--- a/net/netfilter/nft_set_pipapo.c
+++ b/net/netfilter/nft_set_pipapo.c
@@ -1799,52 +1799,31 @@ static void nft_pipapo_activate(const st
}
/**
- * pipapo_deactivate() - Check that element is in set, mark as inactive
+ * nft_pipapo_deactivate() - Search for element and make it inactive
* @net: Network namespace
* @set: nftables API set representation
- * @data: Input key data
- * @ext: nftables API extension pointer, used to check for end element
- *
- * This is a convenience function that can be called from both
- * nft_pipapo_deactivate() and nft_pipapo_flush(), as they are in fact the same
- * operation.
+ * @elem: nftables API element representation containing key data
*
* Return: deactivated element if found, NULL otherwise.
*/
-static void *pipapo_deactivate(const struct net *net, const struct nft_set *set,
- const u8 *data, const struct nft_set_ext *ext)
+static void *nft_pipapo_deactivate(const struct net *net,
+ const struct nft_set *set,
+ const struct nft_set_elem *elem)
{
struct nft_pipapo_elem *e;
- e = pipapo_get(net, set, data, nft_genmask_next(net),
- nft_net_tstamp(net), GFP_KERNEL);
+ e = pipapo_get(net, set, (const u8 *)elem->key.val.data,
+ nft_genmask_next(net), nft_net_tstamp(net), GFP_KERNEL);
if (IS_ERR(e))
return NULL;
nft_set_elem_change_active(net, set, &e->ext);
- return e;
-}
-
-/**
- * nft_pipapo_deactivate() - Call pipapo_deactivate() to make element inactive
- * @net: Network namespace
- * @set: nftables API set representation
- * @elem: nftables API element representation containing key data
- *
- * Return: deactivated element if found, NULL otherwise.
- */
-static void *nft_pipapo_deactivate(const struct net *net,
- const struct nft_set *set,
- const struct nft_set_elem *elem)
-{
- const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv);
-
- return pipapo_deactivate(net, set, (const u8 *)elem->key.val.data, ext);
+ return &e->priv;
}
/**
- * nft_pipapo_flush() - Call pipapo_deactivate() to make element inactive
+ * nft_pipapo_flush() - make element inactive
* @net: Network namespace
* @set: nftables API set representation
* @elem: nftables API element representation containing key data
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 079/235] netfilter: nft_set_pipapo: prepare pipapo_get helper for on-demand clone
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (77 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 078/235] netfilter: nft_set_pipapo: merge deactivate helper into caller Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 080/235] netfilter: nft_set_pipapo: move cloning of match info to insert/removal path Greg Kroah-Hartman
` (158 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Florian Westphal, Stefano Brivio,
Pablo Neira Ayuso, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <fw@strlen.de>
[ Upstream commit a238106703ab4ae1090b86eba128815b8626d8f1 ]
The helper uses priv->clone unconditionally which will fail once we do
the clone conditionally on first insert or removal.
'nft get element' from userspace needs to use priv->match since this
runs from rcu read side lock section.
Prepare for this by passing the match backend data as argument.
Signed-off-by: Florian Westphal <fw@strlen.de>
Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Stable-dep-of: 47e65eff5069 ("netfilter: nft_set_pipapo: don't leak bad clone into future transaction")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/netfilter/nft_set_pipapo.c | 24 +++++++++++++++---------
1 file changed, 15 insertions(+), 9 deletions(-)
--- a/net/netfilter/nft_set_pipapo.c
+++ b/net/netfilter/nft_set_pipapo.c
@@ -502,6 +502,7 @@ out:
* pipapo_get() - Get matching element reference given key data
* @net: Network namespace
* @set: nftables API set representation
+ * @m: storage containing active/existing elements
* @data: Key data to be matched against existing elements
* @genmask: If set, check that element is active in given genmask
* @tstamp: timestamp to check for expired elements
@@ -515,12 +516,11 @@ out:
*/
static struct nft_pipapo_elem *pipapo_get(const struct net *net,
const struct nft_set *set,
+ const struct nft_pipapo_match *m,
const u8 *data, u8 genmask,
u64 tstamp, gfp_t gfp)
{
struct nft_pipapo_elem *ret = ERR_PTR(-ENOENT);
- struct nft_pipapo *priv = nft_set_priv(set);
- struct nft_pipapo_match *m = priv->clone;
unsigned long *res_map, *fill_map = NULL;
struct nft_pipapo_field *f;
int i;
@@ -608,7 +608,10 @@ out:
static void *nft_pipapo_get(const struct net *net, const struct nft_set *set,
const struct nft_set_elem *elem, unsigned int flags)
{
- return pipapo_get(net, set, (const u8 *)elem->key.val.data,
+ struct nft_pipapo *priv = nft_set_priv(set);
+ struct nft_pipapo_match *m = rcu_dereference(priv->match);
+
+ return pipapo_get(net, set, m, (const u8 *)elem->key.val.data,
nft_genmask_cur(net), get_jiffies_64(), GFP_ATOMIC);
}
@@ -1218,7 +1221,7 @@ static int nft_pipapo_insert(const struc
else
end = start;
- dup = pipapo_get(net, set, start, genmask, tstamp, GFP_KERNEL);
+ dup = pipapo_get(net, set, m, start, genmask, tstamp, GFP_KERNEL);
if (!IS_ERR(dup)) {
/* Check if we already have the same exact entry */
const struct nft_data *dup_key, *dup_end;
@@ -1240,7 +1243,7 @@ static int nft_pipapo_insert(const struc
if (PTR_ERR(dup) == -ENOENT) {
/* Look for partially overlapping entries */
- dup = pipapo_get(net, set, end, nft_genmask_next(net), tstamp,
+ dup = pipapo_get(net, set, m, end, nft_genmask_next(net), tstamp,
GFP_KERNEL);
}
@@ -1810,16 +1813,18 @@ static void *nft_pipapo_deactivate(const
const struct nft_set *set,
const struct nft_set_elem *elem)
{
+ const struct nft_pipapo *priv = nft_set_priv(set);
+ struct nft_pipapo_match *m = priv->clone;
struct nft_pipapo_elem *e;
- e = pipapo_get(net, set, (const u8 *)elem->key.val.data,
+ e = pipapo_get(net, set, m, (const u8 *)elem->key.val.data,
nft_genmask_next(net), nft_net_tstamp(net), GFP_KERNEL);
if (IS_ERR(e))
return NULL;
nft_set_elem_change_active(net, set, &e->ext);
- return &e->priv;
+ return e;
}
/**
@@ -1845,8 +1850,9 @@ static bool nft_pipapo_flush(const struc
{
struct nft_pipapo_elem *e = elem;
- return pipapo_deactivate(net, set, (const u8 *)nft_set_ext_key(&e->ext),
- &e->ext);
+ nft_set_elem_change_active(net, set, &e->ext);
+
+ return true;
}
/**
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 080/235] netfilter: nft_set_pipapo: move cloning of match info to insert/removal path
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (78 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 079/235] netfilter: nft_set_pipapo: prepare pipapo_get helper for on-demand clone Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 081/235] netfilter: nft_set_pipapo: dont leak bad clone into future transaction Greg Kroah-Hartman
` (157 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Florian Westphal, Stefano Brivio,
Pablo Neira Ayuso, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <fw@strlen.de>
[ Upstream commit 3f1d886cc7c3525d4dbeee24bfa9bb3fe0d48ddc ]
This set type keeps two copies of the sets' content,
priv->match (live version, used to match from packet path)
priv->clone (work-in-progress version of the 'future' priv->match).
All additions and removals are done on priv->clone. When transaction
completes, priv->clone becomes priv->match and a new clone is allocated
for use by next transaction.
Problem is that the cloning requires GFP_KERNEL allocations but we
cannot fail at either commit or abort time.
This patch defers the clone until we get an insertion or removal
request. This allows us to handle OOM situations correctly.
This also allows to remove ->dirty in a followup change:
If ->clone exists, ->dirty is always true
If ->clone is NULL, ->dirty is always false, no elements were added
or removed (except catchall elements which are external to the specific
set backend).
Signed-off-by: Florian Westphal <fw@strlen.de>
Reviewed-by: Stefano Brivio <sbrivio@redhat.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Stable-dep-of: 47e65eff5069 ("netfilter: nft_set_pipapo: don't leak bad clone into future transaction")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/netfilter/nft_set_pipapo.c | 82 ++++++++++++++++++++++++++++++-----------
1 file changed, 61 insertions(+), 21 deletions(-)
--- a/net/netfilter/nft_set_pipapo.c
+++ b/net/netfilter/nft_set_pipapo.c
@@ -1191,6 +1191,41 @@ static int pipapo_realloc_scratch(struct
return 0;
}
+static bool nft_pipapo_transaction_mutex_held(const struct nft_set *set)
+{
+#ifdef CONFIG_PROVE_LOCKING
+ const struct net *net = read_pnet(&set->net);
+ struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
+
+ return lockdep_is_held(&nft_net->commit_mutex);
+#else
+ return true;
+#endif
+}
+
+static struct nft_pipapo_match *pipapo_clone(struct nft_pipapo_match *old);
+
+/**
+ * pipapo_maybe_clone() - Build clone for pending data changes, if not existing
+ * @set: nftables API set representation
+ *
+ * Return: newly created or existing clone, if any. NULL on allocation failure
+ */
+static struct nft_pipapo_match *pipapo_maybe_clone(const struct nft_set *set)
+{
+ struct nft_pipapo *priv = nft_set_priv(set);
+ struct nft_pipapo_match *m;
+
+ if (priv->clone)
+ return priv->clone;
+
+ m = rcu_dereference_protected(priv->match,
+ nft_pipapo_transaction_mutex_held(set));
+ priv->clone = pipapo_clone(m);
+
+ return priv->clone;
+}
+
/**
* nft_pipapo_insert() - Validate and insert ranged elements
* @net: Network namespace
@@ -1208,14 +1243,17 @@ static int nft_pipapo_insert(const struc
union nft_pipapo_map_bucket rulemap[NFT_PIPAPO_MAX_FIELDS];
const u8 *start = (const u8 *)elem->key.val.data, *end;
struct nft_pipapo_elem *e = elem->priv, *dup;
+ struct nft_pipapo_match *m = pipapo_maybe_clone(set);
struct nft_pipapo *priv = nft_set_priv(set);
- struct nft_pipapo_match *m = priv->clone;
u8 genmask = nft_genmask_next(net);
u64 tstamp = nft_net_tstamp(net);
struct nft_pipapo_field *f;
const u8 *start_p, *end_p;
int i, bsize_max, err = 0;
+ if (!m)
+ return -ENOMEM;
+
if (nft_set_ext_exists(ext, NFT_SET_EXT_KEY_END))
end = (const u8 *)nft_set_ext_key_end(ext)->data;
else
@@ -1737,7 +1775,10 @@ static void pipapo_reclaim_match(struct
static void nft_pipapo_commit(const struct nft_set *set)
{
struct nft_pipapo *priv = nft_set_priv(set);
- struct nft_pipapo_match *new_clone, *old;
+ struct nft_pipapo_match *old;
+
+ if (!priv->clone)
+ return;
if (time_after_eq(jiffies, priv->last_gc + nft_set_gc_interval(set)))
pipapo_gc_scan(set, priv->clone);
@@ -1745,18 +1786,13 @@ static void nft_pipapo_commit(const stru
if (!priv->dirty)
goto out;
- new_clone = pipapo_clone(priv->clone);
- if (!new_clone)
- goto out;
-
+ old = rcu_replace_pointer(priv->match, priv->clone,
+ nft_pipapo_transaction_mutex_held(set));
+ priv->clone = NULL;
priv->dirty = false;
- old = rcu_access_pointer(priv->match);
- rcu_assign_pointer(priv->match, priv->clone);
if (old)
call_rcu(&old->rcu, pipapo_reclaim_match);
-
- priv->clone = new_clone;
out:
pipapo_gc_queue(set);
}
@@ -1764,21 +1800,15 @@ out:
static void nft_pipapo_abort(const struct nft_set *set)
{
struct nft_pipapo *priv = nft_set_priv(set);
- struct nft_pipapo_match *new_clone, *m;
if (!priv->dirty)
return;
- m = rcu_dereference(priv->match);
-
- new_clone = pipapo_clone(m);
- if (!new_clone)
+ if (!priv->clone)
return;
-
priv->dirty = false;
-
pipapo_free_match(priv->clone);
- priv->clone = new_clone;
+ priv->clone = NULL;
}
/**
@@ -1813,10 +1843,15 @@ static void *nft_pipapo_deactivate(const
const struct nft_set *set,
const struct nft_set_elem *elem)
{
- const struct nft_pipapo *priv = nft_set_priv(set);
- struct nft_pipapo_match *m = priv->clone;
+ struct nft_pipapo_match *m = pipapo_maybe_clone(set);
struct nft_pipapo_elem *e;
+ /* removal must occur on priv->clone, if we are low on memory
+ * we have no choice and must fail the removal request.
+ */
+ if (!m)
+ return NULL;
+
e = pipapo_get(net, set, m, (const u8 *)elem->key.val.data,
nft_genmask_next(net), nft_net_tstamp(net), GFP_KERNEL);
if (IS_ERR(e))
@@ -2102,7 +2137,12 @@ static void nft_pipapo_walk(const struct
switch (iter->type) {
case NFT_ITER_UPDATE:
- m = priv->clone;
+ m = pipapo_maybe_clone(set);
+ if (!m) {
+ iter->err = -ENOMEM;
+ return;
+ }
+
nft_pipapo_do_walk(ctx, set, m, iter);
break;
case NFT_ITER_READ:
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 081/235] netfilter: nft_set_pipapo: dont leak bad clone into future transaction
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (79 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 080/235] netfilter: nft_set_pipapo: move cloning of match info to insert/removal path Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 082/235] lsm: use default hook return value in call_int_hook() Greg Kroah-Hartman
` (156 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Stefano Brivio, Florian Westphal,
Sasha Levin, Seesee
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <fw@strlen.de>
[ Upstream commit 47e65eff50691f0a5b79d325e28d83ec1da43bcf ]
On memory allocation failure the cloned nft_pipapo_match can enter a bad
state:
- some fields can have their lookup tables resized while others did
not
- bits might have been toggled
- scratch map can be undersized which also means m->bsize_max can be
lower than what is required
This means that the next insertion in the same batch can trigger
out-of-bounds writes.
Furthermore, a failure in the first can result in the bad clone to
leak into the next transaction because the abort callback is never
executed in this case (the upper layer saw an error and no attempt to
allocate a transactional request was made).
Record a state for the nft_pipapo_match structure:
- NEW (pristine clone)
- MOD (modified clone with good state)
- ERR (potentially bogus content)
Then make it so that deletes and insertions fail when the clone
entered ERR state.
In case the very first insert attempt results in an error, free the
clone right away.
Fixes: 3c4287f62044 ("nf_tables: Add set type for arbitrary concatenation of ranges")
Cc: stable@vger.kernel.org
Reported-and-tested-by: Seesee <cjc000013@gmail.com>
Reviewed-by: Stefano Brivio <sbrivio@redhat.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_set_pipapo.c | 34 +++++++++++++++++++++++++++++-----
net/netfilter/nft_set_pipapo.h | 8 ++++++++
2 files changed, 37 insertions(+), 5 deletions(-)
--- a/net/netfilter/nft_set_pipapo.c
+++ b/net/netfilter/nft_set_pipapo.c
@@ -342,6 +342,8 @@
#include "nft_set_pipapo_avx2.h"
#include "nft_set_pipapo.h"
+static void nft_pipapo_abort(const struct nft_set *set);
+
/**
* pipapo_refill() - For each set bit, set bits from selected mapping table item
* @map: Bitmap to be scanned for set bits
@@ -1251,7 +1253,7 @@ static int nft_pipapo_insert(const struc
const u8 *start_p, *end_p;
int i, bsize_max, err = 0;
- if (!m)
+ if (!m || m->state == NFT_PIPAPO_CLONE_ERR)
return -ENOMEM;
if (nft_set_ext_exists(ext, NFT_SET_EXT_KEY_END))
@@ -1324,8 +1326,10 @@ static int nft_pipapo_insert(const struc
else
ret = pipapo_expand(f, start, end, f->groups * f->bb);
- if (ret < 0)
- return ret;
+ if (ret < 0) {
+ err = ret;
+ goto abort;
+ }
if (f->bsize > bsize_max)
bsize_max = f->bsize;
@@ -1341,7 +1345,7 @@ static int nft_pipapo_insert(const struc
err = pipapo_realloc_scratch(m, bsize_max);
if (err)
- return err;
+ goto abort;
m->bsize_max = bsize_max;
} else {
@@ -1352,7 +1356,26 @@ static int nft_pipapo_insert(const struc
pipapo_map(m, rulemap, e);
+ m->state = NFT_PIPAPO_CLONE_MOD;
return 0;
+abort:
+ WARN_ON_ONCE(m->state == NFT_PIPAPO_CLONE_ERR);
+
+ /* Two rollback cases:
+ * 1) no previous changes. nft_pipapo_abort is not
+ * guaranteed to be invoked (there might be no further
+ * add/delete requests coming after this).
+ *
+ * 2) we had previous changes: there are transaction
+ * records pointing to this set. Leave the rollback to
+ * the transaction handling.
+ */
+ if (m->state == NFT_PIPAPO_CLONE_NEW)
+ nft_pipapo_abort(set); /* releases m */
+ else
+ m->state = NFT_PIPAPO_CLONE_ERR;
+
+ return err;
}
/**
@@ -1427,6 +1450,7 @@ static struct nft_pipapo_match *pipapo_c
dst++;
}
+ new->state = NFT_PIPAPO_CLONE_NEW;
return new;
out_mt:
@@ -1849,7 +1873,7 @@ static void *nft_pipapo_deactivate(const
/* removal must occur on priv->clone, if we are low on memory
* we have no choice and must fail the removal request.
*/
- if (!m)
+ if (!m || m->state == NFT_PIPAPO_CLONE_ERR)
return NULL;
e = pipapo_get(net, set, m, (const u8 *)elem->key.val.data,
--- a/net/netfilter/nft_set_pipapo.h
+++ b/net/netfilter/nft_set_pipapo.h
@@ -142,9 +142,16 @@ struct nft_pipapo_scratch {
unsigned long map[];
};
+enum nft_pipapo_clone_state {
+ NFT_PIPAPO_CLONE_NEW,
+ NFT_PIPAPO_CLONE_MOD,
+ NFT_PIPAPO_CLONE_ERR,
+};
+
/**
* struct nft_pipapo_match - Data used for lookup and matching
* @field_count Amount of fields in set
+ * @state: add/delete state; used from control plane
* @scratch: Preallocated per-CPU maps for partial matching results
* @bsize_max: Maximum lookup table bucket size of all fields, in longs
* @rcu Matching data is swapped on commits
@@ -152,6 +159,7 @@ struct nft_pipapo_scratch {
*/
struct nft_pipapo_match {
int field_count;
+ enum nft_pipapo_clone_state state:8;
struct nft_pipapo_scratch * __percpu *scratch;
size_t bsize_max;
struct rcu_head rcu;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 082/235] lsm: use default hook return value in call_int_hook()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (80 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 081/235] netfilter: nft_set_pipapo: dont leak bad clone into future transaction Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 083/235] lsm: infrastructure management of the sock security Greg Kroah-Hartman
` (155 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Ondrej Mosnacek, Casey Schaufler,
Paul Moore, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ondrej Mosnacek <omosnace@redhat.com>
[ Upstream commit 260017f31a8c3879be5f9048a46f382b06c1923a ]
Change the definition of call_int_hook() to treat LSM_RET_DEFAULT(...)
as the "continue" value instead of 0. To further simplify this macro,
also drop the IRC argument and replace it with LSM_RET_DEFAULT(...).
After this the macro can be used in a couple more hooks, where similar
logic is currently open-coded. At the same time, some other existing
call_int_hook() users now need to be open-coded, but overall it's still
a net simplification.
There should be no functional change resulting from this patch.
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
Reviewed-by: Casey Schaufler <casey@schaufler-ca.com>
[PM: merge fuzz due to other hook changes, tweaks from list discussion]
Signed-off-by: Paul Moore <paul@paul-moore.com>
Stable-dep-of: 56acfeb10019 ("selinux: avoid sk_socket dereference in selinux_sctp_bind_connect()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
security/security.c | 461 +++++++++++++++++++++++++++++-----------------------
1 file changed, 262 insertions(+), 199 deletions(-)
--- a/security/security.c
+++ b/security/security.c
@@ -710,14 +710,14 @@ static void __init lsm_early_task(struct
P->hook.FUNC(__VA_ARGS__); \
} while (0)
-#define call_int_hook(FUNC, IRC, ...) ({ \
- int RC = IRC; \
+#define call_int_hook(FUNC, ...) ({ \
+ int RC = LSM_RET_DEFAULT(FUNC); \
do { \
struct security_hook_list *P; \
\
hlist_for_each_entry(P, &security_hook_heads.FUNC, list) { \
RC = P->hook.FUNC(__VA_ARGS__); \
- if (RC != 0) \
+ if (RC != LSM_RET_DEFAULT(FUNC)) \
break; \
} \
} while (0); \
@@ -728,35 +728,35 @@ static void __init lsm_early_task(struct
int security_binder_set_context_mgr(const struct cred *mgr)
{
- return call_int_hook(binder_set_context_mgr, 0, mgr);
+ return call_int_hook(binder_set_context_mgr, mgr);
}
int security_binder_transaction(const struct cred *from,
const struct cred *to)
{
- return call_int_hook(binder_transaction, 0, from, to);
+ return call_int_hook(binder_transaction, from, to);
}
int security_binder_transfer_binder(const struct cred *from,
const struct cred *to)
{
- return call_int_hook(binder_transfer_binder, 0, from, to);
+ return call_int_hook(binder_transfer_binder, from, to);
}
int security_binder_transfer_file(const struct cred *from,
const struct cred *to, struct file *file)
{
- return call_int_hook(binder_transfer_file, 0, from, to, file);
+ return call_int_hook(binder_transfer_file, from, to, file);
}
int security_ptrace_access_check(struct task_struct *child, unsigned int mode)
{
- return call_int_hook(ptrace_access_check, 0, child, mode);
+ return call_int_hook(ptrace_access_check, child, mode);
}
int security_ptrace_traceme(struct task_struct *parent)
{
- return call_int_hook(ptrace_traceme, 0, parent);
+ return call_int_hook(ptrace_traceme, parent);
}
int security_capget(struct task_struct *target,
@@ -764,7 +764,7 @@ int security_capget(struct task_struct *
kernel_cap_t *inheritable,
kernel_cap_t *permitted)
{
- return call_int_hook(capget, 0, target,
+ return call_int_hook(capget, target,
effective, inheritable, permitted);
}
@@ -773,7 +773,7 @@ int security_capset(struct cred *new, co
const kernel_cap_t *inheritable,
const kernel_cap_t *permitted)
{
- return call_int_hook(capset, 0, new, old,
+ return call_int_hook(capset, new, old,
effective, inheritable, permitted);
}
@@ -782,27 +782,27 @@ int security_capable(const struct cred *
int cap,
unsigned int opts)
{
- return call_int_hook(capable, 0, cred, ns, cap, opts);
+ return call_int_hook(capable, cred, ns, cap, opts);
}
int security_quotactl(int cmds, int type, int id, struct super_block *sb)
{
- return call_int_hook(quotactl, 0, cmds, type, id, sb);
+ return call_int_hook(quotactl, cmds, type, id, sb);
}
int security_quota_on(struct dentry *dentry)
{
- return call_int_hook(quota_on, 0, dentry);
+ return call_int_hook(quota_on, dentry);
}
int security_syslog(int type)
{
- return call_int_hook(syslog, 0, type);
+ return call_int_hook(syslog, type);
}
int security_settime64(const struct timespec64 *ts, const struct timezone *tz)
{
- return call_int_hook(settime, 0, ts, tz);
+ return call_int_hook(settime, ts, tz);
}
int security_vm_enough_memory_mm(struct mm_struct *mm, long pages)
@@ -830,19 +830,19 @@ int security_vm_enough_memory_mm(struct
int security_bprm_creds_for_exec(struct linux_binprm *bprm)
{
- return call_int_hook(bprm_creds_for_exec, 0, bprm);
+ return call_int_hook(bprm_creds_for_exec, bprm);
}
int security_bprm_creds_from_file(struct linux_binprm *bprm, struct file *file)
{
- return call_int_hook(bprm_creds_from_file, 0, bprm, file);
+ return call_int_hook(bprm_creds_from_file, bprm, file);
}
int security_bprm_check(struct linux_binprm *bprm)
{
int ret;
- ret = call_int_hook(bprm_check_security, 0, bprm);
+ ret = call_int_hook(bprm_check_security, bprm);
if (ret)
return ret;
return ima_bprm_check(bprm);
@@ -860,7 +860,7 @@ void security_bprm_committed_creds(struc
int security_fs_context_dup(struct fs_context *fc, struct fs_context *src_fc)
{
- return call_int_hook(fs_context_dup, 0, fc, src_fc);
+ return call_int_hook(fs_context_dup, fc, src_fc);
}
int security_fs_context_parse_param(struct fs_context *fc,
@@ -883,7 +883,7 @@ int security_fs_context_parse_param(stru
int security_sb_alloc(struct super_block *sb)
{
- return call_int_hook(sb_alloc_security, 0, sb);
+ return call_int_hook(sb_alloc_security, sb);
}
void security_sb_free(struct super_block *sb)
@@ -902,46 +902,46 @@ EXPORT_SYMBOL(security_free_mnt_opts);
int security_sb_eat_lsm_opts(char *options, void **mnt_opts)
{
- return call_int_hook(sb_eat_lsm_opts, 0, options, mnt_opts);
+ return call_int_hook(sb_eat_lsm_opts, options, mnt_opts);
}
EXPORT_SYMBOL(security_sb_eat_lsm_opts);
int security_sb_remount(struct super_block *sb,
void *mnt_opts)
{
- return call_int_hook(sb_remount, 0, sb, mnt_opts);
+ return call_int_hook(sb_remount, sb, mnt_opts);
}
EXPORT_SYMBOL(security_sb_remount);
int security_sb_kern_mount(struct super_block *sb)
{
- return call_int_hook(sb_kern_mount, 0, sb);
+ return call_int_hook(sb_kern_mount, sb);
}
int security_sb_show_options(struct seq_file *m, struct super_block *sb)
{
- return call_int_hook(sb_show_options, 0, m, sb);
+ return call_int_hook(sb_show_options, m, sb);
}
int security_sb_statfs(struct dentry *dentry)
{
- return call_int_hook(sb_statfs, 0, dentry);
+ return call_int_hook(sb_statfs, dentry);
}
int security_sb_mount(const char *dev_name, const struct path *path,
const char *type, unsigned long flags, void *data)
{
- return call_int_hook(sb_mount, 0, dev_name, path, type, flags, data);
+ return call_int_hook(sb_mount, dev_name, path, type, flags, data);
}
int security_sb_umount(struct vfsmount *mnt, int flags)
{
- return call_int_hook(sb_umount, 0, mnt, flags);
+ return call_int_hook(sb_umount, mnt, flags);
}
int security_sb_pivotroot(const struct path *old_path, const struct path *new_path)
{
- return call_int_hook(sb_pivotroot, 0, old_path, new_path);
+ return call_int_hook(sb_pivotroot, old_path, new_path);
}
int security_sb_set_mnt_opts(struct super_block *sb,
@@ -949,9 +949,17 @@ int security_sb_set_mnt_opts(struct supe
unsigned long kern_flags,
unsigned long *set_kern_flags)
{
- return call_int_hook(sb_set_mnt_opts,
- mnt_opts ? -EOPNOTSUPP : 0, sb,
- mnt_opts, kern_flags, set_kern_flags);
+ struct security_hook_list *hp;
+ int rc = mnt_opts ? -EOPNOTSUPP : LSM_RET_DEFAULT(sb_set_mnt_opts);
+
+ hlist_for_each_entry(hp, &security_hook_heads.sb_set_mnt_opts,
+ list) {
+ rc = hp->hook.sb_set_mnt_opts(sb, mnt_opts, kern_flags,
+ set_kern_flags);
+ if (rc != LSM_RET_DEFAULT(sb_set_mnt_opts))
+ break;
+ }
+ return rc;
}
EXPORT_SYMBOL(security_sb_set_mnt_opts);
@@ -960,7 +968,7 @@ int security_sb_clone_mnt_opts(const str
unsigned long kern_flags,
unsigned long *set_kern_flags)
{
- return call_int_hook(sb_clone_mnt_opts, 0, oldsb, newsb,
+ return call_int_hook(sb_clone_mnt_opts, oldsb, newsb,
kern_flags, set_kern_flags);
}
EXPORT_SYMBOL(security_sb_clone_mnt_opts);
@@ -968,20 +976,28 @@ EXPORT_SYMBOL(security_sb_clone_mnt_opts
int security_add_mnt_opt(const char *option, const char *val, int len,
void **mnt_opts)
{
- return call_int_hook(sb_add_mnt_opt, -EINVAL,
- option, val, len, mnt_opts);
+ struct security_hook_list *hp;
+ int rc = -EINVAL;
+
+ hlist_for_each_entry(hp, &security_hook_heads.sb_add_mnt_opt,
+ list) {
+ rc = hp->hook.sb_add_mnt_opt(option, val, len, mnt_opts);
+ if (rc != LSM_RET_DEFAULT(sb_add_mnt_opt))
+ break;
+ }
+ return rc;
}
EXPORT_SYMBOL(security_add_mnt_opt);
int security_move_mount(const struct path *from_path, const struct path *to_path)
{
- return call_int_hook(move_mount, 0, from_path, to_path);
+ return call_int_hook(move_mount, from_path, to_path);
}
int security_path_notify(const struct path *path, u64 mask,
unsigned int obj_type)
{
- return call_int_hook(path_notify, 0, path, mask, obj_type);
+ return call_int_hook(path_notify, path, mask, obj_type);
}
int security_inode_alloc(struct inode *inode)
@@ -990,7 +1006,7 @@ int security_inode_alloc(struct inode *i
if (unlikely(rc))
return rc;
- rc = call_int_hook(inode_alloc_security, 0, inode);
+ rc = call_int_hook(inode_alloc_security, inode);
if (unlikely(rc))
security_inode_free(inode);
return rc;
@@ -1026,8 +1042,17 @@ int security_dentry_init_security(struct
const struct qstr *name, void **ctx,
u32 *ctxlen)
{
- return call_int_hook(dentry_init_security, -EOPNOTSUPP, dentry, mode,
- name, ctx, ctxlen);
+ struct security_hook_list *hp;
+ int rc = -EOPNOTSUPP;
+
+ hlist_for_each_entry(hp, &security_hook_heads.dentry_init_security,
+ list) {
+ rc = hp->hook.dentry_init_security(dentry, mode, name,
+ ctx, ctxlen);
+ if (rc != LSM_RET_DEFAULT(dentry_init_security))
+ break;
+ }
+ return rc;
}
EXPORT_SYMBOL(security_dentry_init_security);
@@ -1035,7 +1060,7 @@ int security_dentry_create_files_as(stru
struct qstr *name,
const struct cred *old, struct cred *new)
{
- return call_int_hook(dentry_create_files_as, 0, dentry, mode,
+ return call_int_hook(dentry_create_files_as, dentry, mode,
name, old, new);
}
EXPORT_SYMBOL(security_dentry_create_files_as);
@@ -1046,20 +1071,35 @@ int security_inode_init_security(struct
{
struct xattr new_xattrs[MAX_LSM_EVM_XATTR + 1];
struct xattr *lsm_xattr, *evm_xattr, *xattr;
+ struct security_hook_list *hp;
int ret;
if (unlikely(IS_PRIVATE(inode)))
return 0;
- if (!initxattrs)
- return call_int_hook(inode_init_security, -EOPNOTSUPP, inode,
- dir, qstr, NULL, NULL, NULL);
+ if (!initxattrs) {
+ ret = -EOPNOTSUPP;
+ hlist_for_each_entry(hp, &security_hook_heads.inode_init_security,
+ list) {
+ ret = hp->hook.inode_init_security(inode, dir, qstr,
+ NULL, NULL, NULL);
+ if (ret != LSM_RET_DEFAULT(inode_init_security))
+ break;
+ }
+ return ret;
+ }
memset(new_xattrs, 0, sizeof(new_xattrs));
lsm_xattr = new_xattrs;
- ret = call_int_hook(inode_init_security, -EOPNOTSUPP, inode, dir, qstr,
- &lsm_xattr->name,
- &lsm_xattr->value,
- &lsm_xattr->value_len);
+ ret = -EOPNOTSUPP;
+ hlist_for_each_entry(hp, &security_hook_heads.inode_init_security,
+ list) {
+ ret = hp->hook.inode_init_security(inode, dir, qstr,
+ &lsm_xattr->name,
+ &lsm_xattr->value,
+ &lsm_xattr->value_len);
+ if (ret != LSM_RET_DEFAULT(inode_init_security))
+ break;
+ }
if (ret)
goto out;
@@ -1079,10 +1119,19 @@ int security_old_inode_init_security(str
const struct qstr *qstr, const char **name,
void **value, size_t *len)
{
+ struct security_hook_list *hp;
+ int rc = -EOPNOTSUPP;
+
if (unlikely(IS_PRIVATE(inode)))
return -EOPNOTSUPP;
- return call_int_hook(inode_init_security, -EOPNOTSUPP, inode, dir,
- qstr, name, value, len);
+ hlist_for_each_entry(hp, &security_hook_heads.inode_init_security,
+ list) {
+ rc = hp->hook.inode_init_security(inode, dir, qstr, name,
+ value, len);
+ if (rc != LSM_RET_DEFAULT(inode_init_security))
+ break;
+ }
+ return rc;
}
EXPORT_SYMBOL(security_old_inode_init_security);
@@ -1092,7 +1141,7 @@ int security_path_mknod(const struct pat
{
if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
return 0;
- return call_int_hook(path_mknod, 0, dir, dentry, mode, dev);
+ return call_int_hook(path_mknod, dir, dentry, mode, dev);
}
EXPORT_SYMBOL(security_path_mknod);
@@ -1100,7 +1149,7 @@ int security_path_mkdir(const struct pat
{
if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
return 0;
- return call_int_hook(path_mkdir, 0, dir, dentry, mode);
+ return call_int_hook(path_mkdir, dir, dentry, mode);
}
EXPORT_SYMBOL(security_path_mkdir);
@@ -1108,14 +1157,14 @@ int security_path_rmdir(const struct pat
{
if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
return 0;
- return call_int_hook(path_rmdir, 0, dir, dentry);
+ return call_int_hook(path_rmdir, dir, dentry);
}
int security_path_unlink(const struct path *dir, struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
return 0;
- return call_int_hook(path_unlink, 0, dir, dentry);
+ return call_int_hook(path_unlink, dir, dentry);
}
EXPORT_SYMBOL(security_path_unlink);
@@ -1124,7 +1173,7 @@ int security_path_symlink(const struct p
{
if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry))))
return 0;
- return call_int_hook(path_symlink, 0, dir, dentry, old_name);
+ return call_int_hook(path_symlink, dir, dentry, old_name);
}
int security_path_link(struct dentry *old_dentry, const struct path *new_dir,
@@ -1132,7 +1181,7 @@ int security_path_link(struct dentry *ol
{
if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
return 0;
- return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry);
+ return call_int_hook(path_link, old_dentry, new_dir, new_dentry);
}
int security_path_rename(const struct path *old_dir, struct dentry *old_dentry,
@@ -1144,13 +1193,13 @@ int security_path_rename(const struct pa
return 0;
if (flags & RENAME_EXCHANGE) {
- int err = call_int_hook(path_rename, 0, new_dir, new_dentry,
+ int err = call_int_hook(path_rename, new_dir, new_dentry,
old_dir, old_dentry);
if (err)
return err;
}
- return call_int_hook(path_rename, 0, old_dir, old_dentry, new_dir,
+ return call_int_hook(path_rename, old_dir, old_dentry, new_dir,
new_dentry);
}
EXPORT_SYMBOL(security_path_rename);
@@ -1159,26 +1208,26 @@ int security_path_truncate(const struct
{
if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
return 0;
- return call_int_hook(path_truncate, 0, path);
+ return call_int_hook(path_truncate, path);
}
int security_path_chmod(const struct path *path, umode_t mode)
{
if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
return 0;
- return call_int_hook(path_chmod, 0, path, mode);
+ return call_int_hook(path_chmod, path, mode);
}
int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid)
{
if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
return 0;
- return call_int_hook(path_chown, 0, path, uid, gid);
+ return call_int_hook(path_chown, path, uid, gid);
}
int security_path_chroot(const struct path *path)
{
- return call_int_hook(path_chroot, 0, path);
+ return call_int_hook(path_chroot, path);
}
#endif
@@ -1186,7 +1235,7 @@ int security_inode_create(struct inode *
{
if (unlikely(IS_PRIVATE(dir)))
return 0;
- return call_int_hook(inode_create, 0, dir, dentry, mode);
+ return call_int_hook(inode_create, dir, dentry, mode);
}
EXPORT_SYMBOL_GPL(security_inode_create);
@@ -1195,14 +1244,14 @@ int security_inode_link(struct dentry *o
{
if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry))))
return 0;
- return call_int_hook(inode_link, 0, old_dentry, dir, new_dentry);
+ return call_int_hook(inode_link, old_dentry, dir, new_dentry);
}
int security_inode_unlink(struct inode *dir, struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
return 0;
- return call_int_hook(inode_unlink, 0, dir, dentry);
+ return call_int_hook(inode_unlink, dir, dentry);
}
int security_inode_symlink(struct inode *dir, struct dentry *dentry,
@@ -1210,14 +1259,14 @@ int security_inode_symlink(struct inode
{
if (unlikely(IS_PRIVATE(dir)))
return 0;
- return call_int_hook(inode_symlink, 0, dir, dentry, old_name);
+ return call_int_hook(inode_symlink, dir, dentry, old_name);
}
int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{
if (unlikely(IS_PRIVATE(dir)))
return 0;
- return call_int_hook(inode_mkdir, 0, dir, dentry, mode);
+ return call_int_hook(inode_mkdir, dir, dentry, mode);
}
EXPORT_SYMBOL_GPL(security_inode_mkdir);
@@ -1225,14 +1274,14 @@ int security_inode_rmdir(struct inode *d
{
if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
return 0;
- return call_int_hook(inode_rmdir, 0, dir, dentry);
+ return call_int_hook(inode_rmdir, dir, dentry);
}
int security_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
{
if (unlikely(IS_PRIVATE(dir)))
return 0;
- return call_int_hook(inode_mknod, 0, dir, dentry, mode, dev);
+ return call_int_hook(inode_mknod, dir, dentry, mode, dev);
}
int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
@@ -1244,13 +1293,13 @@ int security_inode_rename(struct inode *
return 0;
if (flags & RENAME_EXCHANGE) {
- int err = call_int_hook(inode_rename, 0, new_dir, new_dentry,
+ int err = call_int_hook(inode_rename, new_dir, new_dentry,
old_dir, old_dentry);
if (err)
return err;
}
- return call_int_hook(inode_rename, 0, old_dir, old_dentry,
+ return call_int_hook(inode_rename, old_dir, old_dentry,
new_dir, new_dentry);
}
@@ -1258,7 +1307,7 @@ int security_inode_readlink(struct dentr
{
if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
return 0;
- return call_int_hook(inode_readlink, 0, dentry);
+ return call_int_hook(inode_readlink, dentry);
}
int security_inode_follow_link(struct dentry *dentry, struct inode *inode,
@@ -1266,14 +1315,14 @@ int security_inode_follow_link(struct de
{
if (unlikely(IS_PRIVATE(inode)))
return 0;
- return call_int_hook(inode_follow_link, 0, dentry, inode, rcu);
+ return call_int_hook(inode_follow_link, dentry, inode, rcu);
}
int security_inode_permission(struct inode *inode, int mask)
{
if (unlikely(IS_PRIVATE(inode)))
return 0;
- return call_int_hook(inode_permission, 0, inode, mask);
+ return call_int_hook(inode_permission, inode, mask);
}
int security_inode_setattr(struct dentry *dentry, struct iattr *attr)
@@ -1282,7 +1331,7 @@ int security_inode_setattr(struct dentry
if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
return 0;
- ret = call_int_hook(inode_setattr, 0, dentry, attr);
+ ret = call_int_hook(inode_setattr, dentry, attr);
if (ret)
return ret;
return evm_inode_setattr(dentry, attr);
@@ -1293,12 +1342,13 @@ int security_inode_getattr(const struct
{
if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry))))
return 0;
- return call_int_hook(inode_getattr, 0, path);
+ return call_int_hook(inode_getattr, path);
}
int security_inode_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
+ struct security_hook_list *hp;
int ret;
if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
@@ -1307,8 +1357,14 @@ int security_inode_setxattr(struct dentr
* SELinux and Smack integrate the cap call,
* so assume that all LSMs supplying this call do so.
*/
- ret = call_int_hook(inode_setxattr, 1, dentry, name, value, size,
- flags);
+ ret = 1;
+ hlist_for_each_entry(hp, &security_hook_heads.inode_setxattr,
+ list) {
+ ret = hp->hook.inode_setxattr(dentry, name, value, size,
+ flags);
+ if (ret != LSM_RET_DEFAULT(inode_setxattr))
+ break;
+ }
if (ret == 1)
ret = cap_inode_setxattr(dentry, name, value, size, flags);
@@ -1333,18 +1389,19 @@ int security_inode_getxattr(struct dentr
{
if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
return 0;
- return call_int_hook(inode_getxattr, 0, dentry, name);
+ return call_int_hook(inode_getxattr, dentry, name);
}
int security_inode_listxattr(struct dentry *dentry)
{
if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
return 0;
- return call_int_hook(inode_listxattr, 0, dentry);
+ return call_int_hook(inode_listxattr, dentry);
}
int security_inode_removexattr(struct dentry *dentry, const char *name)
{
+ struct security_hook_list *hp;
int ret;
if (unlikely(IS_PRIVATE(d_backing_inode(dentry))))
@@ -1353,7 +1410,13 @@ int security_inode_removexattr(struct de
* SELinux and Smack integrate the cap call,
* so assume that all LSMs supplying this call do so.
*/
- ret = call_int_hook(inode_removexattr, 1, dentry, name);
+ ret = 1;
+ hlist_for_each_entry(hp, &security_hook_heads.inode_removexattr,
+ list) {
+ ret = hp->hook.inode_removexattr(dentry, name);
+ if (ret != LSM_RET_DEFAULT(inode_removexattr))
+ break;
+ }
if (ret == 1)
ret = cap_inode_removexattr(dentry, name);
if (ret)
@@ -1366,12 +1429,12 @@ int security_inode_removexattr(struct de
int security_inode_need_killpriv(struct dentry *dentry)
{
- return call_int_hook(inode_need_killpriv, 0, dentry);
+ return call_int_hook(inode_need_killpriv, dentry);
}
int security_inode_killpriv(struct dentry *dentry)
{
- return call_int_hook(inode_killpriv, 0, dentry);
+ return call_int_hook(inode_killpriv, dentry);
}
int security_inode_getsecurity(struct inode *inode, const char *name, void **buffer, bool alloc)
@@ -1415,7 +1478,7 @@ int security_inode_listsecurity(struct i
{
if (unlikely(IS_PRIVATE(inode)))
return 0;
- return call_int_hook(inode_listsecurity, 0, inode, buffer, buffer_size);
+ return call_int_hook(inode_listsecurity, inode, buffer, buffer_size);
}
EXPORT_SYMBOL(security_inode_listsecurity);
@@ -1426,7 +1489,7 @@ void security_inode_getsecid(struct inod
int security_inode_copy_up(struct dentry *src, struct cred **new)
{
- return call_int_hook(inode_copy_up, 0, src, new);
+ return call_int_hook(inode_copy_up, src, new);
}
EXPORT_SYMBOL(security_inode_copy_up);
@@ -1454,14 +1517,14 @@ EXPORT_SYMBOL(security_inode_copy_up_xat
int security_kernfs_init_security(struct kernfs_node *kn_dir,
struct kernfs_node *kn)
{
- return call_int_hook(kernfs_init_security, 0, kn_dir, kn);
+ return call_int_hook(kernfs_init_security, kn_dir, kn);
}
int security_file_permission(struct file *file, int mask)
{
int ret;
- ret = call_int_hook(file_permission, 0, file, mask);
+ ret = call_int_hook(file_permission, file, mask);
if (ret)
return ret;
@@ -1474,7 +1537,7 @@ int security_file_alloc(struct file *fil
if (rc)
return rc;
- rc = call_int_hook(file_alloc_security, 0, file);
+ rc = call_int_hook(file_alloc_security, file);
if (unlikely(rc))
security_file_free(file);
return rc;
@@ -1495,7 +1558,7 @@ void security_file_free(struct file *fil
int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- return call_int_hook(file_ioctl, 0, file, cmd, arg);
+ return call_int_hook(file_ioctl, file, cmd, arg);
}
EXPORT_SYMBOL_GPL(security_file_ioctl);
@@ -1513,7 +1576,7 @@ EXPORT_SYMBOL_GPL(security_file_ioctl);
int security_file_ioctl_compat(struct file *file, unsigned int cmd,
unsigned long arg)
{
- return call_int_hook(file_ioctl_compat, 0, file, cmd, arg);
+ return call_int_hook(file_ioctl_compat, file, cmd, arg);
}
EXPORT_SYMBOL_GPL(security_file_ioctl_compat);
@@ -1556,7 +1619,7 @@ int security_mmap_file(struct file *file
unsigned long prot_adj = mmap_prot(file, prot);
int ret;
- ret = call_int_hook(mmap_file, 0, file, prot, prot_adj, flags);
+ ret = call_int_hook(mmap_file, file, prot, prot_adj, flags);
if (ret)
return ret;
return ima_file_mmap(file, prot, prot_adj, flags);
@@ -1564,7 +1627,7 @@ int security_mmap_file(struct file *file
int security_mmap_addr(unsigned long addr)
{
- return call_int_hook(mmap_addr, 0, addr);
+ return call_int_hook(mmap_addr, addr);
}
int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
@@ -1572,7 +1635,7 @@ int security_file_mprotect(struct vm_are
{
int ret;
- ret = call_int_hook(file_mprotect, 0, vma, reqprot, prot);
+ ret = call_int_hook(file_mprotect, vma, reqprot, prot);
if (ret)
return ret;
return ima_file_mprotect(vma, prot);
@@ -1580,12 +1643,12 @@ int security_file_mprotect(struct vm_are
int security_file_lock(struct file *file, unsigned int cmd)
{
- return call_int_hook(file_lock, 0, file, cmd);
+ return call_int_hook(file_lock, file, cmd);
}
int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
{
- return call_int_hook(file_fcntl, 0, file, cmd, arg);
+ return call_int_hook(file_fcntl, file, cmd, arg);
}
void security_file_set_fowner(struct file *file)
@@ -1596,19 +1659,19 @@ void security_file_set_fowner(struct fil
int security_file_send_sigiotask(struct task_struct *tsk,
struct fown_struct *fown, int sig)
{
- return call_int_hook(file_send_sigiotask, 0, tsk, fown, sig);
+ return call_int_hook(file_send_sigiotask, tsk, fown, sig);
}
int security_file_receive(struct file *file)
{
- return call_int_hook(file_receive, 0, file);
+ return call_int_hook(file_receive, file);
}
int security_file_open(struct file *file)
{
int ret;
- ret = call_int_hook(file_open, 0, file);
+ ret = call_int_hook(file_open, file);
if (ret)
return ret;
@@ -1621,7 +1684,7 @@ int security_task_alloc(struct task_stru
if (rc)
return rc;
- rc = call_int_hook(task_alloc, 0, task, clone_flags);
+ rc = call_int_hook(task_alloc, task, clone_flags);
if (unlikely(rc))
security_task_free(task);
return rc;
@@ -1642,7 +1705,7 @@ int security_cred_alloc_blank(struct cre
if (rc)
return rc;
- rc = call_int_hook(cred_alloc_blank, 0, cred, gfp);
+ rc = call_int_hook(cred_alloc_blank, cred, gfp);
if (unlikely(rc))
security_cred_free(cred);
return rc;
@@ -1670,7 +1733,7 @@ int security_prepare_creds(struct cred *
if (rc)
return rc;
- rc = call_int_hook(cred_prepare, 0, new, old, gfp);
+ rc = call_int_hook(cred_prepare, new, old, gfp);
if (unlikely(rc))
security_cred_free(new);
return rc;
@@ -1690,19 +1753,19 @@ EXPORT_SYMBOL(security_cred_getsecid);
int security_kernel_act_as(struct cred *new, u32 secid)
{
- return call_int_hook(kernel_act_as, 0, new, secid);
+ return call_int_hook(kernel_act_as, new, secid);
}
int security_kernel_create_files_as(struct cred *new, struct inode *inode)
{
- return call_int_hook(kernel_create_files_as, 0, new, inode);
+ return call_int_hook(kernel_create_files_as, new, inode);
}
int security_kernel_module_request(char *kmod_name)
{
int ret;
- ret = call_int_hook(kernel_module_request, 0, kmod_name);
+ ret = call_int_hook(kernel_module_request, kmod_name);
if (ret)
return ret;
return integrity_kernel_module_request(kmod_name);
@@ -1713,7 +1776,7 @@ int security_kernel_read_file(struct fil
{
int ret;
- ret = call_int_hook(kernel_read_file, 0, file, id, contents);
+ ret = call_int_hook(kernel_read_file, file, id, contents);
if (ret)
return ret;
return ima_read_file(file, id, contents);
@@ -1725,7 +1788,7 @@ int security_kernel_post_read_file(struc
{
int ret;
- ret = call_int_hook(kernel_post_read_file, 0, file, buf, size, id);
+ ret = call_int_hook(kernel_post_read_file, file, buf, size, id);
if (ret)
return ret;
return ima_post_read_file(file, buf, size, id);
@@ -1736,7 +1799,7 @@ int security_kernel_load_data(enum kerne
{
int ret;
- ret = call_int_hook(kernel_load_data, 0, id, contents);
+ ret = call_int_hook(kernel_load_data, id, contents);
if (ret)
return ret;
return ima_load_data(id, contents);
@@ -1749,7 +1812,7 @@ int security_kernel_post_load_data(char
{
int ret;
- ret = call_int_hook(kernel_post_load_data, 0, buf, size, id,
+ ret = call_int_hook(kernel_post_load_data, buf, size, id,
description);
if (ret)
return ret;
@@ -1760,28 +1823,28 @@ EXPORT_SYMBOL_GPL(security_kernel_post_l
int security_task_fix_setuid(struct cred *new, const struct cred *old,
int flags)
{
- return call_int_hook(task_fix_setuid, 0, new, old, flags);
+ return call_int_hook(task_fix_setuid, new, old, flags);
}
int security_task_fix_setgid(struct cred *new, const struct cred *old,
int flags)
{
- return call_int_hook(task_fix_setgid, 0, new, old, flags);
+ return call_int_hook(task_fix_setgid, new, old, flags);
}
int security_task_setpgid(struct task_struct *p, pid_t pgid)
{
- return call_int_hook(task_setpgid, 0, p, pgid);
+ return call_int_hook(task_setpgid, p, pgid);
}
int security_task_getpgid(struct task_struct *p)
{
- return call_int_hook(task_getpgid, 0, p);
+ return call_int_hook(task_getpgid, p);
}
int security_task_getsid(struct task_struct *p)
{
- return call_int_hook(task_getsid, 0, p);
+ return call_int_hook(task_getsid, p);
}
void security_task_getsecid(struct task_struct *p, u32 *secid)
@@ -1793,50 +1856,50 @@ EXPORT_SYMBOL(security_task_getsecid);
int security_task_setnice(struct task_struct *p, int nice)
{
- return call_int_hook(task_setnice, 0, p, nice);
+ return call_int_hook(task_setnice, p, nice);
}
int security_task_setioprio(struct task_struct *p, int ioprio)
{
- return call_int_hook(task_setioprio, 0, p, ioprio);
+ return call_int_hook(task_setioprio, p, ioprio);
}
int security_task_getioprio(struct task_struct *p)
{
- return call_int_hook(task_getioprio, 0, p);
+ return call_int_hook(task_getioprio, p);
}
int security_task_prlimit(const struct cred *cred, const struct cred *tcred,
unsigned int flags)
{
- return call_int_hook(task_prlimit, 0, cred, tcred, flags);
+ return call_int_hook(task_prlimit, cred, tcred, flags);
}
int security_task_setrlimit(struct task_struct *p, unsigned int resource,
struct rlimit *new_rlim)
{
- return call_int_hook(task_setrlimit, 0, p, resource, new_rlim);
+ return call_int_hook(task_setrlimit, p, resource, new_rlim);
}
int security_task_setscheduler(struct task_struct *p)
{
- return call_int_hook(task_setscheduler, 0, p);
+ return call_int_hook(task_setscheduler, p);
}
int security_task_getscheduler(struct task_struct *p)
{
- return call_int_hook(task_getscheduler, 0, p);
+ return call_int_hook(task_getscheduler, p);
}
int security_task_movememory(struct task_struct *p)
{
- return call_int_hook(task_movememory, 0, p);
+ return call_int_hook(task_movememory, p);
}
int security_task_kill(struct task_struct *p, struct kernel_siginfo *info,
int sig, const struct cred *cred)
{
- return call_int_hook(task_kill, 0, p, info, sig, cred);
+ return call_int_hook(task_kill, p, info, sig, cred);
}
int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
@@ -1864,7 +1927,7 @@ void security_task_to_inode(struct task_
int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag)
{
- return call_int_hook(ipc_permission, 0, ipcp, flag);
+ return call_int_hook(ipc_permission, ipcp, flag);
}
void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
@@ -1879,7 +1942,7 @@ int security_msg_msg_alloc(struct msg_ms
if (unlikely(rc))
return rc;
- rc = call_int_hook(msg_msg_alloc_security, 0, msg);
+ rc = call_int_hook(msg_msg_alloc_security, msg);
if (unlikely(rc))
security_msg_msg_free(msg);
return rc;
@@ -1898,7 +1961,7 @@ int security_msg_queue_alloc(struct kern
if (unlikely(rc))
return rc;
- rc = call_int_hook(msg_queue_alloc_security, 0, msq);
+ rc = call_int_hook(msg_queue_alloc_security, msq);
if (unlikely(rc))
security_msg_queue_free(msq);
return rc;
@@ -1913,24 +1976,24 @@ void security_msg_queue_free(struct kern
int security_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg)
{
- return call_int_hook(msg_queue_associate, 0, msq, msqflg);
+ return call_int_hook(msg_queue_associate, msq, msqflg);
}
int security_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd)
{
- return call_int_hook(msg_queue_msgctl, 0, msq, cmd);
+ return call_int_hook(msg_queue_msgctl, msq, cmd);
}
int security_msg_queue_msgsnd(struct kern_ipc_perm *msq,
struct msg_msg *msg, int msqflg)
{
- return call_int_hook(msg_queue_msgsnd, 0, msq, msg, msqflg);
+ return call_int_hook(msg_queue_msgsnd, msq, msg, msqflg);
}
int security_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg,
struct task_struct *target, long type, int mode)
{
- return call_int_hook(msg_queue_msgrcv, 0, msq, msg, target, type, mode);
+ return call_int_hook(msg_queue_msgrcv, msq, msg, target, type, mode);
}
int security_shm_alloc(struct kern_ipc_perm *shp)
@@ -1939,7 +2002,7 @@ int security_shm_alloc(struct kern_ipc_p
if (unlikely(rc))
return rc;
- rc = call_int_hook(shm_alloc_security, 0, shp);
+ rc = call_int_hook(shm_alloc_security, shp);
if (unlikely(rc))
security_shm_free(shp);
return rc;
@@ -1954,17 +2017,17 @@ void security_shm_free(struct kern_ipc_p
int security_shm_associate(struct kern_ipc_perm *shp, int shmflg)
{
- return call_int_hook(shm_associate, 0, shp, shmflg);
+ return call_int_hook(shm_associate, shp, shmflg);
}
int security_shm_shmctl(struct kern_ipc_perm *shp, int cmd)
{
- return call_int_hook(shm_shmctl, 0, shp, cmd);
+ return call_int_hook(shm_shmctl, shp, cmd);
}
int security_shm_shmat(struct kern_ipc_perm *shp, char __user *shmaddr, int shmflg)
{
- return call_int_hook(shm_shmat, 0, shp, shmaddr, shmflg);
+ return call_int_hook(shm_shmat, shp, shmaddr, shmflg);
}
int security_sem_alloc(struct kern_ipc_perm *sma)
@@ -1973,7 +2036,7 @@ int security_sem_alloc(struct kern_ipc_p
if (unlikely(rc))
return rc;
- rc = call_int_hook(sem_alloc_security, 0, sma);
+ rc = call_int_hook(sem_alloc_security, sma);
if (unlikely(rc))
security_sem_free(sma);
return rc;
@@ -1988,18 +2051,18 @@ void security_sem_free(struct kern_ipc_p
int security_sem_associate(struct kern_ipc_perm *sma, int semflg)
{
- return call_int_hook(sem_associate, 0, sma, semflg);
+ return call_int_hook(sem_associate, sma, semflg);
}
int security_sem_semctl(struct kern_ipc_perm *sma, int cmd)
{
- return call_int_hook(sem_semctl, 0, sma, cmd);
+ return call_int_hook(sem_semctl, sma, cmd);
}
int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops,
unsigned nsops, int alter)
{
- return call_int_hook(sem_semop, 0, sma, sops, nsops, alter);
+ return call_int_hook(sem_semop, sma, sops, nsops, alter);
}
void security_d_instantiate(struct dentry *dentry, struct inode *inode)
@@ -2038,12 +2101,12 @@ int security_setprocattr(const char *lsm
int security_netlink_send(struct sock *sk, struct sk_buff *skb)
{
- return call_int_hook(netlink_send, 0, sk, skb);
+ return call_int_hook(netlink_send, sk, skb);
}
int security_ismaclabel(const char *name)
{
- return call_int_hook(ismaclabel, 0, name);
+ return call_int_hook(ismaclabel, name);
}
EXPORT_SYMBOL(security_ismaclabel);
@@ -2069,7 +2132,7 @@ EXPORT_SYMBOL(security_secid_to_secctx);
int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
{
*secid = 0;
- return call_int_hook(secctx_to_secid, 0, secdata, seclen, secid);
+ return call_int_hook(secctx_to_secid, secdata, seclen, secid);
}
EXPORT_SYMBOL(security_secctx_to_secid);
@@ -2087,13 +2150,13 @@ EXPORT_SYMBOL(security_inode_invalidate_
int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
{
- return call_int_hook(inode_notifysecctx, 0, inode, ctx, ctxlen);
+ return call_int_hook(inode_notifysecctx, inode, ctx, ctxlen);
}
EXPORT_SYMBOL(security_inode_notifysecctx);
int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
{
- return call_int_hook(inode_setsecctx, 0, dentry, ctx, ctxlen);
+ return call_int_hook(inode_setsecctx, dentry, ctx, ctxlen);
}
EXPORT_SYMBOL(security_inode_setsecctx);
@@ -2120,14 +2183,14 @@ int security_post_notification(const str
const struct cred *cred,
struct watch_notification *n)
{
- return call_int_hook(post_notification, 0, w_cred, cred, n);
+ return call_int_hook(post_notification, w_cred, cred, n);
}
#endif /* CONFIG_WATCH_QUEUE */
#ifdef CONFIG_KEY_NOTIFICATIONS
int security_watch_key(struct key *key)
{
- return call_int_hook(watch_key, 0, key);
+ return call_int_hook(watch_key, key);
}
#endif
@@ -2135,93 +2198,93 @@ int security_watch_key(struct key *key)
int security_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk)
{
- return call_int_hook(unix_stream_connect, 0, sock, other, newsk);
+ return call_int_hook(unix_stream_connect, sock, other, newsk);
}
EXPORT_SYMBOL(security_unix_stream_connect);
int security_unix_may_send(struct socket *sock, struct socket *other)
{
- return call_int_hook(unix_may_send, 0, sock, other);
+ return call_int_hook(unix_may_send, sock, other);
}
EXPORT_SYMBOL(security_unix_may_send);
int security_socket_create(int family, int type, int protocol, int kern)
{
- return call_int_hook(socket_create, 0, family, type, protocol, kern);
+ return call_int_hook(socket_create, family, type, protocol, kern);
}
int security_socket_post_create(struct socket *sock, int family,
int type, int protocol, int kern)
{
- return call_int_hook(socket_post_create, 0, sock, family, type,
+ return call_int_hook(socket_post_create, sock, family, type,
protocol, kern);
}
int security_socket_socketpair(struct socket *socka, struct socket *sockb)
{
- return call_int_hook(socket_socketpair, 0, socka, sockb);
+ return call_int_hook(socket_socketpair, socka, sockb);
}
EXPORT_SYMBOL(security_socket_socketpair);
int security_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
{
- return call_int_hook(socket_bind, 0, sock, address, addrlen);
+ return call_int_hook(socket_bind, sock, address, addrlen);
}
int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen)
{
- return call_int_hook(socket_connect, 0, sock, address, addrlen);
+ return call_int_hook(socket_connect, sock, address, addrlen);
}
int security_socket_listen(struct socket *sock, int backlog)
{
- return call_int_hook(socket_listen, 0, sock, backlog);
+ return call_int_hook(socket_listen, sock, backlog);
}
int security_socket_accept(struct socket *sock, struct socket *newsock)
{
- return call_int_hook(socket_accept, 0, sock, newsock);
+ return call_int_hook(socket_accept, sock, newsock);
}
int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size)
{
- return call_int_hook(socket_sendmsg, 0, sock, msg, size);
+ return call_int_hook(socket_sendmsg, sock, msg, size);
}
int security_socket_recvmsg(struct socket *sock, struct msghdr *msg,
int size, int flags)
{
- return call_int_hook(socket_recvmsg, 0, sock, msg, size, flags);
+ return call_int_hook(socket_recvmsg, sock, msg, size, flags);
}
int security_socket_getsockname(struct socket *sock)
{
- return call_int_hook(socket_getsockname, 0, sock);
+ return call_int_hook(socket_getsockname, sock);
}
int security_socket_getpeername(struct socket *sock)
{
- return call_int_hook(socket_getpeername, 0, sock);
+ return call_int_hook(socket_getpeername, sock);
}
int security_socket_getsockopt(struct socket *sock, int level, int optname)
{
- return call_int_hook(socket_getsockopt, 0, sock, level, optname);
+ return call_int_hook(socket_getsockopt, sock, level, optname);
}
int security_socket_setsockopt(struct socket *sock, int level, int optname)
{
- return call_int_hook(socket_setsockopt, 0, sock, level, optname);
+ return call_int_hook(socket_setsockopt, sock, level, optname);
}
int security_socket_shutdown(struct socket *sock, int how)
{
- return call_int_hook(socket_shutdown, 0, sock, how);
+ return call_int_hook(socket_shutdown, sock, how);
}
int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
- return call_int_hook(socket_sock_rcv_skb, 0, sk, skb);
+ return call_int_hook(socket_sock_rcv_skb, sk, skb);
}
EXPORT_SYMBOL(security_sock_rcv_skb);
@@ -2264,7 +2327,7 @@ EXPORT_SYMBOL(security_socket_getpeersec
int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
{
- return call_int_hook(sk_alloc_security, 0, sk, family, priority);
+ return call_int_hook(sk_alloc_security, sk, family, priority);
}
void security_sk_free(struct sock *sk)
@@ -2300,7 +2363,7 @@ EXPORT_SYMBOL(security_sock_graft);
int security_inet_conn_request(struct sock *sk,
struct sk_buff *skb, struct request_sock *req)
{
- return call_int_hook(inet_conn_request, 0, sk, skb, req);
+ return call_int_hook(inet_conn_request, sk, skb, req);
}
EXPORT_SYMBOL(security_inet_conn_request);
@@ -2319,7 +2382,7 @@ EXPORT_SYMBOL(security_inet_conn_establi
int security_secmark_relabel_packet(u32 secid)
{
- return call_int_hook(secmark_relabel_packet, 0, secid);
+ return call_int_hook(secmark_relabel_packet, secid);
}
EXPORT_SYMBOL(security_secmark_relabel_packet);
@@ -2337,7 +2400,7 @@ EXPORT_SYMBOL(security_secmark_refcount_
int security_tun_dev_alloc_security(void **security)
{
- return call_int_hook(tun_dev_alloc_security, 0, security);
+ return call_int_hook(tun_dev_alloc_security, security);
}
EXPORT_SYMBOL(security_tun_dev_alloc_security);
@@ -2349,38 +2412,38 @@ EXPORT_SYMBOL(security_tun_dev_free_secu
int security_tun_dev_create(void)
{
- return call_int_hook(tun_dev_create, 0);
+ return call_int_hook(tun_dev_create);
}
EXPORT_SYMBOL(security_tun_dev_create);
int security_tun_dev_attach_queue(void *security)
{
- return call_int_hook(tun_dev_attach_queue, 0, security);
+ return call_int_hook(tun_dev_attach_queue, security);
}
EXPORT_SYMBOL(security_tun_dev_attach_queue);
int security_tun_dev_attach(struct sock *sk, void *security)
{
- return call_int_hook(tun_dev_attach, 0, sk, security);
+ return call_int_hook(tun_dev_attach, sk, security);
}
EXPORT_SYMBOL(security_tun_dev_attach);
int security_tun_dev_open(void *security)
{
- return call_int_hook(tun_dev_open, 0, security);
+ return call_int_hook(tun_dev_open, security);
}
EXPORT_SYMBOL(security_tun_dev_open);
int security_sctp_assoc_request(struct sctp_endpoint *ep, struct sk_buff *skb)
{
- return call_int_hook(sctp_assoc_request, 0, ep, skb);
+ return call_int_hook(sctp_assoc_request, ep, skb);
}
EXPORT_SYMBOL(security_sctp_assoc_request);
int security_sctp_bind_connect(struct sock *sk, int optname,
struct sockaddr *address, int addrlen)
{
- return call_int_hook(sctp_bind_connect, 0, sk, optname,
+ return call_int_hook(sctp_bind_connect, sk, optname,
address, addrlen);
}
EXPORT_SYMBOL(security_sctp_bind_connect);
@@ -2398,19 +2461,19 @@ EXPORT_SYMBOL(security_sctp_sk_clone);
int security_ib_pkey_access(void *sec, u64 subnet_prefix, u16 pkey)
{
- return call_int_hook(ib_pkey_access, 0, sec, subnet_prefix, pkey);
+ return call_int_hook(ib_pkey_access, sec, subnet_prefix, pkey);
}
EXPORT_SYMBOL(security_ib_pkey_access);
int security_ib_endport_manage_subnet(void *sec, const char *dev_name, u8 port_num)
{
- return call_int_hook(ib_endport_manage_subnet, 0, sec, dev_name, port_num);
+ return call_int_hook(ib_endport_manage_subnet, sec, dev_name, port_num);
}
EXPORT_SYMBOL(security_ib_endport_manage_subnet);
int security_ib_alloc_security(void **sec)
{
- return call_int_hook(ib_alloc_security, 0, sec);
+ return call_int_hook(ib_alloc_security, sec);
}
EXPORT_SYMBOL(security_ib_alloc_security);
@@ -2427,14 +2490,14 @@ int security_xfrm_policy_alloc(struct xf
struct xfrm_user_sec_ctx *sec_ctx,
gfp_t gfp)
{
- return call_int_hook(xfrm_policy_alloc_security, 0, ctxp, sec_ctx, gfp);
+ return call_int_hook(xfrm_policy_alloc_security, ctxp, sec_ctx, gfp);
}
EXPORT_SYMBOL(security_xfrm_policy_alloc);
int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
struct xfrm_sec_ctx **new_ctxp)
{
- return call_int_hook(xfrm_policy_clone_security, 0, old_ctx, new_ctxp);
+ return call_int_hook(xfrm_policy_clone_security, old_ctx, new_ctxp);
}
void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx)
@@ -2445,25 +2508,25 @@ EXPORT_SYMBOL(security_xfrm_policy_free)
int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx)
{
- return call_int_hook(xfrm_policy_delete_security, 0, ctx);
+ return call_int_hook(xfrm_policy_delete_security, ctx);
}
int security_xfrm_state_alloc(struct xfrm_state *x,
struct xfrm_user_sec_ctx *sec_ctx)
{
- return call_int_hook(xfrm_state_alloc, 0, x, sec_ctx);
+ return call_int_hook(xfrm_state_alloc, x, sec_ctx);
}
EXPORT_SYMBOL(security_xfrm_state_alloc);
int security_xfrm_state_alloc_acquire(struct xfrm_state *x,
struct xfrm_sec_ctx *polsec, u32 secid)
{
- return call_int_hook(xfrm_state_alloc_acquire, 0, x, polsec, secid);
+ return call_int_hook(xfrm_state_alloc_acquire, x, polsec, secid);
}
int security_xfrm_state_delete(struct xfrm_state *x)
{
- return call_int_hook(xfrm_state_delete_security, 0, x);
+ return call_int_hook(xfrm_state_delete_security, x);
}
EXPORT_SYMBOL(security_xfrm_state_delete);
@@ -2474,7 +2537,7 @@ void security_xfrm_state_free(struct xfr
int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir)
{
- return call_int_hook(xfrm_policy_lookup, 0, ctx, fl_secid, dir);
+ return call_int_hook(xfrm_policy_lookup, ctx, fl_secid, dir);
}
int security_xfrm_state_pol_flow_match(struct xfrm_state *x,
@@ -2503,12 +2566,12 @@ int security_xfrm_state_pol_flow_match(s
int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid)
{
- return call_int_hook(xfrm_decode_session, 0, skb, secid, 1);
+ return call_int_hook(xfrm_decode_session, skb, secid, 1);
}
void security_skb_classify_flow(struct sk_buff *skb, struct flowi_common *flic)
{
- int rc = call_int_hook(xfrm_decode_session, 0, skb, &flic->flowic_secid,
+ int rc = call_int_hook(xfrm_decode_session, skb, &flic->flowic_secid,
0);
BUG_ON(rc);
@@ -2522,7 +2585,7 @@ EXPORT_SYMBOL(security_skb_classify_flow
int security_key_alloc(struct key *key, const struct cred *cred,
unsigned long flags)
{
- return call_int_hook(key_alloc, 0, key, cred, flags);
+ return call_int_hook(key_alloc, key, cred, flags);
}
void security_key_free(struct key *key)
@@ -2533,13 +2596,13 @@ void security_key_free(struct key *key)
int security_key_permission(key_ref_t key_ref, const struct cred *cred,
enum key_need_perm need_perm)
{
- return call_int_hook(key_permission, 0, key_ref, cred, need_perm);
+ return call_int_hook(key_permission, key_ref, cred, need_perm);
}
int security_key_getsecurity(struct key *key, char **_buffer)
{
*_buffer = NULL;
- return call_int_hook(key_getsecurity, 0, key, _buffer);
+ return call_int_hook(key_getsecurity, key, _buffer);
}
#endif /* CONFIG_KEYS */
@@ -2549,13 +2612,13 @@ int security_key_getsecurity(struct key
int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule,
gfp_t gfp)
{
- return call_int_hook(audit_rule_init, 0, field, op, rulestr, lsmrule,
+ return call_int_hook(audit_rule_init, field, op, rulestr, lsmrule,
gfp);
}
int security_audit_rule_known(struct audit_krule *krule)
{
- return call_int_hook(audit_rule_known, 0, krule);
+ return call_int_hook(audit_rule_known, krule);
}
void security_audit_rule_free(void *lsmrule)
@@ -2565,30 +2628,30 @@ void security_audit_rule_free(void *lsmr
int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule)
{
- return call_int_hook(audit_rule_match, 0, secid, field, op, lsmrule);
+ return call_int_hook(audit_rule_match, secid, field, op, lsmrule);
}
#endif /* CONFIG_AUDIT */
#ifdef CONFIG_BPF_SYSCALL
int security_bpf(int cmd, union bpf_attr *attr, unsigned int size)
{
- return call_int_hook(bpf, 0, cmd, attr, size);
+ return call_int_hook(bpf, cmd, attr, size);
}
int security_bpf_map(struct bpf_map *map, fmode_t fmode)
{
- return call_int_hook(bpf_map, 0, map, fmode);
+ return call_int_hook(bpf_map, map, fmode);
}
int security_bpf_prog(struct bpf_prog *prog)
{
- return call_int_hook(bpf_prog, 0, prog);
+ return call_int_hook(bpf_prog, prog);
}
int security_bpf_map_alloc(struct bpf_map *map)
{
- return call_int_hook(bpf_map_alloc_security, 0, map);
+ return call_int_hook(bpf_map_alloc_security, map);
}
int security_bpf_prog_alloc(struct bpf_prog_aux *aux)
{
- return call_int_hook(bpf_prog_alloc_security, 0, aux);
+ return call_int_hook(bpf_prog_alloc_security, aux);
}
void security_bpf_map_free(struct bpf_map *map)
{
@@ -2602,19 +2665,19 @@ void security_bpf_prog_free(struct bpf_p
int security_locked_down(enum lockdown_reason what)
{
- return call_int_hook(locked_down, 0, what);
+ return call_int_hook(locked_down, what);
}
EXPORT_SYMBOL(security_locked_down);
#ifdef CONFIG_PERF_EVENTS
int security_perf_event_open(struct perf_event_attr *attr, int type)
{
- return call_int_hook(perf_event_open, 0, attr, type);
+ return call_int_hook(perf_event_open, attr, type);
}
int security_perf_event_alloc(struct perf_event *event)
{
- return call_int_hook(perf_event_alloc, 0, event);
+ return call_int_hook(perf_event_alloc, event);
}
void security_perf_event_free(struct perf_event *event)
@@ -2624,11 +2687,11 @@ void security_perf_event_free(struct per
int security_perf_event_read(struct perf_event *event)
{
- return call_int_hook(perf_event_read, 0, event);
+ return call_int_hook(perf_event_read, event);
}
int security_perf_event_write(struct perf_event *event)
{
- return call_int_hook(perf_event_write, 0, event);
+ return call_int_hook(perf_event_write, event);
}
#endif /* CONFIG_PERF_EVENTS */
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 083/235] lsm: infrastructure management of the sock security
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (81 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 082/235] lsm: use default hook return value in call_int_hook() Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 084/235] selinux: avoid sk_socket dereference in selinux_sctp_bind_connect() Greg Kroah-Hartman
` (154 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Paul Moore, Kees Cook, John Johansen,
Stephen Smalley, Casey Schaufler, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Casey Schaufler <casey@schaufler-ca.com>
[ Upstream commit 2aff9d20d50ac45dd13a013ef5231f4fb8912356 ]
Move management of the sock->sk_security blob out
of the individual security modules and into the security
infrastructure. Instead of allocating the blobs from within
the modules the modules tell the infrastructure how much
space is required, and the space is allocated there.
Acked-by: Paul Moore <paul@paul-moore.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: John Johansen <john.johansen@canonical.com>
Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
[PM: subject tweak]
Signed-off-by: Paul Moore <paul@paul-moore.com>
Stable-dep-of: 56acfeb10019 ("selinux: avoid sk_socket dereference in selinux_sctp_bind_connect()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/lsm_hooks.h | 1
security/apparmor/include/net.h | 6 ++-
security/apparmor/lsm.c | 38 +++++---------------
security/security.c | 47 ++++++++++++++++++++++++
security/selinux/hooks.c | 72 +++++++++++++++++---------------------
security/selinux/include/objsec.h | 5 ++
security/selinux/netlabel.c | 23 ++++++------
security/smack/smack.h | 5 ++
security/smack/smack_lsm.c | 66 ++++++++++++++++------------------
security/smack/smack_netfilter.c | 8 ++--
10 files changed, 152 insertions(+), 119 deletions(-)
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1563,6 +1563,7 @@ struct lsm_blob_sizes {
int lbs_cred;
int lbs_file;
int lbs_inode;
+ int lbs_sock;
int lbs_ipc;
int lbs_msg_msg;
int lbs_task;
--- a/security/apparmor/include/net.h
+++ b/security/apparmor/include/net.h
@@ -51,8 +51,12 @@ struct aa_sk_ctx {
struct aa_label *peer;
};
-#define SK_CTX(X) ((X)->sk_security)
#define SOCK_ctx(X) SOCK_INODE(X)->i_security
+static inline struct aa_sk_ctx *aa_sock(const struct sock *sk)
+{
+ return sk->sk_security + apparmor_blob_sizes.lbs_sock;
+}
+
#define DEFINE_AUDIT_NET(NAME, OP, SK, F, T, P) \
struct lsm_network_audit NAME ## _net = { .sk = (SK), \
.family = (F)}; \
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -767,32 +767,14 @@ static int apparmor_task_kill(struct tas
}
/**
- * apparmor_sk_alloc_security - allocate and attach the sk_security field
- */
-static int apparmor_sk_alloc_security(struct sock *sk, int family, gfp_t flags)
-{
- struct aa_sk_ctx *ctx;
-
- ctx = kzalloc(sizeof(*ctx), flags);
- if (!ctx)
- return -ENOMEM;
-
- SK_CTX(sk) = ctx;
-
- return 0;
-}
-
-/**
* apparmor_sk_free_security - free the sk_security field
*/
static void apparmor_sk_free_security(struct sock *sk)
{
- struct aa_sk_ctx *ctx = SK_CTX(sk);
+ struct aa_sk_ctx *ctx = aa_sock(sk);
- SK_CTX(sk) = NULL;
aa_put_label(ctx->label);
aa_put_label(ctx->peer);
- kfree(ctx);
}
/**
@@ -801,8 +783,8 @@ static void apparmor_sk_free_security(st
static void apparmor_sk_clone_security(const struct sock *sk,
struct sock *newsk)
{
- struct aa_sk_ctx *ctx = SK_CTX(sk);
- struct aa_sk_ctx *new = SK_CTX(newsk);
+ struct aa_sk_ctx *ctx = aa_sock(sk);
+ struct aa_sk_ctx *new = aa_sock(newsk);
if (new->label)
aa_put_label(new->label);
@@ -858,7 +840,7 @@ static int apparmor_socket_post_create(s
label = aa_get_current_label();
if (sock->sk) {
- struct aa_sk_ctx *ctx = SK_CTX(sock->sk);
+ struct aa_sk_ctx *ctx = aa_sock(sock->sk);
aa_put_label(ctx->label);
ctx->label = aa_get_label(label);
@@ -1059,7 +1041,7 @@ static int apparmor_socket_shutdown(stru
*/
static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
- struct aa_sk_ctx *ctx = SK_CTX(sk);
+ struct aa_sk_ctx *ctx = aa_sock(sk);
if (!skb->secmark)
return 0;
@@ -1079,7 +1061,7 @@ static int apparmor_socket_sock_rcv_skb(
static struct aa_label *sk_peer_label(struct sock *sk)
{
- struct aa_sk_ctx *ctx = SK_CTX(sk);
+ struct aa_sk_ctx *ctx = aa_sock(sk);
if (ctx->peer)
return ctx->peer;
@@ -1160,7 +1142,7 @@ static int apparmor_socket_getpeersec_dg
*/
static void apparmor_sock_graft(struct sock *sk, struct socket *parent)
{
- struct aa_sk_ctx *ctx = SK_CTX(sk);
+ struct aa_sk_ctx *ctx = aa_sock(sk);
if (!ctx->label)
ctx->label = aa_get_current_label();
@@ -1170,7 +1152,7 @@ static void apparmor_sock_graft(struct s
static int apparmor_inet_conn_request(struct sock *sk, struct sk_buff *skb,
struct request_sock *req)
{
- struct aa_sk_ctx *ctx = SK_CTX(sk);
+ struct aa_sk_ctx *ctx = aa_sock(sk);
if (!skb->secmark)
return 0;
@@ -1187,6 +1169,7 @@ struct lsm_blob_sizes apparmor_blob_size
.lbs_cred = sizeof(struct aa_label *),
.lbs_file = sizeof(struct aa_file_ctx),
.lbs_task = sizeof(struct aa_task_ctx),
+ .lbs_sock = sizeof(struct aa_sk_ctx),
};
static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
@@ -1223,7 +1206,6 @@ static struct security_hook_list apparmo
LSM_HOOK_INIT(getprocattr, apparmor_getprocattr),
LSM_HOOK_INIT(setprocattr, apparmor_setprocattr),
- LSM_HOOK_INIT(sk_alloc_security, apparmor_sk_alloc_security),
LSM_HOOK_INIT(sk_free_security, apparmor_sk_free_security),
LSM_HOOK_INIT(sk_clone_security, apparmor_sk_clone_security),
@@ -1774,7 +1756,7 @@ static unsigned int apparmor_ip_postrout
if (sk == NULL)
return NF_ACCEPT;
- ctx = SK_CTX(sk);
+ ctx = aa_sock(sk);
if (!apparmor_secmark_check(ctx->label, OP_SENDMSG, AA_MAY_SEND,
skb->secmark, sk))
return NF_ACCEPT;
--- a/security/security.c
+++ b/security/security.c
@@ -29,6 +29,7 @@
#include <linux/string.h>
#include <linux/msg.h>
#include <net/flow.h>
+#include <net/sock.h>
#define MAX_LSM_EVM_XATTR 2
@@ -206,6 +207,7 @@ static void __init lsm_set_blob_sizes(st
lsm_set_blob_size(&needed->lbs_inode, &blob_sizes.lbs_inode);
lsm_set_blob_size(&needed->lbs_ipc, &blob_sizes.lbs_ipc);
lsm_set_blob_size(&needed->lbs_msg_msg, &blob_sizes.lbs_msg_msg);
+ lsm_set_blob_size(&needed->lbs_sock, &blob_sizes.lbs_sock);
lsm_set_blob_size(&needed->lbs_task, &blob_sizes.lbs_task);
}
@@ -341,6 +343,7 @@ static void __init ordered_lsm_init(void
init_debug("inode blob size = %d\n", blob_sizes.lbs_inode);
init_debug("ipc blob size = %d\n", blob_sizes.lbs_ipc);
init_debug("msg_msg blob size = %d\n", blob_sizes.lbs_msg_msg);
+ init_debug("sock blob size = %d\n", blob_sizes.lbs_sock);
init_debug("task blob size = %d\n", blob_sizes.lbs_task);
/*
@@ -2325,14 +2328,56 @@ int security_socket_getpeersec_dgram(str
}
EXPORT_SYMBOL(security_socket_getpeersec_dgram);
+/**
+ * lsm_sock_alloc - allocate a composite sock blob
+ * @sock: the sock that needs a blob
+ * @priority: allocation mode
+ *
+ * Allocate the sock blob for all the modules
+ *
+ * Returns 0, or -ENOMEM if memory can't be allocated.
+ */
+static int lsm_sock_alloc(struct sock *sock, gfp_t priority)
+{
+ if (blob_sizes.lbs_sock == 0) {
+ sock->sk_security = NULL;
+ return 0;
+ }
+
+ sock->sk_security = kzalloc(blob_sizes.lbs_sock, priority);
+ if (sock->sk_security == NULL)
+ return -ENOMEM;
+ return 0;
+}
+
+/**
+ * security_sk_alloc() - Allocate and initialize a sock's LSM blob
+ * @sk: sock
+ * @family: protocol family
+ * @priority: gfp flags
+ *
+ * Allocate and attach a security structure to the sk->sk_security field, which
+ * is used to copy security attributes between local stream sockets.
+ *
+ * Return: Returns 0 on success, error on failure.
+ */
int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
{
- return call_int_hook(sk_alloc_security, sk, family, priority);
+ int rc = lsm_sock_alloc(sk, priority);
+
+ if (unlikely(rc))
+ return rc;
+ rc = call_int_hook(sk_alloc_security, sk, family, priority);
+ if (unlikely(rc))
+ security_sk_free(sk);
+ return rc;
}
void security_sk_free(struct sock *sk)
{
call_void_hook(sk_free_security, sk);
+ kfree(sk->sk_security);
+ sk->sk_security = NULL;
}
void security_sk_clone(const struct sock *sk, struct sock *newsk)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4522,7 +4522,7 @@ static int socket_sockcreate_sid(const s
static int sock_has_perm(struct sock *sk, u32 perms)
{
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
struct common_audit_data ad;
struct lsm_network_audit net = {0,};
@@ -4579,7 +4579,7 @@ static int selinux_socket_post_create(st
isec->initialized = LABEL_INITIALIZED;
if (sock->sk) {
- sksec = sock->sk->sk_security;
+ sksec = selinux_sock(sock->sk);
sksec->sclass = sclass;
sksec->sid = sid;
/* Allows detection of the first association on this socket */
@@ -4595,8 +4595,8 @@ static int selinux_socket_post_create(st
static int selinux_socket_socketpair(struct socket *socka,
struct socket *sockb)
{
- struct sk_security_struct *sksec_a = socka->sk->sk_security;
- struct sk_security_struct *sksec_b = sockb->sk->sk_security;
+ struct sk_security_struct *sksec_a = selinux_sock(socka->sk);
+ struct sk_security_struct *sksec_b = selinux_sock(sockb->sk);
sksec_a->peer_sid = sksec_b->sid;
sksec_b->peer_sid = sksec_a->sid;
@@ -4611,7 +4611,7 @@ static int selinux_socket_socketpair(str
static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
{
struct sock *sk = sock->sk;
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
u16 family;
int err;
@@ -4753,7 +4753,7 @@ static int selinux_socket_connect_helper
struct sockaddr *address, int addrlen)
{
struct sock *sk = sock->sk;
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
int err;
err = sock_has_perm(sk, SOCKET__CONNECT);
@@ -4932,9 +4932,9 @@ static int selinux_socket_unix_stream_co
struct sock *other,
struct sock *newsk)
{
- struct sk_security_struct *sksec_sock = sock->sk_security;
- struct sk_security_struct *sksec_other = other->sk_security;
- struct sk_security_struct *sksec_new = newsk->sk_security;
+ struct sk_security_struct *sksec_sock = selinux_sock(sock);
+ struct sk_security_struct *sksec_other = selinux_sock(other);
+ struct sk_security_struct *sksec_new = selinux_sock(newsk);
struct common_audit_data ad;
struct lsm_network_audit net = {0,};
int err;
@@ -4966,8 +4966,8 @@ static int selinux_socket_unix_stream_co
static int selinux_socket_unix_may_send(struct socket *sock,
struct socket *other)
{
- struct sk_security_struct *ssec = sock->sk->sk_security;
- struct sk_security_struct *osec = other->sk->sk_security;
+ struct sk_security_struct *ssec = selinux_sock(sock->sk);
+ struct sk_security_struct *osec = selinux_sock(other->sk);
struct common_audit_data ad;
struct lsm_network_audit net = {0,};
@@ -5009,7 +5009,7 @@ static int selinux_sock_rcv_skb_compat(s
u16 family)
{
int err = 0;
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
u32 sk_sid = sksec->sid;
struct common_audit_data ad;
struct lsm_network_audit net = {0,};
@@ -5042,7 +5042,7 @@ static int selinux_sock_rcv_skb_compat(s
static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
int err;
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
u16 family = sk->sk_family;
u32 sk_sid = sksec->sid;
struct common_audit_data ad;
@@ -5117,7 +5117,7 @@ static int selinux_socket_getpeersec_str
int err = 0;
char *scontext = NULL;
u32 scontext_len;
- struct sk_security_struct *sksec = sock->sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sock->sk);
u32 peer_sid = SECSID_NULL;
if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET ||
@@ -5175,34 +5175,27 @@ out:
static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority)
{
- struct sk_security_struct *sksec;
-
- sksec = kzalloc(sizeof(*sksec), priority);
- if (!sksec)
- return -ENOMEM;
+ struct sk_security_struct *sksec = selinux_sock(sk);
sksec->peer_sid = SECINITSID_UNLABELED;
sksec->sid = SECINITSID_UNLABELED;
sksec->sclass = SECCLASS_SOCKET;
selinux_netlbl_sk_security_reset(sksec);
- sk->sk_security = sksec;
return 0;
}
static void selinux_sk_free_security(struct sock *sk)
{
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
- sk->sk_security = NULL;
selinux_netlbl_sk_security_free(sksec);
- kfree(sksec);
}
static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk)
{
- struct sk_security_struct *sksec = sk->sk_security;
- struct sk_security_struct *newsksec = newsk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
+ struct sk_security_struct *newsksec = selinux_sock(newsk);
newsksec->sid = sksec->sid;
newsksec->peer_sid = sksec->peer_sid;
@@ -5216,7 +5209,7 @@ static void selinux_sk_getsecid(struct s
if (!sk)
*secid = SECINITSID_ANY_SOCKET;
else {
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
*secid = sksec->sid;
}
@@ -5226,7 +5219,7 @@ static void selinux_sock_graft(struct so
{
struct inode_security_struct *isec =
inode_security_novalidate(SOCK_INODE(parent));
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
if (sk->sk_family == PF_INET || sk->sk_family == PF_INET6 ||
sk->sk_family == PF_UNIX)
@@ -5241,7 +5234,7 @@ static void selinux_sock_graft(struct so
static int selinux_sctp_assoc_request(struct sctp_endpoint *ep,
struct sk_buff *skb)
{
- struct sk_security_struct *sksec = ep->base.sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(ep->base.sk);
struct common_audit_data ad;
struct lsm_network_audit net = {0,};
u8 peerlbl_active;
@@ -5392,8 +5385,8 @@ static int selinux_sctp_bind_connect(str
static void selinux_sctp_sk_clone(struct sctp_endpoint *ep, struct sock *sk,
struct sock *newsk)
{
- struct sk_security_struct *sksec = sk->sk_security;
- struct sk_security_struct *newsksec = newsk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
+ struct sk_security_struct *newsksec = selinux_sock(newsk);
/* If policy does not support SECCLASS_SCTP_SOCKET then call
* the non-sctp clone version.
@@ -5410,7 +5403,7 @@ static void selinux_sctp_sk_clone(struct
static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb,
struct request_sock *req)
{
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
int err;
u16 family = req->rsk_ops->family;
u32 connsid;
@@ -5431,7 +5424,7 @@ static int selinux_inet_conn_request(str
static void selinux_inet_csk_clone(struct sock *newsk,
const struct request_sock *req)
{
- struct sk_security_struct *newsksec = newsk->sk_security;
+ struct sk_security_struct *newsksec = selinux_sock(newsk);
newsksec->sid = req->secid;
newsksec->peer_sid = req->peer_secid;
@@ -5448,7 +5441,7 @@ static void selinux_inet_csk_clone(struc
static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb)
{
u16 family = sk->sk_family;
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
/* handle mapped IPv4 packets arriving via IPv6 sockets */
if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP))
@@ -5532,7 +5525,7 @@ static int selinux_tun_dev_attach_queue(
static int selinux_tun_dev_attach(struct sock *sk, void *security)
{
struct tun_security_struct *tunsec = security;
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
/* we don't currently perform any NetLabel based labeling here and it
* isn't clear that we would want to do so anyway; while we could apply
@@ -5676,7 +5669,7 @@ static unsigned int selinux_ip_output(st
return NF_ACCEPT;
/* standard practice, label using the parent socket */
- sksec = sk->sk_security;
+ sksec = selinux_sock(sk);
sid = sksec->sid;
} else
sid = SECINITSID_KERNEL;
@@ -5715,7 +5708,7 @@ static unsigned int selinux_ip_postroute
if (sk == NULL)
return NF_ACCEPT;
- sksec = sk->sk_security;
+ sksec = selinux_sock(sk);
ad.type = LSM_AUDIT_DATA_NET;
ad.u.net = &net;
@@ -5807,7 +5800,7 @@ static unsigned int selinux_ip_postroute
u32 skb_sid;
struct sk_security_struct *sksec;
- sksec = sk->sk_security;
+ sksec = selinux_sock(sk);
if (selinux_skb_peerlbl_sid(skb, family, &skb_sid))
return NF_DROP;
/* At this point, if the returned skb peerlbl is SECSID_NULL
@@ -5836,7 +5829,7 @@ static unsigned int selinux_ip_postroute
} else {
/* Locally generated packet, fetch the security label from the
* associated socket. */
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
peer_sid = sksec->sid;
secmark_perm = PACKET__SEND;
}
@@ -5901,7 +5894,7 @@ static int selinux_netlink_send(struct s
unsigned int data_len = skb->len;
unsigned char *data = skb->data;
struct nlmsghdr *nlh;
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
u16 sclass = sksec->sclass;
u32 perm;
@@ -6927,6 +6920,7 @@ struct lsm_blob_sizes selinux_blob_sizes
.lbs_inode = sizeof(struct inode_security_struct),
.lbs_ipc = sizeof(struct ipc_security_struct),
.lbs_msg_msg = sizeof(struct msg_security_struct),
+ .lbs_sock = sizeof(struct sk_security_struct),
};
#ifdef CONFIG_PERF_EVENTS
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -189,4 +189,9 @@ static inline u32 current_sid(void)
return tsec->sid;
}
+static inline struct sk_security_struct *selinux_sock(const struct sock *sock)
+{
+ return sock->sk_security + selinux_blob_sizes.lbs_sock;
+}
+
#endif /* _SELINUX_OBJSEC_H_ */
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -17,6 +17,7 @@
#include <linux/gfp.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
+#include <linux/lsm_hooks.h>
#include <net/sock.h>
#include <net/netlabel.h>
#include <net/ip.h>
@@ -67,7 +68,7 @@ static int selinux_netlbl_sidlookup_cach
static struct netlbl_lsm_secattr *selinux_netlbl_sock_genattr(struct sock *sk)
{
int rc;
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
struct netlbl_lsm_secattr *secattr;
if (sksec->nlbl_secattr != NULL)
@@ -100,7 +101,7 @@ static struct netlbl_lsm_secattr *selinu
const struct sock *sk,
u32 sid)
{
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
struct netlbl_lsm_secattr *secattr = sksec->nlbl_secattr;
if (secattr == NULL)
@@ -235,7 +236,7 @@ int selinux_netlbl_skbuff_setsid(struct
* being labeled by it's parent socket, if it is just exit */
sk = skb_to_full_sk(skb);
if (sk != NULL) {
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
if (sksec->nlbl_state != NLBL_REQSKB)
return 0;
@@ -273,7 +274,7 @@ int selinux_netlbl_sctp_assoc_request(st
{
int rc;
struct netlbl_lsm_secattr secattr;
- struct sk_security_struct *sksec = ep->base.sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(ep->base.sk);
struct sockaddr_in addr4;
struct sockaddr_in6 addr6;
@@ -352,7 +353,7 @@ inet_conn_request_return:
*/
void selinux_netlbl_inet_csk_clone(struct sock *sk, u16 family)
{
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
if (family == PF_INET)
sksec->nlbl_state = NLBL_LABELED;
@@ -370,8 +371,8 @@ void selinux_netlbl_inet_csk_clone(struc
*/
void selinux_netlbl_sctp_sk_clone(struct sock *sk, struct sock *newsk)
{
- struct sk_security_struct *sksec = sk->sk_security;
- struct sk_security_struct *newsksec = newsk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
+ struct sk_security_struct *newsksec = selinux_sock(newsk);
newsksec->nlbl_state = sksec->nlbl_state;
}
@@ -389,7 +390,7 @@ void selinux_netlbl_sctp_sk_clone(struct
int selinux_netlbl_socket_post_create(struct sock *sk, u16 family)
{
int rc;
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
struct netlbl_lsm_secattr *secattr;
if (family != PF_INET && family != PF_INET6)
@@ -504,7 +505,7 @@ int selinux_netlbl_socket_setsockopt(str
{
int rc = 0;
struct sock *sk = sock->sk;
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
struct netlbl_lsm_secattr secattr;
if (selinux_netlbl_option(level, optname) &&
@@ -542,7 +543,7 @@ static int selinux_netlbl_socket_connect
struct sockaddr *addr)
{
int rc;
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
struct netlbl_lsm_secattr *secattr;
/* connected sockets are allowed to disconnect when the address family
@@ -581,7 +582,7 @@ static int selinux_netlbl_socket_connect
int selinux_netlbl_socket_connect_locked(struct sock *sk,
struct sockaddr *addr)
{
- struct sk_security_struct *sksec = sk->sk_security;
+ struct sk_security_struct *sksec = selinux_sock(sk);
if (sksec->nlbl_state != NLBL_REQSKB &&
sksec->nlbl_state != NLBL_CONNLABELED)
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -358,6 +358,11 @@ static inline struct smack_known **smack
return ipc->security + smack_blob_sizes.lbs_ipc;
}
+static inline struct socket_smack *smack_sock(const struct sock *sock)
+{
+ return sock->sk_security + smack_blob_sizes.lbs_sock;
+}
+
/*
* Is the directory transmuting?
*/
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -1469,7 +1469,7 @@ static int smack_inode_getsecurity(struc
if (sock == NULL || sock->sk == NULL)
return -EOPNOTSUPP;
- ssp = sock->sk->sk_security;
+ ssp = smack_sock(sock->sk);
if (strcmp(name, XATTR_SMACK_IPIN) == 0)
isp = ssp->smk_in;
@@ -1856,7 +1856,7 @@ static int smack_file_receive(struct fil
if (inode->i_sb->s_magic == SOCKFS_MAGIC) {
sock = SOCKET_I(inode);
- ssp = sock->sk->sk_security;
+ ssp = smack_sock(sock->sk);
tsp = smack_cred(current_cred());
/*
* If the receiving process can't write to the
@@ -2263,11 +2263,7 @@ static void smack_task_to_inode(struct t
static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
{
struct smack_known *skp = smk_of_current();
- struct socket_smack *ssp;
-
- ssp = kzalloc(sizeof(struct socket_smack), gfp_flags);
- if (ssp == NULL)
- return -ENOMEM;
+ struct socket_smack *ssp = smack_sock(sk);
/*
* Sockets created by kernel threads receive web label.
@@ -2281,11 +2277,10 @@ static int smack_sk_alloc_security(struc
}
ssp->smk_packet = NULL;
- sk->sk_security = ssp;
-
return 0;
}
+#ifdef SMACK_IPV6_PORT_LABELING
/**
* smack_sk_free_security - Free a socket blob
* @sk: the socket
@@ -2294,7 +2289,6 @@ static int smack_sk_alloc_security(struc
*/
static void smack_sk_free_security(struct sock *sk)
{
-#ifdef SMACK_IPV6_PORT_LABELING
struct smk_port_label *spp;
if (sk->sk_family == PF_INET6) {
@@ -2307,9 +2301,8 @@ static void smack_sk_free_security(struc
}
rcu_read_unlock();
}
-#endif
- kfree(sk->sk_security);
}
+#endif
/**
* smack_ipv4host_label - check host based restrictions
@@ -2422,7 +2415,7 @@ static struct smack_known *smack_ipv6hos
*/
static int smack_netlbl_add(struct sock *sk)
{
- struct socket_smack *ssp = sk->sk_security;
+ struct socket_smack *ssp = smack_sock(sk);
struct smack_known *skp = ssp->smk_out;
int rc;
@@ -2454,7 +2447,7 @@ static int smack_netlbl_add(struct sock
*/
static void smack_netlbl_delete(struct sock *sk)
{
- struct socket_smack *ssp = sk->sk_security;
+ struct socket_smack *ssp = smack_sock(sk);
/*
* Take the label off the socket if one is set.
@@ -2486,7 +2479,7 @@ static int smk_ipv4_check(struct sock *s
struct smack_known *skp;
int rc = 0;
struct smack_known *hkp;
- struct socket_smack *ssp = sk->sk_security;
+ struct socket_smack *ssp = smack_sock(sk);
struct smk_audit_info ad;
rcu_read_lock();
@@ -2559,7 +2552,7 @@ static void smk_ipv6_port_label(struct s
{
struct sock *sk = sock->sk;
struct sockaddr_in6 *addr6;
- struct socket_smack *ssp = sock->sk->sk_security;
+ struct socket_smack *ssp = smack_sock(sock->sk);
struct smk_port_label *spp;
unsigned short port = 0;
@@ -2648,7 +2641,7 @@ static int smk_ipv6_port_check(struct so
int act)
{
struct smk_port_label *spp;
- struct socket_smack *ssp = sk->sk_security;
+ struct socket_smack *ssp = smack_sock(sk);
struct smack_known *skp = NULL;
unsigned short port;
struct smack_known *object;
@@ -2750,7 +2743,7 @@ static int smack_inode_setsecurity(struc
if (sock == NULL || sock->sk == NULL)
return -EOPNOTSUPP;
- ssp = sock->sk->sk_security;
+ ssp = smack_sock(sock->sk);
if (strcmp(name, XATTR_SMACK_IPIN) == 0)
ssp->smk_in = skp;
@@ -2798,7 +2791,7 @@ static int smack_socket_post_create(stru
* Sockets created by kernel threads receive web label.
*/
if (unlikely(current->flags & PF_KTHREAD)) {
- ssp = sock->sk->sk_security;
+ ssp = smack_sock(sock->sk);
ssp->smk_in = &smack_known_web;
ssp->smk_out = &smack_known_web;
}
@@ -2823,8 +2816,8 @@ static int smack_socket_post_create(stru
static int smack_socket_socketpair(struct socket *socka,
struct socket *sockb)
{
- struct socket_smack *asp = socka->sk->sk_security;
- struct socket_smack *bsp = sockb->sk->sk_security;
+ struct socket_smack *asp = smack_sock(socka->sk);
+ struct socket_smack *bsp = smack_sock(sockb->sk);
asp->smk_packet = bsp->smk_out;
bsp->smk_packet = asp->smk_out;
@@ -2887,7 +2880,7 @@ static int smack_socket_connect(struct s
if (__is_defined(SMACK_IPV6_SECMARK_LABELING))
rsp = smack_ipv6host_label(sip);
if (rsp != NULL) {
- struct socket_smack *ssp = sock->sk->sk_security;
+ struct socket_smack *ssp = smack_sock(sock->sk);
rc = smk_ipv6_check(ssp->smk_out, rsp, sip,
SMK_CONNECTING);
@@ -3628,9 +3621,9 @@ static int smack_unix_stream_connect(str
{
struct smack_known *skp;
struct smack_known *okp;
- struct socket_smack *ssp = sock->sk_security;
- struct socket_smack *osp = other->sk_security;
- struct socket_smack *nsp = newsk->sk_security;
+ struct socket_smack *ssp = smack_sock(sock);
+ struct socket_smack *osp = smack_sock(other);
+ struct socket_smack *nsp = smack_sock(newsk);
struct smk_audit_info ad;
int rc = 0;
#ifdef CONFIG_AUDIT
@@ -3682,8 +3675,8 @@ static int smack_unix_stream_connect(str
*/
static int smack_unix_may_send(struct socket *sock, struct socket *other)
{
- struct socket_smack *ssp = sock->sk->sk_security;
- struct socket_smack *osp = other->sk->sk_security;
+ struct socket_smack *ssp = smack_sock(sock->sk);
+ struct socket_smack *osp = smack_sock(other->sk);
struct smk_audit_info ad;
int rc;
@@ -3720,7 +3713,7 @@ static int smack_socket_sendmsg(struct s
struct sockaddr_in6 *sap = (struct sockaddr_in6 *) msg->msg_name;
#endif
#ifdef SMACK_IPV6_SECMARK_LABELING
- struct socket_smack *ssp = sock->sk->sk_security;
+ struct socket_smack *ssp = smack_sock(sock->sk);
struct smack_known *rsp;
#endif
int rc = 0;
@@ -3933,7 +3926,7 @@ static struct smack_known *smack_from_ne
netlbl_secattr_init(&secattr);
if (sk)
- ssp = sk->sk_security;
+ ssp = smack_sock(sk);
if (netlbl_skbuff_getattr(skb, family, &secattr) == 0) {
skp = smack_from_secattr(&secattr, ssp);
@@ -3955,7 +3948,7 @@ static struct smack_known *smack_from_ne
*/
static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
- struct socket_smack *ssp = sk->sk_security;
+ struct socket_smack *ssp = smack_sock(sk);
struct smack_known *skp = NULL;
int rc = 0;
struct smk_audit_info ad;
@@ -4059,7 +4052,7 @@ static int smack_socket_getpeersec_strea
u32 slen = 1;
int rc = 0;
- ssp = sock->sk->sk_security;
+ ssp = smack_sock(sock->sk);
if (ssp->smk_packet != NULL) {
rcp = ssp->smk_packet->smk_known;
slen = strlen(rcp) + 1;
@@ -4109,7 +4102,7 @@ static int smack_socket_getpeersec_dgram
switch (family) {
case PF_UNIX:
- ssp = sock->sk->sk_security;
+ ssp = smack_sock(sock->sk);
s = ssp->smk_out->smk_secid;
break;
case PF_INET:
@@ -4158,7 +4151,7 @@ static void smack_sock_graft(struct sock
(sk->sk_family != PF_INET && sk->sk_family != PF_INET6))
return;
- ssp = sk->sk_security;
+ ssp = smack_sock(sk);
ssp->smk_in = skp;
ssp->smk_out = skp;
/* cssp->smk_packet is already set in smack_inet_csk_clone() */
@@ -4178,7 +4171,7 @@ static int smack_inet_conn_request(struc
{
u16 family = sk->sk_family;
struct smack_known *skp;
- struct socket_smack *ssp = sk->sk_security;
+ struct socket_smack *ssp = smack_sock(sk);
struct sockaddr_in addr;
struct iphdr *hdr;
struct smack_known *hskp;
@@ -4264,7 +4257,7 @@ static int smack_inet_conn_request(struc
static void smack_inet_csk_clone(struct sock *sk,
const struct request_sock *req)
{
- struct socket_smack *ssp = sk->sk_security;
+ struct socket_smack *ssp = smack_sock(sk);
struct smack_known *skp;
if (req->peer_secid != 0) {
@@ -4761,6 +4754,7 @@ struct lsm_blob_sizes smack_blob_sizes _
.lbs_inode = sizeof(struct inode_smack),
.lbs_ipc = sizeof(struct smack_known *),
.lbs_msg_msg = sizeof(struct smack_known *),
+ .lbs_sock = sizeof(struct socket_smack),
};
static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
@@ -4871,7 +4865,9 @@ static struct security_hook_list smack_h
LSM_HOOK_INIT(socket_getpeersec_stream, smack_socket_getpeersec_stream),
LSM_HOOK_INIT(socket_getpeersec_dgram, smack_socket_getpeersec_dgram),
LSM_HOOK_INIT(sk_alloc_security, smack_sk_alloc_security),
+#ifdef SMACK_IPV6_PORT_LABELING
LSM_HOOK_INIT(sk_free_security, smack_sk_free_security),
+#endif
LSM_HOOK_INIT(sock_graft, smack_sock_graft),
LSM_HOOK_INIT(inet_conn_request, smack_inet_conn_request),
LSM_HOOK_INIT(inet_csk_clone, smack_inet_csk_clone),
--- a/security/smack/smack_netfilter.c
+++ b/security/smack/smack_netfilter.c
@@ -28,8 +28,8 @@ static unsigned int smack_ipv6_output(vo
struct socket_smack *ssp;
struct smack_known *skp;
- if (sk && sk->sk_security) {
- ssp = sk->sk_security;
+ if (sk) {
+ ssp = smack_sock(sk);
skp = ssp->smk_out;
skb->secmark = skp->smk_secid;
}
@@ -46,8 +46,8 @@ static unsigned int smack_ipv4_output(vo
struct socket_smack *ssp;
struct smack_known *skp;
- if (sk && sk->sk_security) {
- ssp = sk->sk_security;
+ if (sk) {
+ ssp = smack_sock(sk);
skp = ssp->smk_out;
skb->secmark = skp->smk_secid;
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 084/235] selinux: avoid sk_socket dereference in selinux_sctp_bind_connect()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (82 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 083/235] lsm: infrastructure management of the sock security Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 085/235] net/9p: fix infinite loop in p9_client_rpc on fatal signal Greg Kroah-Hartman
` (153 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Stephen Smalley, Tristan Madani,
Paul Moore, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <tristan@talencesecurity.com>
[ Upstream commit 56acfeb10019e200ab6787d01f8d7cbe0f01526f ]
selinux_sctp_bind_connect() dereferences sk->sk_socket to pass a
struct socket * to selinux_socket_bind() and
selinux_socket_connect_helper(). However, when the hook is invoked
from the ASCONF softirq path (sctp_process_asconf), there is no file
reference guaranteeing that sk->sk_socket is non-NULL. The setsockopt
callers (bindx, connectx, set_primary, sendmsg connect) hold a file
reference and are not affected.
Both selinux_socket_bind() and selinux_socket_connect_helper()
immediately resolve sock->sk, never using the struct socket * for
anything else. Refactor the inner logic into helpers that take a
struct sock * directly so that selinux_sctp_bind_connect() never needs
to touch sk->sk_socket at all.
Cc: stable@vger.kernel.org
Fixes: d452930fd3b9 ("selinux: Add SCTP support")
Suggested-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Signed-off-by: Tristan Madani <tristan@talencesecurity.com>
Reviewed-by: Stephen Smalley <stephen.smalley.work@gmail.com>
Tested-by: Stephen Smalley <stephen.smalley.work@gmail.com>
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>
---
security/selinux/hooks.c | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4608,9 +4608,8 @@ static int selinux_socket_socketpair(str
Need to determine whether we should perform a name_bind
permission check between the socket and the port number. */
-static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
+static int __selinux_socket_bind(struct sock *sk, struct sockaddr *address, int addrlen)
{
- struct sock *sk = sock->sk;
struct sk_security_struct *sksec = selinux_sock(sk);
u16 family;
int err;
@@ -4746,13 +4745,17 @@ err_af:
return -EAFNOSUPPORT;
}
+static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
+{
+ return __selinux_socket_bind(sock->sk, address, addrlen);
+}
+
/* This supports connect(2) and SCTP connect services such as sctp_connectx(3)
* and sctp_sendmsg(3) as described in Documentation/security/SCTP.rst
*/
-static int selinux_socket_connect_helper(struct socket *sock,
+static int selinux_socket_connect_helper(struct sock *sk,
struct sockaddr *address, int addrlen)
{
- struct sock *sk = sock->sk;
struct sk_security_struct *sksec = selinux_sock(sk);
int err;
@@ -4846,7 +4849,7 @@ static int selinux_socket_connect(struct
int err;
struct sock *sk = sock->sk;
- err = selinux_socket_connect_helper(sock, address, addrlen);
+ err = selinux_socket_connect_helper(sk, address, addrlen);
if (err)
return err;
@@ -5310,13 +5313,11 @@ static int selinux_sctp_bind_connect(str
int len, err = 0, walk_size = 0;
void *addr_buf;
struct sockaddr *addr;
- struct socket *sock;
if (!selinux_policycap_extsockclass())
return 0;
/* Process one or more addresses that may be IPv4 or IPv6 */
- sock = sk->sk_socket;
addr_buf = address;
while (walk_size < addrlen) {
@@ -5345,14 +5346,14 @@ static int selinux_sctp_bind_connect(str
case SCTP_PRIMARY_ADDR:
case SCTP_SET_PEER_PRIMARY_ADDR:
case SCTP_SOCKOPT_BINDX_ADD:
- err = selinux_socket_bind(sock, addr, len);
+ err = __selinux_socket_bind(sk, addr, len);
break;
/* Connect checks */
case SCTP_SOCKOPT_CONNECTX:
case SCTP_PARAM_SET_PRIMARY:
case SCTP_PARAM_ADD_IP:
case SCTP_SENDMSG_CONNECT:
- err = selinux_socket_connect_helper(sock, addr, len);
+ err = selinux_socket_connect_helper(sk, addr, len);
if (err)
return err;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 085/235] net/9p: fix infinite loop in p9_client_rpc on fatal signal
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (83 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 084/235] selinux: avoid sk_socket dereference in selinux_sctp_bind_connect() Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 086/235] 9p: skip nlink update in cacheless mode to fix WARN_ON Greg Kroah-Hartman
` (152 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Vasiliy Kovalev, Dominique Martinet,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vasiliy Kovalev <kovalev@altlinux.org>
[ Upstream commit 6b4f48728faa8bb514368f7eacda05565dea8696 ]
When p9_client_rpc() is called with type P9_TFLUSH and the transport
has no peer (e.g. fd transport backed by pipes with no 9p server),
a fatal signal causes an infinite loop:
again:
err = io_wait_event_killable(req->wq, ...)
/* SIGKILL wakes the task, returns -ERESTARTSYS */
if (err == -ERESTARTSYS && c->status == Connected &&
type == P9_TFLUSH) {
sigpending = 1;
clear_thread_flag(TIF_SIGPENDING);
goto again;
}
clear_thread_flag() clears TIF_SIGPENDING before jumping back to
io_wait_event_killable(). signal_pending_state() checks TIF_SIGPENDING,
finds it zero, and the task goes to sleep again. The task can only wake
on the next signal delivery that calls signal_wake_up() and sets
TIF_SIGPENDING again. When that happens the loop repeats, clears
TIF_SIGPENDING, and sleeps again indefinitely.
This is triggered in practice by coredump_wait(): when a thread in a
multi-threaded process causes a coredump (e.g. via SIGSYS from Syscall
User Dispatch), coredump_wait() sends SIGKILL to all other threads and
waits for them to call mm_release(). If one of those threads is blocked
in p9_client_rpc() over an fd transport with no peer, it enters the
P9_TFLUSH loop and never calls mm_release(), so coredump_wait() stalls
forever:
INFO: task syz.0.18:676 blocked for more than 143 seconds.
Not tainted 6.12.77+ #1
task:syz.0.18 state:D stack:27600 pid:676 tgid:673 ppid:630 flags:0x00000004
Call Trace:
<TASK>
context_switch kernel/sched/core.c:5344 [inline]
__schedule+0xcb4/0x5d50 kernel/sched/core.c:6724
__schedule_loop kernel/sched/core.c:6801 [inline]
schedule+0xe5/0x350 kernel/sched/core.c:6816
schedule_timeout+0x253/0x290 kernel/time/timer.c:2593
do_wait_for_common kernel/sched/completion.c:95 [inline]
__wait_for_common+0x409/0x600 kernel/sched/completion.c:116
wait_for_common kernel/sched/completion.c:127 [inline]
wait_for_completion_state+0x1d/0x40 kernel/sched/completion.c:264
coredump_wait fs/coredump.c:448 [inline]
do_coredump+0x854/0x4350 fs/coredump.c:629
get_signal+0x1425/0x2730 kernel/signal.c:2903
arch_do_signal_or_restart+0x81/0x880 arch/x86/kernel/signal.c:337
exit_to_user_mode_loop kernel/entry/common.c:111 [inline]
exit_to_user_mode_prepare include/linux/entry-common.h:328 [inline]
__syscall_exit_to_user_mode_work kernel/entry/common.c:207 [inline]
syscall_exit_to_user_mode+0xf9/0x160 kernel/entry/common.c:218
do_syscall_64+0x102/0x220 arch/x86/entry/common.c:84
entry_SYSCALL_64_after_hwframe+0x77/0x7f
</TASK>
Fix: check fatal_signal_pending() before clearing TIF_SIGPENDING in the
P9_TFLUSH retry loop. At that point TIF_SIGPENDING is still set, so
fatal_signal_pending() works correctly. If a fatal signal is pending,
jump to recalc_sigpending to restore TIF_SIGPENDING and return
-ERESTARTSYS to the caller.
The same defect is present in stable kernels back to 5.4. On those
kernels the infinite loop is broken earlier by a second SIGKILL from
the parent process (e.g. kill_and_wait() retrying after a timeout),
resulting in a zombie process and a shutdown delay rather than a
permanent D-state hang, but the underlying flaw is the same.
Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
Fixes: 91b8534fa8f5 ("9p: make rpc code common and rework flush code")
Closes: https://syzkaller.appspot.com/bug?extid=3ce7863f8fc836a427e7
Cc: stable@vger.kernel.org
Signed-off-by: Vasiliy Kovalev <kovalev@altlinux.org>
Message-ID: <20260415155237.182891-1-kovalev@altlinux.org>
Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
[ adjusted context to match the older parenthesized `if ((err == -ERESTARTSYS) && ...)` condition style ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/9p/client.c | 2 ++
1 file changed, 2 insertions(+)
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -771,6 +771,8 @@ again:
if ((err == -ERESTARTSYS) && (c->status == Connected)
&& (type == P9_TFLUSH)) {
+ if (fatal_signal_pending(current))
+ goto recalc_sigpending;
sigpending = 1;
clear_thread_flag(TIF_SIGPENDING);
goto again;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 086/235] 9p: skip nlink update in cacheless mode to fix WARN_ON
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (84 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 085/235] net/9p: fix infinite loop in p9_client_rpc on fatal signal Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 087/235] mtd: maps: vmu-flash: fix fault in unaligned fixup Greg Kroah-Hartman
` (151 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Dominique Martinet, Breno Leitao,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Breno Leitao <leitao@debian.org>
[ Upstream commit 574aa0b4799470ac814479f1138d19efe6262255 ]
v9fs_dec_count() unconditionally calls drop_nlink() on regular files,
even when the inode's nlink is already zero. In cacheless mode the
client refetches inode metadata from the server (the source of truth)
on every operation, so by the time v9fs_remove() returns, the locally
cached nlink may already reflect the post-unlink value:
1. Client initiates unlink, server processes it and sets nlink to 0
2. Client refetches inode metadata (nlink=0) before unlink returns
3. Client's v9fs_remove() completes successfully
4. Client calls v9fs_dec_count() which calls drop_nlink() on nlink=0
This race is easily triggered under heavy unlink workloads, such as
stress-ng's unlink stressor, producing the following warning:
WARNING: fs/inode.c:417 at drop_nlink+0x4c/0xc8
Call trace:
drop_nlink+0x4c/0xc8
v9fs_remove+0x1e0/0x250 [9p]
v9fs_vfs_unlink+0x20/0x38 [9p]
vfs_unlink+0x13c/0x258
...
In cacheless mode the server is authoritative and the inode is on its
way out, so locally adjusting nlink buys nothing. Skip v9fs_dec_count()
entirely when neither CACHE_META nor CACHE_LOOSE is set, which both
avoids the warning and removes a class of nlink races (two concurrent
unlinkers observing nlink > 0 and both calling drop_nlink()) that an
nlink == 0 guard alone would only narrow rather than close.
Fixes: ac89b2ef9b55 ("9p: don't maintain dir i_nlink if the exported fs doesn't either")
Cc: stable@vger.kernel.org
Suggested-by: Dominique Martinet <asmadeus@codewreck.org>
Signed-off-by: Breno Leitao <leitao@debian.org>
Message-ID: <20260421-9p-v2-1-48762d294fad@debian.org>
Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
[ Adapted `v9ses->cache & (CACHE_META | CACHE_LOOSE)` bitmask test to the pre-bitmask exclusive enum form `v9ses->cache != CACHE_LOOSE && v9ses->cache != CACHE_FSCACHE`. ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/9p/vfs_inode.c | 9 +++++++++
1 file changed, 9 insertions(+)
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -516,10 +516,19 @@ static int v9fs_at_to_dotl_flags(int fla
* - ext4 (with dir_nlink feature enabled) sets nlink to 1 if a dir has more
* than EXT4_LINK_MAX (65000) links.
*
+ * In cacheless mode the server is the source of truth for nlink and the
+ * inode is going away immediately, so locally adjusting i_nlink buys
+ * nothing and races with concurrent metadata fetches that may already
+ * have observed the post-unlink value (nlink == 0).
+ *
* @inode: inode whose nlink is being dropped
*/
static void v9fs_dec_count(struct inode *inode)
{
+ struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode);
+
+ if (v9ses->cache != CACHE_LOOSE && v9ses->cache != CACHE_FSCACHE)
+ return;
if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2)
drop_nlink(inode);
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 087/235] mtd: maps: vmu-flash: fix fault in unaligned fixup
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (85 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 086/235] 9p: skip nlink update in cacheless mode to fix WARN_ON Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 088/235] net: thunderbolt: Fix frags[] overflow by bounding frame_count Greg Kroah-Hartman
` (150 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Florian Fuchs, Miquel Raynal,
Sasha Levin
5.10-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] 239+ messages in thread
* [PATCH 5.10 088/235] net: thunderbolt: Fix frags[] overflow by bounding frame_count
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (86 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 087/235] mtd: maps: vmu-flash: fix fault in unaligned fixup Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 089/235] taskstats: fill_stats_for_tgid: use for_each_thread() Greg Kroah-Hartman
` (149 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Maoyi Xie, Mika Westerberg,
Jakub Kicinski, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maoyi Xie <maoyixie.tju@gmail.com>
[ Upstream commit 55d9895f89970501fe126d1026b586b04a224c27 ]
tbnet_poll() assembles a multi-frame ThunderboltIP packet into one skb. The
first frame goes into the skb linear area and every further frame is added as
a page fragment.
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
page, hdr_size, frame_size,
TBNET_RX_PAGE_SIZE - hdr_size);
A packet of frame_count frames therefore ends up with frame_count - 1
fragments. tbnet_check_frame() only bounds the peer supplied frame_count to
TBNET_RING_SIZE / 4 (64), which is far above MAX_SKB_FRAGS (17 by default). A
peer that sends a packet of 19 or more small frames pushes nr_frags past
MAX_SKB_FRAGS, so skb_add_rx_frag() writes past skb_shinfo()->frags[] and
corrupts memory after the shared info.
Tighten the start of packet bound to MAX_SKB_FRAGS + 1 so a packet can never
produce more fragments than frags[] can hold. This matches the recent skb
frags overflow fixes in other receive paths, for example f0813bcd2d9d ("net:
wwan: t7xx: fix potential skb->frags overflow in RX path") and 600dc40554dc
("net: usb: cdc-phonet: fix skb frags[] overflow in rx_complete()").
Fixes: e69b6c02b4c3 ("net: Add support for networking over Thunderbolt cable")
Cc: stable@vger.kernel.org
Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Link: https://patch.msgid.link/178163152194.2486768.14724194232649760778@maoyixie.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/thunderbolt.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
--- a/drivers/net/thunderbolt.c
+++ b/drivers/net/thunderbolt.c
@@ -724,8 +724,12 @@ static bool tbnet_check_frame(struct tbn
return true;
}
- /* Start of packet, validate the frame header */
- if (frame_count == 0 || frame_count > TBNET_RING_SIZE / 4) {
+ /* Start of packet, validate the frame header. tbnet_poll() puts the
+ * first frame in the skb linear area and every further frame in a page
+ * fragment, so a packet may not span more than MAX_SKB_FRAGS + 1 frames
+ * without overflowing skb_shinfo()->frags[].
+ */
+ if (frame_count == 0 || frame_count > MAX_SKB_FRAGS + 1) {
net->stats.rx_length_errors++;
return false;
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 089/235] taskstats: fill_stats_for_tgid: use for_each_thread()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (87 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 088/235] net: thunderbolt: Fix frags[] overflow by bounding frame_count Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 090/235] taskstats: retain dead thread stats in TGID queries Greg Kroah-Hartman
` (148 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Oleg Nesterov, Eric W. Biederman,
Andrew Morton, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oleg Nesterov <oleg@redhat.com>
[ Upstream commit ed5378a387fd7c382497f2abcf4605e030b64044 ]
do/while_each_thread should be avoided when possible.
Plus I _think_ this change allows to avoid lock_task_sighand() but I am
not sure, I forgot everything about taskstats. In any case, this code
does not look right in that the same thread can be accounted twice:
taskstats_exit() can account the exiting thread in signal->stats and drop
->siglock but this thread is still on the thread-group list, so
lock_task_sighand() can't help.
Link: https://lkml.kernel.org/r/20230909214951.GA24274@redhat.com
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Cc: Eric W. Biederman <ebiederm@xmission.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Stable-dep-of: b3e4fbb04220 ("taskstats: retain dead thread stats in TGID queries")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
kernel/taskstats.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
--- a/kernel/taskstats.c
+++ b/kernel/taskstats.c
@@ -211,9 +211,8 @@ static int fill_stats_for_tgid(pid_t tgi
else
memset(stats, 0, sizeof(*stats));
- tsk = first;
start_time = ktime_get_ns();
- do {
+ for_each_thread(first, tsk) {
if (tsk->exit_state)
continue;
/*
@@ -236,7 +235,7 @@ static int fill_stats_for_tgid(pid_t tgi
stats->nvcsw += tsk->nvcsw;
stats->nivcsw += tsk->nivcsw;
- } while_each_thread(first, tsk);
+ }
unlock_task_sighand(first, &flags);
rc = 0;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 090/235] taskstats: retain dead thread stats in TGID queries
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (88 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 089/235] taskstats: fill_stats_for_tgid: use for_each_thread() Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 091/235] mtd: spi-nor: sst: remove global protection flag Greg Kroah-Hartman
` (147 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yiyang Chen, Balbir Singh,
Dr. Thomas Orgis, Oleg Nesterov, Wang Yaxin, Yang Yang,
Andrew Morton, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yiyang Chen <cyyzero16@gmail.com>
[ Upstream commit b3e4fbb04220efc3bc022bcf31b5689d39c6b111 ]
Patch series "taskstats: fix TGID dead-thread stat retention", v3.
This series fixes a taskstats TGID aggregation bug where fields added in
the TGID query path were not preserved after thread exit, and adds a
kselftest covering the regression.
The first patch keeps the cached TGID aggregate used for dead threads in
step with the fields already accumulated for live threads, and also fixes
the final TGID exit notification emitted when group_dead is true.
The second patch adds a kselftest that verifies TGID CPU stats do not
regress after a worker thread exits and has been reaped.
This patch (of 2):
fill_stats_for_tgid() builds TGID stats from two sources: the cached
aggregate in signal->stats and a scan of the live threads in the group.
However, fill_tgid_exit() only accumulates delay accounting into
signal->stats. This means that once a thread exits, TGID queries lose the
fields that fill_stats_for_tgid() adds for live threads.
This gap was introduced incrementally by two earlier changes that extended
fill_stats_for_tgid() but did not make the corresponding update to
fill_tgid_exit():
- commit 8c733420bdd5 ("taskstats: add e/u/stime for TGID command")
added ac_etime, ac_utime, and ac_stime to the TGID query path.
- commit b663a79c1915 ("taskstats: add context-switch counters")
added nvcsw and nivcsw to the TGID query path.
As a result, those fields were accounted for live threads in TGID queries,
but were dropped from the cached TGID aggregate after thread exit. The
final TGID exit notification emitted when group_dead is true also copies
that cached aggregate, so it loses the same fields.
Factor the per-task TGID accumulation into tgid_stats_add_task() and use
it in both fill_stats_for_tgid() and fill_tgid_exit(). This keeps the
cached aggregate used for dead threads aligned with the live-thread
accumulation used by TGID queries.
Link: https://lore.kernel.org/cover.1776094300.git.cyyzero16@gmail.com
Link: https://lore.kernel.org/abd2a15d33343636ab5ba43d540bcfe508bd66c7.1776094300.git.cyyzero16@gmail.com
Fixes: 8c733420bdd5 ("taskstats: add e/u/stime for TGID command")
Fixes: b663a79c1915 ("taskstats: add context-switch counters")
Signed-off-by: Yiyang Chen <cyyzero16@gmail.com>
Acked-by: Balbir Singh <balbirs@nvidia.com>
Cc: Dr. Thomas Orgis <thomas.orgis@uni-hamburg.de>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Wang Yaxin <wang.yaxin@zte.com.cn>
Cc: Yang Yang <yang.yang29@zte.com.cn>
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>
---
kernel/taskstats.c | 62 ++++++++++++++++++++++++++++-------------------------
1 file changed, 33 insertions(+), 29 deletions(-)
--- a/kernel/taskstats.c
+++ b/kernel/taskstats.c
@@ -188,13 +188,39 @@ static int fill_stats_for_pid(pid_t pid,
return 0;
}
+static void tgid_stats_add_task(struct taskstats *stats,
+ struct task_struct *tsk, u64 now_ns)
+{
+ u64 delta, utime, stime;
+
+ /*
+ * Each accounting subsystem calls its functions here to
+ * accumulate its per-task stats for tsk, into the per-tgid structure
+ *
+ * per-task-foo(stats, tsk);
+ */
+ delayacct_add_tsk(stats, tsk);
+
+ /* calculate task elapsed time in nsec */
+ delta = now_ns - tsk->start_time;
+ /* Convert to micro seconds */
+ do_div(delta, NSEC_PER_USEC);
+ stats->ac_etime += delta;
+
+ task_cputime(tsk, &utime, &stime);
+ stats->ac_utime += div_u64(utime, NSEC_PER_USEC);
+ stats->ac_stime += div_u64(stime, NSEC_PER_USEC);
+
+ stats->nvcsw += tsk->nvcsw;
+ stats->nivcsw += tsk->nivcsw;
+}
+
static int fill_stats_for_tgid(pid_t tgid, struct taskstats *stats)
{
struct task_struct *tsk, *first;
unsigned long flags;
int rc = -ESRCH;
- u64 delta, utime, stime;
- u64 start_time;
+ u64 now_ns;
/*
* Add additional stats from live tasks except zombie thread group
@@ -211,30 +237,12 @@ static int fill_stats_for_tgid(pid_t tgi
else
memset(stats, 0, sizeof(*stats));
- start_time = ktime_get_ns();
+ now_ns = ktime_get_ns();
for_each_thread(first, tsk) {
if (tsk->exit_state)
continue;
- /*
- * Accounting subsystem can call its functions here to
- * fill in relevant parts of struct taskstsats as follows
- *
- * per-task-foo(stats, tsk);
- */
- delayacct_add_tsk(stats, tsk);
-
- /* calculate task elapsed time in nsec */
- delta = start_time - tsk->start_time;
- /* Convert to micro seconds */
- do_div(delta, NSEC_PER_USEC);
- stats->ac_etime += delta;
-
- task_cputime(tsk, &utime, &stime);
- stats->ac_utime += div_u64(utime, NSEC_PER_USEC);
- stats->ac_stime += div_u64(stime, NSEC_PER_USEC);
- stats->nvcsw += tsk->nvcsw;
- stats->nivcsw += tsk->nivcsw;
+ tgid_stats_add_task(stats, tsk, now_ns);
}
unlock_task_sighand(first, &flags);
@@ -253,18 +261,14 @@ out:
static void fill_tgid_exit(struct task_struct *tsk)
{
unsigned long flags;
+ u64 now_ns;
spin_lock_irqsave(&tsk->sighand->siglock, flags);
if (!tsk->signal->stats)
goto ret;
- /*
- * Each accounting subsystem calls its functions here to
- * accumalate its per-task stats for tsk, into the per-tgid structure
- *
- * per-task-foo(tsk->signal->stats, tsk);
- */
- delayacct_add_tsk(tsk->signal->stats, tsk);
+ now_ns = ktime_get_ns();
+ tgid_stats_add_task(tsk->signal->stats, tsk, now_ns);
ret:
spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
return;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 091/235] mtd: spi-nor: sst: remove global protection flag
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (89 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 090/235] taskstats: retain dead thread stats in TGID queries Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 092/235] mtd: spi-nor: intel: " Greg Kroah-Hartman
` (146 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Michael Walle, Vignesh Raghavendra,
Tudor Ambarus, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Walle <michael@walle.cc>
[ Upstream commit a833383732116c2afe665520bbe6951999631ef1 ]
This is considered bad for the following reasons:
(1) We only support the block protection with BPn bits for write
protection. Not all SST parts support this.
(2) Newly added flash chip will automatically inherit the "has
locking" support and thus needs to explicitly tested. Better
be opt-in instead of opt-out.
(3) There are already supported flashes which doesn't support
the locking scheme. So I assume this wasn't properly tested
before adding that chip; which enforces my previous argument
that locking support should be an opt-in.
Remove the global flag and add individual flags to all flashes
which supports BP locking. In particular the following flashes
don't support the BP scheme:
- SST26VF016B
- SST26WF016B
- SST26VF064B
Signed-off-by: Michael Walle <michael@walle.cc>
Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
Reviewed-by: Tudor Ambarus <tudor.ambarus@microchip.com>
Link: https://lore.kernel.org/r/20201203162959.29589-5-michael@walle.cc
Stable-dep-of: e1d456b26bf2 ("mtd: spi-nor: swp: Improve locking user experience")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/mtd/spi-nor/sst.c | 30 ++++++++++++------------------
1 file changed, 12 insertions(+), 18 deletions(-)
--- a/drivers/mtd/spi-nor/sst.c
+++ b/drivers/mtd/spi-nor/sst.c
@@ -11,27 +11,27 @@
static const struct flash_info sst_parts[] = {
/* SST -- large erase sizes are "overlays", "sectors" are 4K */
{ "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8,
- SECT_4K | SST_WRITE) },
+ SECT_4K | SST_WRITE | SPI_NOR_HAS_LOCK) },
{ "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16,
- SECT_4K | SST_WRITE) },
+ SECT_4K | SST_WRITE | SPI_NOR_HAS_LOCK) },
{ "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32,
- SECT_4K | SST_WRITE) },
+ SECT_4K | SST_WRITE | SPI_NOR_HAS_LOCK) },
{ "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64,
- SECT_4K | SST_WRITE) },
+ SECT_4K | SST_WRITE | SPI_NOR_HAS_LOCK) },
{ "sst25vf064c", INFO(0xbf254b, 0, 64 * 1024, 128,
- SECT_4K | SPI_NOR_4BIT_BP) },
+ SECT_4K | SPI_NOR_4BIT_BP | SPI_NOR_HAS_LOCK) },
{ "sst25wf512", INFO(0xbf2501, 0, 64 * 1024, 1,
- SECT_4K | SST_WRITE) },
+ SECT_4K | SST_WRITE | SPI_NOR_HAS_LOCK) },
{ "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2,
- SECT_4K | SST_WRITE) },
+ SECT_4K | SST_WRITE | SPI_NOR_HAS_LOCK) },
{ "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4,
- SECT_4K | SST_WRITE) },
- { "sst25wf020a", INFO(0x621612, 0, 64 * 1024, 4, SECT_4K) },
- { "sst25wf040b", INFO(0x621613, 0, 64 * 1024, 8, SECT_4K) },
+ SECT_4K | SST_WRITE | SPI_NOR_HAS_LOCK) },
+ { "sst25wf020a", INFO(0x621612, 0, 64 * 1024, 4, SECT_4K | SPI_NOR_HAS_LOCK) },
+ { "sst25wf040b", INFO(0x621613, 0, 64 * 1024, 8, SECT_4K | SPI_NOR_HAS_LOCK) },
{ "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8,
- SECT_4K | SST_WRITE) },
+ SECT_4K | SST_WRITE | SPI_NOR_HAS_LOCK) },
{ "sst25wf080", INFO(0xbf2505, 0, 64 * 1024, 16,
- SECT_4K | SST_WRITE) },
+ SECT_4K | SST_WRITE | SPI_NOR_HAS_LOCK) },
{ "sst26wf016b", INFO(0xbf2651, 0, 64 * 1024, 32,
SECT_4K | SPI_NOR_DUAL_READ |
SPI_NOR_QUAD_READ) },
@@ -141,11 +141,6 @@ out:
return ret;
}
-static void sst_default_init(struct spi_nor *nor)
-{
- nor->flags |= SNOR_F_HAS_LOCK;
-}
-
static void sst_post_sfdp_fixups(struct spi_nor *nor)
{
if (nor->info->flags & SST_WRITE)
@@ -153,7 +148,6 @@ static void sst_post_sfdp_fixups(struct
}
static const struct spi_nor_fixups sst_fixups = {
- .default_init = sst_default_init,
.post_sfdp = sst_post_sfdp_fixups,
};
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 092/235] mtd: spi-nor: intel: remove global protection flag
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (90 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 091/235] mtd: spi-nor: sst: remove global protection flag Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 093/235] mtd: spi-nor: Move Software Write Protection logic out of the core Greg Kroah-Hartman
` (145 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Michael Walle, Vignesh Raghavendra,
Tudor Ambarus, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Walle <michael@walle.cc>
[ Upstream commit afcf93e9d63fc1e15935a2df9457f803394e4f20 ]
For the Atmel and SST parts this flag was already moved to individual
flash parts because it is considered bad esp. because newer flash chips
will automatically inherit the "has locking" support. While this won't
likely be the case for the Intel parts, we do it for consistency
reasons.
Signed-off-by: Michael Walle <michael@walle.cc>
Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
Reviewed-by: Tudor Ambarus <tudor.ambarus@microchip.com>
Link: https://lore.kernel.org/r/20201203162959.29589-6-michael@walle.cc
Stable-dep-of: e1d456b26bf2 ("mtd: spi-nor: swp: Improve locking user experience")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/mtd/spi-nor/intel.c | 16 +++-------------
1 file changed, 3 insertions(+), 13 deletions(-)
--- a/drivers/mtd/spi-nor/intel.c
+++ b/drivers/mtd/spi-nor/intel.c
@@ -10,23 +10,13 @@
static const struct flash_info intel_parts[] = {
/* Intel/Numonyx -- xxxs33b */
- { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) },
- { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) },
- { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) },
-};
-
-static void intel_default_init(struct spi_nor *nor)
-{
- nor->flags |= SNOR_F_HAS_LOCK;
-}
-
-static const struct spi_nor_fixups intel_fixups = {
- .default_init = intel_default_init,
+ { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, SPI_NOR_HAS_LOCK) },
+ { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, SPI_NOR_HAS_LOCK) },
+ { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, SPI_NOR_HAS_LOCK) },
};
const struct spi_nor_manufacturer spi_nor_intel = {
.name = "intel",
.parts = intel_parts,
.nparts = ARRAY_SIZE(intel_parts),
- .fixups = &intel_fixups,
};
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 093/235] mtd: spi-nor: Move Software Write Protection logic out of the core
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (91 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 092/235] mtd: spi-nor: intel: " Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 094/235] mtd: spi-nor: Fix spi_nor_try_unlock_all() Greg Kroah-Hartman
` (144 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Tudor Ambarus, Michael Walle,
Pratyush Yadav, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tudor Ambarus <tudor.ambarus@microchip.com>
[ Upstream commit c4c795105f2924c80752c30ffd3c7029a8e0ef28 ]
It makes the core file a bit smaller and provides better separation
between the Software Write Protection features and the core logic.
All the next generic software write protection features (e.g. Individual
Block Protection) will reside in swp.c.
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
Reviewed-by: Michael Walle <michael@walle.cc>
Acked-by: Pratyush Yadav <p.yadav@ti.com>
Link: https://lore.kernel.org/r/20210322075131.45093-2-tudor.ambarus@microchip.com
Stable-dep-of: e1d456b26bf2 ("mtd: spi-nor: swp: Improve locking user experience")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/mtd/spi-nor/Makefile | 2
drivers/mtd/spi-nor/core.c | 406 -----------------------------------------
drivers/mtd/spi-nor/core.h | 5
drivers/mtd/spi-nor/swp.c | 421 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 431 insertions(+), 403 deletions(-)
create mode 100644 drivers/mtd/spi-nor/swp.c
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
-spi-nor-objs := core.o sfdp.o
+spi-nor-objs := core.o sfdp.o swp.o
spi-nor-objs += atmel.o
spi-nor-objs += catalyst.o
spi-nor-objs += eon.o
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -276,7 +276,7 @@ int spi_nor_write_disable(struct spi_nor
*
* Return: 0 on success, -errno otherwise.
*/
-static int spi_nor_read_sr(struct spi_nor *nor, u8 *sr)
+int spi_nor_read_sr(struct spi_nor *nor, u8 *sr)
{
int ret;
@@ -1550,376 +1550,6 @@ erase_err:
return ret;
}
-static u8 spi_nor_get_sr_bp_mask(struct spi_nor *nor)
-{
- u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
-
- if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6)
- return mask | SR_BP3_BIT6;
-
- if (nor->flags & SNOR_F_HAS_4BIT_BP)
- return mask | SR_BP3;
-
- return mask;
-}
-
-static u8 spi_nor_get_sr_tb_mask(struct spi_nor *nor)
-{
- if (nor->flags & SNOR_F_HAS_SR_TB_BIT6)
- return SR_TB_BIT6;
- else
- return SR_TB_BIT5;
-}
-
-static u64 spi_nor_get_min_prot_length_sr(struct spi_nor *nor)
-{
- unsigned int bp_slots, bp_slots_needed;
- u8 mask = spi_nor_get_sr_bp_mask(nor);
-
- /* Reserved one for "protect none" and one for "protect all". */
- bp_slots = (1 << hweight8(mask)) - 2;
- bp_slots_needed = ilog2(nor->info->n_sectors);
-
- if (bp_slots_needed > bp_slots)
- return nor->info->sector_size <<
- (bp_slots_needed - bp_slots);
- else
- return nor->info->sector_size;
-}
-
-static void spi_nor_get_locked_range_sr(struct spi_nor *nor, u8 sr, loff_t *ofs,
- uint64_t *len)
-{
- struct mtd_info *mtd = &nor->mtd;
- u64 min_prot_len;
- u8 mask = spi_nor_get_sr_bp_mask(nor);
- u8 tb_mask = spi_nor_get_sr_tb_mask(nor);
- u8 bp, val = sr & mask;
-
- if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6 && val & SR_BP3_BIT6)
- val = (val & ~SR_BP3_BIT6) | SR_BP3;
-
- bp = val >> SR_BP_SHIFT;
-
- if (!bp) {
- /* No protection */
- *ofs = 0;
- *len = 0;
- return;
- }
-
- min_prot_len = spi_nor_get_min_prot_length_sr(nor);
- *len = min_prot_len << (bp - 1);
-
- if (*len > mtd->size)
- *len = mtd->size;
-
- if (nor->flags & SNOR_F_HAS_SR_TB && sr & tb_mask)
- *ofs = 0;
- else
- *ofs = mtd->size - *len;
-}
-
-/*
- * Return 1 if the entire region is locked (if @locked is true) or unlocked (if
- * @locked is false); 0 otherwise
- */
-static int spi_nor_check_lock_status_sr(struct spi_nor *nor, loff_t ofs,
- uint64_t len, u8 sr, bool locked)
-{
- loff_t lock_offs;
- uint64_t lock_len;
-
- if (!len)
- return 1;
-
- spi_nor_get_locked_range_sr(nor, sr, &lock_offs, &lock_len);
-
- if (locked)
- /* Requested range is a sub-range of locked range */
- return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs);
- else
- /* Requested range does not overlap with locked range */
- return (ofs >= lock_offs + lock_len) || (ofs + len <= lock_offs);
-}
-
-static int spi_nor_is_locked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len,
- u8 sr)
-{
- return spi_nor_check_lock_status_sr(nor, ofs, len, sr, true);
-}
-
-static int spi_nor_is_unlocked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len,
- u8 sr)
-{
- return spi_nor_check_lock_status_sr(nor, ofs, len, sr, false);
-}
-
-/*
- * Lock a region of the flash. Compatible with ST Micro and similar flash.
- * Supports the block protection bits BP{0,1,2}/BP{0,1,2,3} in the status
- * register
- * (SR). Does not support these features found in newer SR bitfields:
- * - SEC: sector/block protect - only handle SEC=0 (block protect)
- * - CMP: complement protect - only support CMP=0 (range is not complemented)
- *
- * Support for the following is provided conditionally for some flash:
- * - TB: top/bottom protect
- *
- * Sample table portion for 8MB flash (Winbond w25q64fw):
- *
- * SEC | TB | BP2 | BP1 | BP0 | Prot Length | Protected Portion
- * --------------------------------------------------------------------------
- * X | X | 0 | 0 | 0 | NONE | NONE
- * 0 | 0 | 0 | 0 | 1 | 128 KB | Upper 1/64
- * 0 | 0 | 0 | 1 | 0 | 256 KB | Upper 1/32
- * 0 | 0 | 0 | 1 | 1 | 512 KB | Upper 1/16
- * 0 | 0 | 1 | 0 | 0 | 1 MB | Upper 1/8
- * 0 | 0 | 1 | 0 | 1 | 2 MB | Upper 1/4
- * 0 | 0 | 1 | 1 | 0 | 4 MB | Upper 1/2
- * X | X | 1 | 1 | 1 | 8 MB | ALL
- * ------|-------|-------|-------|-------|---------------|-------------------
- * 0 | 1 | 0 | 0 | 1 | 128 KB | Lower 1/64
- * 0 | 1 | 0 | 1 | 0 | 256 KB | Lower 1/32
- * 0 | 1 | 0 | 1 | 1 | 512 KB | Lower 1/16
- * 0 | 1 | 1 | 0 | 0 | 1 MB | Lower 1/8
- * 0 | 1 | 1 | 0 | 1 | 2 MB | Lower 1/4
- * 0 | 1 | 1 | 1 | 0 | 4 MB | Lower 1/2
- *
- * Returns negative on errors, 0 on success.
- */
-static int spi_nor_sr_lock(struct spi_nor *nor, loff_t ofs, uint64_t len)
-{
- struct mtd_info *mtd = &nor->mtd;
- u64 min_prot_len;
- int ret, status_old, status_new;
- u8 mask = spi_nor_get_sr_bp_mask(nor);
- u8 tb_mask = spi_nor_get_sr_tb_mask(nor);
- u8 pow, val;
- loff_t lock_len;
- bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB;
- bool use_top;
-
- ret = spi_nor_read_sr(nor, nor->bouncebuf);
- if (ret)
- return ret;
-
- status_old = nor->bouncebuf[0];
-
- /* If nothing in our range is unlocked, we don't need to do anything */
- if (spi_nor_is_locked_sr(nor, ofs, len, status_old))
- return 0;
-
- /* If anything below us is unlocked, we can't use 'bottom' protection */
- if (!spi_nor_is_locked_sr(nor, 0, ofs, status_old))
- can_be_bottom = false;
-
- /* If anything above us is unlocked, we can't use 'top' protection */
- if (!spi_nor_is_locked_sr(nor, ofs + len, mtd->size - (ofs + len),
- status_old))
- can_be_top = false;
-
- if (!can_be_bottom && !can_be_top)
- return -EINVAL;
-
- /* Prefer top, if both are valid */
- use_top = can_be_top;
-
- /* lock_len: length of region that should end up locked */
- if (use_top)
- lock_len = mtd->size - ofs;
- else
- lock_len = ofs + len;
-
- if (lock_len == mtd->size) {
- val = mask;
- } else {
- min_prot_len = spi_nor_get_min_prot_length_sr(nor);
- pow = ilog2(lock_len) - ilog2(min_prot_len) + 1;
- val = pow << SR_BP_SHIFT;
-
- if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6 && val & SR_BP3)
- val = (val & ~SR_BP3) | SR_BP3_BIT6;
-
- if (val & ~mask)
- return -EINVAL;
-
- /* Don't "lock" with no region! */
- if (!(val & mask))
- return -EINVAL;
- }
-
- status_new = (status_old & ~mask & ~tb_mask) | val;
-
- /* Disallow further writes if WP pin is asserted */
- status_new |= SR_SRWD;
-
- if (!use_top)
- status_new |= tb_mask;
-
- /* Don't bother if they're the same */
- if (status_new == status_old)
- return 0;
-
- /* Only modify protection if it will not unlock other areas */
- if ((status_new & mask) < (status_old & mask))
- return -EINVAL;
-
- return spi_nor_write_sr_and_check(nor, status_new);
-}
-
-/*
- * Unlock a region of the flash. See spi_nor_sr_lock() for more info
- *
- * Returns negative on errors, 0 on success.
- */
-static int spi_nor_sr_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len)
-{
- struct mtd_info *mtd = &nor->mtd;
- u64 min_prot_len;
- int ret, status_old, status_new;
- u8 mask = spi_nor_get_sr_bp_mask(nor);
- u8 tb_mask = spi_nor_get_sr_tb_mask(nor);
- u8 pow, val;
- loff_t lock_len;
- bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB;
- bool use_top;
-
- ret = spi_nor_read_sr(nor, nor->bouncebuf);
- if (ret)
- return ret;
-
- status_old = nor->bouncebuf[0];
-
- /* If nothing in our range is locked, we don't need to do anything */
- if (spi_nor_is_unlocked_sr(nor, ofs, len, status_old))
- return 0;
-
- /* If anything below us is locked, we can't use 'top' protection */
- if (!spi_nor_is_unlocked_sr(nor, 0, ofs, status_old))
- can_be_top = false;
-
- /* If anything above us is locked, we can't use 'bottom' protection */
- if (!spi_nor_is_unlocked_sr(nor, ofs + len, mtd->size - (ofs + len),
- status_old))
- can_be_bottom = false;
-
- if (!can_be_bottom && !can_be_top)
- return -EINVAL;
-
- /* Prefer top, if both are valid */
- use_top = can_be_top;
-
- /* lock_len: length of region that should remain locked */
- if (use_top)
- lock_len = mtd->size - (ofs + len);
- else
- lock_len = ofs;
-
- if (lock_len == 0) {
- val = 0; /* fully unlocked */
- } else {
- min_prot_len = spi_nor_get_min_prot_length_sr(nor);
- pow = ilog2(lock_len) - ilog2(min_prot_len) + 1;
- val = pow << SR_BP_SHIFT;
-
- if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6 && val & SR_BP3)
- val = (val & ~SR_BP3) | SR_BP3_BIT6;
-
- /* Some power-of-two sizes are not supported */
- if (val & ~mask)
- return -EINVAL;
- }
-
- status_new = (status_old & ~mask & ~tb_mask) | val;
-
- /* Don't protect status register if we're fully unlocked */
- if (lock_len == 0)
- status_new &= ~SR_SRWD;
-
- if (!use_top)
- status_new |= tb_mask;
-
- /* Don't bother if they're the same */
- if (status_new == status_old)
- return 0;
-
- /* Only modify protection if it will not lock other areas */
- if ((status_new & mask) > (status_old & mask))
- return -EINVAL;
-
- return spi_nor_write_sr_and_check(nor, status_new);
-}
-
-/*
- * Check if a region of the flash is (completely) locked. See spi_nor_sr_lock()
- * for more info.
- *
- * Returns 1 if entire region is locked, 0 if any portion is unlocked, and
- * negative on errors.
- */
-static int spi_nor_sr_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len)
-{
- int ret;
-
- ret = spi_nor_read_sr(nor, nor->bouncebuf);
- if (ret)
- return ret;
-
- return spi_nor_is_locked_sr(nor, ofs, len, nor->bouncebuf[0]);
-}
-
-static const struct spi_nor_locking_ops spi_nor_sr_locking_ops = {
- .lock = spi_nor_sr_lock,
- .unlock = spi_nor_sr_unlock,
- .is_locked = spi_nor_sr_is_locked,
-};
-
-static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
-{
- struct spi_nor *nor = mtd_to_spi_nor(mtd);
- int ret;
-
- ret = spi_nor_lock_and_prep(nor);
- if (ret)
- return ret;
-
- ret = nor->params->locking_ops->lock(nor, ofs, len);
-
- spi_nor_unlock_and_unprep(nor);
- return ret;
-}
-
-static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
-{
- struct spi_nor *nor = mtd_to_spi_nor(mtd);
- int ret;
-
- ret = spi_nor_lock_and_prep(nor);
- if (ret)
- return ret;
-
- ret = nor->params->locking_ops->unlock(nor, ofs, len);
-
- spi_nor_unlock_and_unprep(nor);
- return ret;
-}
-
-static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
-{
- struct spi_nor *nor = mtd_to_spi_nor(mtd);
- int ret;
-
- ret = spi_nor_lock_and_prep(nor);
- if (ret)
- return ret;
-
- ret = nor->params->locking_ops->is_locked(nor, ofs, len);
-
- spi_nor_unlock_and_unprep(nor);
- return ret;
-}
-
/**
* spi_nor_sr1_bit6_quad_enable() - Set the Quad Enable BIT(6) in the Status
* Register 1.
@@ -2858,7 +2488,7 @@ static void spi_nor_late_init_params(str
* the default ones.
*/
if (nor->flags & SNOR_F_HAS_LOCK && !nor->params->locking_ops)
- nor->params->locking_ops = &spi_nor_sr_locking_ops;
+ spi_nor_init_default_locking_ops(nor);
}
/**
@@ -2937,30 +2567,6 @@ static int spi_nor_quad_enable(struct sp
return nor->params->quad_enable(nor);
}
-/**
- * spi_nor_try_unlock_all() - Tries to unlock the entire flash memory array.
- * @nor: pointer to a 'struct spi_nor'.
- *
- * Some SPI NOR flashes are write protected by default after a power-on reset
- * cycle, in order to avoid inadvertent writes during power-up. Backward
- * compatibility imposes to unlock the entire flash memory array at power-up
- * by default.
- *
- * Unprotecting the entire flash array will fail for boards which are hardware
- * write-protected. Thus any errors are ignored.
- */
-static void spi_nor_try_unlock_all(struct spi_nor *nor)
-{
- int ret;
-
- if (!(nor->flags & SNOR_F_HAS_LOCK))
- return;
-
- ret = spi_nor_unlock(&nor->mtd, 0, nor->params->size);
- if (ret)
- dev_dbg(nor->dev, "Failed to unlock the entire flash memory array\n");
-}
-
static int spi_nor_init(struct spi_nor *nor)
{
int err;
@@ -3212,12 +2818,6 @@ int spi_nor_scan(struct spi_nor *nor, co
mtd->_get_device = spi_nor_get_device;
mtd->_put_device = spi_nor_put_device;
- if (nor->params->locking_ops) {
- mtd->_lock = spi_nor_lock;
- mtd->_unlock = spi_nor_unlock;
- mtd->_is_locked = spi_nor_is_locked;
- }
-
if (info->flags & USE_FSR)
nor->flags |= SNOR_F_USE_FSR;
if (info->flags & SPI_NOR_HAS_TB) {
@@ -3264,6 +2864,8 @@ int spi_nor_scan(struct spi_nor *nor, co
if (ret)
return ret;
+ spi_nor_register_locking_ops(nor);
+
/* Send all the required SPI flash commands to initialize device */
ret = spi_nor_init(nor);
if (ret)
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -409,6 +409,7 @@ void spi_nor_unlock_and_unprep(struct sp
int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor);
int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor);
int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor);
+int spi_nor_read_sr(struct spi_nor *nor, u8 *sr);
int spi_nor_write_sr_and_check(struct spi_nor *nor, u8 sr1);
int spi_nor_xread_sr(struct spi_nor *nor, u8 *sr);
@@ -435,6 +436,10 @@ int spi_nor_post_bfpt_fixups(struct spi_
const struct sfdp_bfpt *bfpt,
struct spi_nor_flash_parameter *params);
+void spi_nor_init_default_locking_ops(struct spi_nor *nor);
+void spi_nor_try_unlock_all(struct spi_nor *nor);
+void spi_nor_register_locking_ops(struct spi_nor *nor);
+
static struct spi_nor __maybe_unused *mtd_to_spi_nor(struct mtd_info *mtd)
{
return mtd->priv;
--- /dev/null
+++ b/drivers/mtd/spi-nor/swp.c
@@ -0,0 +1,421 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SPI NOR Software Write Protection logic.
+ *
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static u8 spi_nor_get_sr_bp_mask(struct spi_nor *nor)
+{
+ u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
+
+ if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6)
+ return mask | SR_BP3_BIT6;
+
+ if (nor->flags & SNOR_F_HAS_4BIT_BP)
+ return mask | SR_BP3;
+
+ return mask;
+}
+
+static u8 spi_nor_get_sr_tb_mask(struct spi_nor *nor)
+{
+ if (nor->flags & SNOR_F_HAS_SR_TB_BIT6)
+ return SR_TB_BIT6;
+ else
+ return SR_TB_BIT5;
+}
+
+static u64 spi_nor_get_min_prot_length_sr(struct spi_nor *nor)
+{
+ unsigned int bp_slots, bp_slots_needed;
+ u8 mask = spi_nor_get_sr_bp_mask(nor);
+
+ /* Reserved one for "protect none" and one for "protect all". */
+ bp_slots = (1 << hweight8(mask)) - 2;
+ bp_slots_needed = ilog2(nor->info->n_sectors);
+
+ if (bp_slots_needed > bp_slots)
+ return nor->info->sector_size <<
+ (bp_slots_needed - bp_slots);
+ else
+ return nor->info->sector_size;
+}
+
+static void spi_nor_get_locked_range_sr(struct spi_nor *nor, u8 sr, loff_t *ofs,
+ uint64_t *len)
+{
+ struct mtd_info *mtd = &nor->mtd;
+ u64 min_prot_len;
+ u8 mask = spi_nor_get_sr_bp_mask(nor);
+ u8 tb_mask = spi_nor_get_sr_tb_mask(nor);
+ u8 bp, val = sr & mask;
+
+ if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6 && val & SR_BP3_BIT6)
+ val = (val & ~SR_BP3_BIT6) | SR_BP3;
+
+ bp = val >> SR_BP_SHIFT;
+
+ if (!bp) {
+ /* No protection */
+ *ofs = 0;
+ *len = 0;
+ return;
+ }
+
+ min_prot_len = spi_nor_get_min_prot_length_sr(nor);
+ *len = min_prot_len << (bp - 1);
+
+ if (*len > mtd->size)
+ *len = mtd->size;
+
+ if (nor->flags & SNOR_F_HAS_SR_TB && sr & tb_mask)
+ *ofs = 0;
+ else
+ *ofs = mtd->size - *len;
+}
+
+/*
+ * Return 1 if the entire region is locked (if @locked is true) or unlocked (if
+ * @locked is false); 0 otherwise
+ */
+static int spi_nor_check_lock_status_sr(struct spi_nor *nor, loff_t ofs,
+ uint64_t len, u8 sr, bool locked)
+{
+ loff_t lock_offs;
+ uint64_t lock_len;
+
+ if (!len)
+ return 1;
+
+ spi_nor_get_locked_range_sr(nor, sr, &lock_offs, &lock_len);
+
+ if (locked)
+ /* Requested range is a sub-range of locked range */
+ return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs);
+ else
+ /* Requested range does not overlap with locked range */
+ return (ofs >= lock_offs + lock_len) || (ofs + len <= lock_offs);
+}
+
+static int spi_nor_is_locked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len,
+ u8 sr)
+{
+ return spi_nor_check_lock_status_sr(nor, ofs, len, sr, true);
+}
+
+static int spi_nor_is_unlocked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len,
+ u8 sr)
+{
+ return spi_nor_check_lock_status_sr(nor, ofs, len, sr, false);
+}
+
+/*
+ * Lock a region of the flash. Compatible with ST Micro and similar flash.
+ * Supports the block protection bits BP{0,1,2}/BP{0,1,2,3} in the status
+ * register
+ * (SR). Does not support these features found in newer SR bitfields:
+ * - SEC: sector/block protect - only handle SEC=0 (block protect)
+ * - CMP: complement protect - only support CMP=0 (range is not complemented)
+ *
+ * Support for the following is provided conditionally for some flash:
+ * - TB: top/bottom protect
+ *
+ * Sample table portion for 8MB flash (Winbond w25q64fw):
+ *
+ * SEC | TB | BP2 | BP1 | BP0 | Prot Length | Protected Portion
+ * --------------------------------------------------------------------------
+ * X | X | 0 | 0 | 0 | NONE | NONE
+ * 0 | 0 | 0 | 0 | 1 | 128 KB | Upper 1/64
+ * 0 | 0 | 0 | 1 | 0 | 256 KB | Upper 1/32
+ * 0 | 0 | 0 | 1 | 1 | 512 KB | Upper 1/16
+ * 0 | 0 | 1 | 0 | 0 | 1 MB | Upper 1/8
+ * 0 | 0 | 1 | 0 | 1 | 2 MB | Upper 1/4
+ * 0 | 0 | 1 | 1 | 0 | 4 MB | Upper 1/2
+ * X | X | 1 | 1 | 1 | 8 MB | ALL
+ * ------|-------|-------|-------|-------|---------------|-------------------
+ * 0 | 1 | 0 | 0 | 1 | 128 KB | Lower 1/64
+ * 0 | 1 | 0 | 1 | 0 | 256 KB | Lower 1/32
+ * 0 | 1 | 0 | 1 | 1 | 512 KB | Lower 1/16
+ * 0 | 1 | 1 | 0 | 0 | 1 MB | Lower 1/8
+ * 0 | 1 | 1 | 0 | 1 | 2 MB | Lower 1/4
+ * 0 | 1 | 1 | 1 | 0 | 4 MB | Lower 1/2
+ *
+ * Returns negative on errors, 0 on success.
+ */
+static int spi_nor_sr_lock(struct spi_nor *nor, loff_t ofs, uint64_t len)
+{
+ struct mtd_info *mtd = &nor->mtd;
+ u64 min_prot_len;
+ int ret, status_old, status_new;
+ u8 mask = spi_nor_get_sr_bp_mask(nor);
+ u8 tb_mask = spi_nor_get_sr_tb_mask(nor);
+ u8 pow, val;
+ loff_t lock_len;
+ bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB;
+ bool use_top;
+
+ ret = spi_nor_read_sr(nor, nor->bouncebuf);
+ if (ret)
+ return ret;
+
+ status_old = nor->bouncebuf[0];
+
+ /* If nothing in our range is unlocked, we don't need to do anything */
+ if (spi_nor_is_locked_sr(nor, ofs, len, status_old))
+ return 0;
+
+ /* If anything below us is unlocked, we can't use 'bottom' protection */
+ if (!spi_nor_is_locked_sr(nor, 0, ofs, status_old))
+ can_be_bottom = false;
+
+ /* If anything above us is unlocked, we can't use 'top' protection */
+ if (!spi_nor_is_locked_sr(nor, ofs + len, mtd->size - (ofs + len),
+ status_old))
+ can_be_top = false;
+
+ if (!can_be_bottom && !can_be_top)
+ return -EINVAL;
+
+ /* Prefer top, if both are valid */
+ use_top = can_be_top;
+
+ /* lock_len: length of region that should end up locked */
+ if (use_top)
+ lock_len = mtd->size - ofs;
+ else
+ lock_len = ofs + len;
+
+ if (lock_len == mtd->size) {
+ val = mask;
+ } else {
+ min_prot_len = spi_nor_get_min_prot_length_sr(nor);
+ pow = ilog2(lock_len) - ilog2(min_prot_len) + 1;
+ val = pow << SR_BP_SHIFT;
+
+ if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6 && val & SR_BP3)
+ val = (val & ~SR_BP3) | SR_BP3_BIT6;
+
+ if (val & ~mask)
+ return -EINVAL;
+
+ /* Don't "lock" with no region! */
+ if (!(val & mask))
+ return -EINVAL;
+ }
+
+ status_new = (status_old & ~mask & ~tb_mask) | val;
+
+ /* Disallow further writes if WP pin is asserted */
+ status_new |= SR_SRWD;
+
+ if (!use_top)
+ status_new |= tb_mask;
+
+ /* Don't bother if they're the same */
+ if (status_new == status_old)
+ return 0;
+
+ /* Only modify protection if it will not unlock other areas */
+ if ((status_new & mask) < (status_old & mask))
+ return -EINVAL;
+
+ return spi_nor_write_sr_and_check(nor, status_new);
+}
+
+/*
+ * Unlock a region of the flash. See spi_nor_sr_lock() for more info
+ *
+ * Returns negative on errors, 0 on success.
+ */
+static int spi_nor_sr_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len)
+{
+ u64 min_prot_len;
+ int ret, status_old, status_new;
+ u8 mask = spi_nor_get_sr_bp_mask(nor);
+ u8 tb_mask = spi_nor_get_sr_tb_mask(nor);
+ u8 pow, val;
+ loff_t lock_len;
+ bool can_be_top = true, can_be_bottom = nor->flags & SNOR_F_HAS_SR_TB;
+ bool use_top;
+
+ ret = spi_nor_read_sr(nor, nor->bouncebuf);
+ if (ret)
+ return ret;
+
+ status_old = nor->bouncebuf[0];
+
+ /* If nothing in our range is locked, we don't need to do anything */
+ if (spi_nor_is_unlocked_sr(nor, ofs, len, status_old))
+ return 0;
+
+ /* If anything below us is locked, we can't use 'top' protection */
+ if (!spi_nor_is_unlocked_sr(nor, 0, ofs, status_old))
+ can_be_top = false;
+
+ /* If anything above us is locked, we can't use 'bottom' protection */
+ if (!spi_nor_is_unlocked_sr(nor, ofs + len, nor->params->size - (ofs + len),
+ status_old))
+ can_be_bottom = false;
+
+ if (!can_be_bottom && !can_be_top)
+ return -EINVAL;
+
+ /* Prefer top, if both are valid */
+ use_top = can_be_top;
+
+ /* lock_len: length of region that should remain locked */
+ if (use_top)
+ lock_len = nor->params->size - (ofs + len);
+ else
+ lock_len = ofs;
+
+ if (lock_len == 0) {
+ val = 0; /* fully unlocked */
+ } else {
+ min_prot_len = spi_nor_get_min_prot_length_sr(nor);
+ pow = ilog2(lock_len) - ilog2(min_prot_len) + 1;
+ val = pow << SR_BP_SHIFT;
+
+ if (nor->flags & SNOR_F_HAS_SR_BP3_BIT6 && val & SR_BP3)
+ val = (val & ~SR_BP3) | SR_BP3_BIT6;
+
+ /* Some power-of-two sizes are not supported */
+ if (val & ~mask)
+ return -EINVAL;
+ }
+
+ status_new = (status_old & ~mask & ~tb_mask) | val;
+
+ /* Don't protect status register if we're fully unlocked */
+ if (lock_len == 0)
+ status_new &= ~SR_SRWD;
+
+ if (!use_top)
+ status_new |= tb_mask;
+
+ /* Don't bother if they're the same */
+ if (status_new == status_old)
+ return 0;
+
+ /* Only modify protection if it will not lock other areas */
+ if ((status_new & mask) > (status_old & mask))
+ return -EINVAL;
+
+ return spi_nor_write_sr_and_check(nor, status_new);
+}
+
+/*
+ * Check if a region of the flash is (completely) locked. See spi_nor_sr_lock()
+ * for more info.
+ *
+ * Returns 1 if entire region is locked, 0 if any portion is unlocked, and
+ * negative on errors.
+ */
+static int spi_nor_sr_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len)
+{
+ int ret;
+
+ ret = spi_nor_read_sr(nor, nor->bouncebuf);
+ if (ret)
+ return ret;
+
+ return spi_nor_is_locked_sr(nor, ofs, len, nor->bouncebuf[0]);
+}
+
+static const struct spi_nor_locking_ops spi_nor_sr_locking_ops = {
+ .lock = spi_nor_sr_lock,
+ .unlock = spi_nor_sr_unlock,
+ .is_locked = spi_nor_sr_is_locked,
+};
+
+void spi_nor_init_default_locking_ops(struct spi_nor *nor)
+{
+ nor->params->locking_ops = &spi_nor_sr_locking_ops;
+}
+
+static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+ struct spi_nor *nor = mtd_to_spi_nor(mtd);
+ int ret;
+
+ ret = spi_nor_lock_and_prep(nor);
+ if (ret)
+ return ret;
+
+ ret = nor->params->locking_ops->lock(nor, ofs, len);
+
+ spi_nor_unlock_and_unprep(nor);
+ return ret;
+}
+
+static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+ struct spi_nor *nor = mtd_to_spi_nor(mtd);
+ int ret;
+
+ ret = spi_nor_lock_and_prep(nor);
+ if (ret)
+ return ret;
+
+ ret = nor->params->locking_ops->unlock(nor, ofs, len);
+
+ spi_nor_unlock_and_unprep(nor);
+ return ret;
+}
+
+static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
+{
+ struct spi_nor *nor = mtd_to_spi_nor(mtd);
+ int ret;
+
+ ret = spi_nor_lock_and_prep(nor);
+ if (ret)
+ return ret;
+
+ ret = nor->params->locking_ops->is_locked(nor, ofs, len);
+
+ spi_nor_unlock_and_unprep(nor);
+ return ret;
+}
+
+/**
+ * spi_nor_try_unlock_all() - Tries to unlock the entire flash memory array.
+ * @nor: pointer to a 'struct spi_nor'.
+ *
+ * Some SPI NOR flashes are write protected by default after a power-on reset
+ * cycle, in order to avoid inadvertent writes during power-up. Backward
+ * compatibility imposes to unlock the entire flash memory array at power-up
+ * by default.
+ *
+ * Unprotecting the entire flash array will fail for boards which are hardware
+ * write-protected. Thus any errors are ignored.
+ */
+void spi_nor_try_unlock_all(struct spi_nor *nor)
+{
+ int ret;
+
+ if (!(nor->flags & SNOR_F_HAS_LOCK))
+ return;
+
+ ret = spi_nor_unlock(&nor->mtd, 0, nor->params->size);
+ if (ret)
+ dev_dbg(nor->dev, "Failed to unlock the entire flash memory array\n");
+}
+
+void spi_nor_register_locking_ops(struct spi_nor *nor)
+{
+ struct mtd_info *mtd = &nor->mtd;
+
+ if (!nor->params->locking_ops)
+ return;
+
+ mtd->_lock = spi_nor_lock;
+ mtd->_unlock = spi_nor_unlock;
+ mtd->_is_locked = spi_nor_is_locked;
+}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 094/235] mtd: spi-nor: Fix spi_nor_try_unlock_all()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (92 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 093/235] mtd: spi-nor: Move Software Write Protection logic out of the core Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 095/235] mtd: spi-nor: swp: Improve locking user experience Greg Kroah-Hartman
` (143 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jean-Marc Ranger, Michael Walle,
Pratyush Yadav, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Walle <mwalle@kernel.org>
[ Upstream commit 2e3a7476ec3989e77270b9481e76e137824b17c0 ]
Commit ff67592cbdfc ("mtd: spi-nor: Introduce spi_nor_set_mtd_info()")
moved all initialization of the mtd fields at the end of spi_nor_scan().
Normally, the mtd info is only needed for the mtd ops on the device,
with one exception: spi_nor_try_unlock_all(), which will also make use
of the mtd->size parameter. With that commit, the size will always be
zero because it is not initialized. Fix that by not using the size of
the mtd_info struct, but use the size from struct spi_nor_flash_parameter.
Fixes: ff67592cbdfc ("mtd: spi-nor: Introduce spi_nor_set_mtd_info()")
Cc: stable@vger.kernel.org
Reported-by: Jean-Marc Ranger <jmranger@hotmail.com>
Closes: https://lore.kernel.org/all/DM6PR06MB561177323DC5207E34AF2A06C547A@DM6PR06MB5611.namprd06.prod.outlook.com/
Tested-by: Jean-Marc Ranger <jmranger@hotmail.com>
Signed-off-by: Michael Walle <mwalle@kernel.org>
Reviewed-by: Pratyush Yadav <pratyush@kernel.org>
Signed-off-by: Pratyush Yadav <pratyush@kernel.org>
Link: https://lore.kernel.org/r/20250701140426.2355182-1-mwalle@kernel.org
Stable-dep-of: e1d456b26bf2 ("mtd: spi-nor: swp: Improve locking user experience")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/mtd/spi-nor/swp.c | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
--- a/drivers/mtd/spi-nor/swp.c
+++ b/drivers/mtd/spi-nor/swp.c
@@ -50,7 +50,6 @@ static u64 spi_nor_get_min_prot_length_s
static void spi_nor_get_locked_range_sr(struct spi_nor *nor, u8 sr, loff_t *ofs,
uint64_t *len)
{
- struct mtd_info *mtd = &nor->mtd;
u64 min_prot_len;
u8 mask = spi_nor_get_sr_bp_mask(nor);
u8 tb_mask = spi_nor_get_sr_tb_mask(nor);
@@ -71,13 +70,13 @@ static void spi_nor_get_locked_range_sr(
min_prot_len = spi_nor_get_min_prot_length_sr(nor);
*len = min_prot_len << (bp - 1);
- if (*len > mtd->size)
- *len = mtd->size;
+ if (*len > nor->params->size)
+ *len = nor->params->size;
if (nor->flags & SNOR_F_HAS_SR_TB && sr & tb_mask)
*ofs = 0;
else
- *ofs = mtd->size - *len;
+ *ofs = nor->params->size - *len;
}
/*
@@ -150,7 +149,6 @@ static int spi_nor_is_unlocked_sr(struct
*/
static int spi_nor_sr_lock(struct spi_nor *nor, loff_t ofs, uint64_t len)
{
- struct mtd_info *mtd = &nor->mtd;
u64 min_prot_len;
int ret, status_old, status_new;
u8 mask = spi_nor_get_sr_bp_mask(nor);
@@ -175,7 +173,7 @@ static int spi_nor_sr_lock(struct spi_no
can_be_bottom = false;
/* If anything above us is unlocked, we can't use 'top' protection */
- if (!spi_nor_is_locked_sr(nor, ofs + len, mtd->size - (ofs + len),
+ if (!spi_nor_is_locked_sr(nor, ofs + len, nor->params->size - (ofs + len),
status_old))
can_be_top = false;
@@ -187,11 +185,11 @@ static int spi_nor_sr_lock(struct spi_no
/* lock_len: length of region that should end up locked */
if (use_top)
- lock_len = mtd->size - ofs;
+ lock_len = nor->params->size - ofs;
else
lock_len = ofs + len;
- if (lock_len == mtd->size) {
+ if (lock_len == nor->params->size) {
val = mask;
} else {
min_prot_len = spi_nor_get_min_prot_length_sr(nor);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 095/235] mtd: spi-nor: swp: Improve locking user experience
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (93 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 094/235] mtd: spi-nor: Fix spi_nor_try_unlock_all() Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 096/235] smb: client: use kvzalloc() for megabyte buffer in simple fallocate Greg Kroah-Hartman
` (142 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, stable, Miquel Raynal, Michael Walle,
Pratyush Yadav, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miquel Raynal <miquel.raynal@bootlin.com>
[ Upstream commit e1d456b26bf23e30db305a6184e8abd9ab68bbf2 ]
In the case of the first block being locked (or the few first blocks),
if the user want to fully unlock the device it has two possibilities:
- either it asks to unlock the entire device, and this works;
- or it asks to unlock just the block(s) that are currently locked,
which fails.
It fails because the conditions "can_be_top" and "can_be_bottom" are
true. Indeed, in this case, we unlock everything, so the TB bit does not
matter. However in the current implementation, use_top would be true (as
this is the favourite option) and lock_len, which in practice should be
reduced down to 0, is set to "nor->params->size - (ofs + len)" which is
a positive number. This is wrong.
An easy way is to simply add an extra condition. In the unlock() path,
if we can achieve the same result from both sides, it means we unlock
everything and lock_len must simply be 0. A comment is added to clarify
that logic.
Fixes: 3dd8012a8eeb ("mtd: spi-nor: add TB (Top/Bottom) protect support")
Cc: stable@kernel.org
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Reviewed-by: Michael Walle <mwalle@kernel.org>
Signed-off-by: Pratyush Yadav <pratyush@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/mtd/spi-nor/swp.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
--- a/drivers/mtd/spi-nor/swp.c
+++ b/drivers/mtd/spi-nor/swp.c
@@ -267,8 +267,15 @@ static int spi_nor_sr_unlock(struct spi_
/* Prefer top, if both are valid */
use_top = can_be_top;
- /* lock_len: length of region that should remain locked */
- if (use_top)
+ /*
+ * lock_len: length of region that should remain locked.
+ *
+ * When can_be_top and can_be_bottom booleans are true, both adjacent
+ * regions are unlocked, thus the entire flash can be unlocked.
+ */
+ if (can_be_top && can_be_bottom)
+ lock_len = 0;
+ else if (use_top)
lock_len = nor->params->size - (ofs + len);
else
lock_len = ofs;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 096/235] smb: client: use kvzalloc() for megabyte buffer in simple fallocate
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (94 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 095/235] mtd: spi-nor: swp: Improve locking user experience Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 097/235] tpm: tpm_tis_spi: Use wait_woken() in wait_for_tmp_stat() Greg Kroah-Hartman
` (141 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Fredric Cover, Steve French,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fredric Cover <fredric.cover.lkernel@gmail.com>
[ Upstream commit 806c00c23e3ce8eae397a40ced536ef88ae4e012 ]
Currently in smb3_simple_fallocate_range(), a 1 MB buffer is allocated
using kzalloc(). Under heavy memory fragmentation, a contiguous 1 MB block
of physical memory (an order-8 allocation) may not be available,
causing the allocation to fail.
This failure was observed during xfstests generic/013 on a 4GB RAM
test machine running fsstress:
fsstress: page allocation failure: order:8,
mode:0x40dc0(GFP_KERNEL|__GFP_ZERO|__GFP_COMP),
nodemask=(null),cpuset=/,mems_allowed=0
Call Trace:
<TASK>
dump_stack_lvl+0x5d/0x80
warn_alloc+0x163/0x190
__alloc_pages_slowpath.constprop.0+0x71b/0x12f0
__alloc_frozen_pages_noprof+0x2f6/0x340
alloc_pages_mpol+0xb6/0x170
___kmalloc_large_node+0xb3/0xd0
__kmalloc_large_noprof+0x1e/0xc0
smb3_simple_falloc.isra.0+0x62b/0x960
cifs_fallocate+0xed/0x180
vfs_fallocate+0x165/0x3c0
__x64_sys_fallocate+0x48/0xa0
do_syscall_64+0xe1/0x640
entry_SYSCALL_64_after_hwframe+0x76/0x7e
</TASK>
Node 0 Normal: 3375*4kB ... 7*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB
Since this scratch buffer does not require physically contiguous memory,
switch the allocation to kvzalloc(). This retains the performance
benefits of kmalloc() under normal conditions, while gracefully falling
back to virtually contiguous memory when physical allocation fails.
Fixes: 966a3cb7c7db ("cifs: improve fallocate emulation")
Cc: stable@vger.kernel.org
Signed-off-by: Fredric Cover <fredric.cover.lkernel@gmail.com>
Tested-by: Fredric Cover <fredric.cover.lkernel@gmail.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/cifs/smb2ops.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -3568,7 +3568,7 @@ static int smb3_simple_fallocate_range(u
if (rc)
goto out;
- buf = kzalloc(1024 * 1024, GFP_KERNEL);
+ buf = kvzalloc(1024 * 1024, GFP_KERNEL);
if (buf == NULL) {
rc = -ENOMEM;
goto out;
@@ -3635,7 +3635,7 @@ static int smb3_simple_fallocate_range(u
out:
kfree(out_data);
- kfree(buf);
+ kvfree(buf);
return rc;
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 097/235] tpm: tpm_tis_spi: Use wait_woken() in wait_for_tmp_stat()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (95 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 096/235] smb: client: use kvzalloc() for megabyte buffer in simple fallocate Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 098/235] PCI: Add pci_find_vsec_capability() to find a specific VSEC Greg Kroah-Hartman
` (140 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Linus Walleij, Stefan Wahren,
Jarkko Sakkinen, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jarkko Sakkinen <jarkko@kernel.org>
[ Upstream commit c0c9cfb3b75def8bf200a2d4db09015806acfeaf ]
wait_event_interruptible_timeout() evaluates its condition after setting
the current task state to TASK_INTERRUPTIBLE.
With CONFIG_DEBUG_ATOMIC_SLEEP this triggers a warning when the IRQ wait
path is used:
tpm_tis_status()
tpm_tis_spi_read_bytes()
tpm_tis_spi_transfer_full()
spi_bus_lock()
mutex_lock()
Address this with the following measures:
1. Call wait_tpm_stat_cond() only while tasking is running.
2. Use wait_woken() to wait for changes.
Cc: stable@vger.kernel.org # v4.19+
Cc: Linus Walleij <linusw@kernel.org>
Reported-by: Stefan Wahren <wahrenst@gmx.net>
Closes: https://lore.kernel.org/linux-integrity/6964bec7-3dbb-453b-89ef-9b990217a8b9@gmx.net/
Fixes: 1a339b658d9d ("tpm_tis_spi: Pass the SPI IRQ down to the driver")
Reviewed-by: Linus Walleij <linusw@kernel.org>
Tested-by: Stefan Wahren <wahrenst@gmx.net>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/char/tpm/tpm_tis_core.c | 38 ++++++++++++++++++++++++--------------
1 file changed, 24 insertions(+), 14 deletions(-)
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -49,10 +49,11 @@ static int wait_for_tpm_stat(struct tpm_
bool check_cancel)
{
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
unsigned long stop;
- long rc;
u8 status;
bool canceled = false;
+ int ret;
/* check current status */
status = chip->ops->status(chip);
@@ -62,23 +63,32 @@ static int wait_for_tpm_stat(struct tpm_
stop = jiffies + timeout;
if (chip->flags & TPM_CHIP_FLAG_IRQ) {
+ ret = -ETIME;
+ add_wait_queue(queue, &wait);
again:
+ if (wait_for_tpm_stat_cond(chip, mask, check_cancel,
+ &canceled)) {
+ ret = canceled ? -ECANCELED : 0;
+ goto out;
+ }
+
timeout = stop - jiffies;
if ((long)timeout <= 0)
- return -ETIME;
- rc = wait_event_interruptible_timeout(*queue,
- wait_for_tpm_stat_cond(chip, mask, check_cancel,
- &canceled),
- timeout);
- if (rc > 0) {
- if (canceled)
- return -ECANCELED;
- return 0;
- }
- if (rc == -ERESTARTSYS && freezing(current)) {
- clear_thread_flag(TIF_SIGPENDING);
- goto again;
+ goto out;
+
+ if (signal_pending(current)) {
+ if (freezing(current)) {
+ clear_thread_flag(TIF_SIGPENDING);
+ goto again;
+ }
+ goto out;
}
+
+ wait_woken(&wait, TASK_INTERRUPTIBLE, timeout);
+ goto again;
+out:
+ remove_wait_queue(queue, &wait);
+ return ret;
} else {
do {
usleep_range(priv->timeout_min,
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 098/235] PCI: Add pci_find_vsec_capability() to find a specific VSEC
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (96 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 097/235] tpm: tpm_tis_spi: Use wait_woken() in wait_for_tmp_stat() Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 099/235] dmaengine: dw-edma: Improve the linked list and data blocks definition Greg Kroah-Hartman
` (139 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Gustavo Pimentel, Bjorn Helgaas,
Vinod Koul, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gustavo Pimentel <Gustavo.Pimentel@synopsys.com>
[ Upstream commit c124fd9a969acaa83f6dfa5e160a99a500af9e4b ]
Add pci_find_vsec_capability() to locate a Vendor-Specific Extended
Capability with the specified VSEC ID.
The Vendor-Specific Extended Capability (VSEC) allows one or more
proprietary capabilities defined by the vendor which aren't standard
or shared between vendors.
Signed-off-by: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Link: https://lore.kernel.org/r/d89506834fb11c6fa0bd5d515c0dd55b13ac6958.1613674948.git.gustavo.pimentel@synopsys.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Stable-dep-of: 8ffba0171c6b ("dmaengine: dw-edma: Add spinlock to protect DONE_INT_MASK and ABORT_INT_MASK")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/pci/pci.c | 30 ++++++++++++++++++++++++++++++
include/linux/pci.h | 1 +
2 files changed, 31 insertions(+)
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -691,6 +691,36 @@ int pci_find_ht_capability(struct pci_de
EXPORT_SYMBOL_GPL(pci_find_ht_capability);
/**
+ * pci_find_vsec_capability - Find a vendor-specific extended capability
+ * @dev: PCI device to query
+ * @vendor: Vendor ID for which capability is defined
+ * @cap: Vendor-specific capability ID
+ *
+ * If @dev has Vendor ID @vendor, search for a VSEC capability with
+ * VSEC ID @cap. If found, return the capability offset in
+ * config space; otherwise return 0.
+ */
+u16 pci_find_vsec_capability(struct pci_dev *dev, u16 vendor, int cap)
+{
+ u16 vsec = 0;
+ u32 header;
+
+ if (vendor != dev->vendor)
+ return 0;
+
+ while ((vsec = pci_find_next_ext_capability(dev, vsec,
+ PCI_EXT_CAP_ID_VNDR))) {
+ if (pci_read_config_dword(dev, vsec + PCI_VNDR_HEADER,
+ &header) == PCIBIOS_SUCCESSFUL &&
+ PCI_VNDR_HEADER_ID(header) == cap)
+ return vsec;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pci_find_vsec_capability);
+
+/**
* pci_find_parent_resource - return resource region of parent bus of given
* region
* @dev: PCI device structure contains resources to be searched
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1101,6 +1101,7 @@ int pci_find_next_ext_capability(struct
int pci_find_ht_capability(struct pci_dev *dev, int ht_cap);
int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap);
struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
+u16 pci_find_vsec_capability(struct pci_dev *dev, u16 vendor, int cap);
u64 pci_get_dsn(struct pci_dev *dev);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 099/235] dmaengine: dw-edma: Improve the linked list and data blocks definition
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (97 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 098/235] PCI: Add pci_find_vsec_capability() to find a specific VSEC Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 100/235] dmaengine: dw-edma: Remove unused irq field in struct dw_edma_chip Greg Kroah-Hartman
` (138 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Gustavo Pimentel, Vinod Koul,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gustavo Pimentel <Gustavo.Pimentel@synopsys.com>
[ Upstream commit 31fb8c1ff962d93ed5025f39a6a186207c9805eb ]
In the previous implementation, the driver assumed that there existed
only two memory spaces that would equally distribute the amount of
read/write channels.
This might not be the case on some other implementations, therefore this
patch change this requirement so that each write/read channel has
its own linked list and data space well defined, which allows
different sizes and locations.
Signed-off-by: Gustavo Pimentel <gustavo.pimentel@synopsys.com>
Link: https://lore.kernel.org/r/2e316cb983f8a1e09ce929029f87619dc92a52de.1613674948.git.gustavo.pimentel@synopsys.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Stable-dep-of: 8ffba0171c6b ("dmaengine: dw-edma: Add spinlock to protect DONE_INT_MASK and ABORT_INT_MASK")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/dma/dw-edma/dw-edma-core.c | 77 +++++++-------
drivers/dma/dw-edma/dw-edma-core.h | 18 ++-
drivers/dma/dw-edma/dw-edma-pcie.c | 181 ++++++++++++++++++++++++----------
drivers/dma/dw-edma/dw-edma-v0-core.c | 70 ++++++-------
4 files changed, 217 insertions(+), 129 deletions(-)
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -81,8 +81,13 @@ static struct dw_edma_chunk *dw_edma_all
* - Even chunks originate CB equal to 1
*/
chunk->cb = !(desc->chunks_alloc % 2);
- chunk->ll_region.paddr = dw->ll_region.paddr + chan->ll_off;
- chunk->ll_region.vaddr = dw->ll_region.vaddr + chan->ll_off;
+ if (chan->dir == EDMA_DIR_WRITE) {
+ chunk->ll_region.paddr = dw->ll_region_wr[chan->id].paddr;
+ chunk->ll_region.vaddr = dw->ll_region_wr[chan->id].vaddr;
+ } else {
+ chunk->ll_region.paddr = dw->ll_region_rd[chan->id].paddr;
+ chunk->ll_region.vaddr = dw->ll_region_rd[chan->id].vaddr;
+ }
if (desc->chunk) {
/* Create and add new element into the linked list */
@@ -669,24 +674,13 @@ static int dw_edma_channel_setup(struct
struct device *dev = chip->dev;
struct dw_edma *dw = chip->dw;
struct dw_edma_chan *chan;
- size_t ll_chunk, dt_chunk;
struct dw_edma_irq *irq;
struct dma_device *dma;
- u32 i, j, cnt, ch_cnt;
u32 alloc, off_alloc;
+ u32 i, j, cnt;
int err = 0;
u32 pos;
- ch_cnt = dw->wr_ch_cnt + dw->rd_ch_cnt;
- ll_chunk = dw->ll_region.sz;
- dt_chunk = dw->dt_region.sz;
-
- /* Calculate linked list chunk for each channel */
- ll_chunk /= roundup_pow_of_two(ch_cnt);
-
- /* Calculate linked list chunk for each channel */
- dt_chunk /= roundup_pow_of_two(ch_cnt);
-
if (write) {
i = 0;
cnt = dw->wr_ch_cnt;
@@ -712,20 +706,21 @@ static int dw_edma_channel_setup(struct
chan->vc.chan.private = dt_region;
chan->chip = chip;
+ chan->dw = dw;
chan->id = j;
chan->dir = write ? EDMA_DIR_WRITE : EDMA_DIR_READ;
chan->configured = false;
chan->request = EDMA_REQ_NONE;
chan->status = EDMA_ST_IDLE;
- chan->ll_off = (ll_chunk * i);
- chan->ll_max = (ll_chunk / EDMA_LL_SZ) - 1;
-
- chan->dt_off = (dt_chunk * i);
+ if (write)
+ chan->ll_max = (dw->ll_region_wr[j].sz / EDMA_LL_SZ);
+ else
+ chan->ll_max = (dw->ll_region_rd[j].sz / EDMA_LL_SZ);
+ chan->ll_max -= 1;
- dev_vdbg(dev, "L. List:\tChannel %s[%u] off=0x%.8lx, max_cnt=%u\n",
- write ? "write" : "read", j,
- chan->ll_off, chan->ll_max);
+ dev_vdbg(dev, "L. List:\tChannel %s[%u] max_cnt=%u\n",
+ write ? "write" : "read", j, chan->ll_max);
if (dw->nr_irqs == 1)
pos = 0;
@@ -750,12 +745,15 @@ static int dw_edma_channel_setup(struct
chan->vc.desc_free = vchan_free_desc;
vchan_init(&chan->vc, dma);
- dt_region->paddr = dw->dt_region.paddr + chan->dt_off;
- dt_region->vaddr = dw->dt_region.vaddr + chan->dt_off;
- dt_region->sz = dt_chunk;
-
- dev_vdbg(dev, "Data:\tChannel %s[%u] off=0x%.8lx\n",
- write ? "write" : "read", j, chan->dt_off);
+ if (write) {
+ dt_region->paddr = dw->dt_region_wr[j].paddr;
+ dt_region->vaddr = dw->dt_region_wr[j].vaddr;
+ dt_region->sz = dw->dt_region_wr[j].sz;
+ } else {
+ dt_region->paddr = dw->dt_region_rd[j].paddr;
+ dt_region->vaddr = dw->dt_region_rd[j].vaddr;
+ dt_region->sz = dw->dt_region_rd[j].sz;
+ }
dw_edma_v0_core_device_config(chan);
}
@@ -824,7 +822,7 @@ static int dw_edma_irq_request(struct dw
if (dw->nr_irqs == 1) {
/* Common IRQ shared among all channels */
- irq = dw->ops->irq_vector(dev, 0);
+ irq = dw->core->irq_vector(dev, 0);
err = request_irq(irq, dw_edma_interrupt_common,
IRQF_SHARED, dw->name, &dw->irq[0]);
if (err) {
@@ -847,7 +845,7 @@ static int dw_edma_irq_request(struct dw
dw_edma_add_irq_mask(&rd_mask, *rd_alloc, dw->rd_ch_cnt);
for (i = 0; i < (*wr_alloc + *rd_alloc); i++) {
- irq = dw->ops->irq_vector(dev, i);
+ irq = dw->core->irq_vector(dev, i);
err = request_irq(irq,
i < *wr_alloc ?
dw_edma_interrupt_write :
@@ -885,19 +883,20 @@ int dw_edma_probe(struct dw_edma_chip *c
return -EINVAL;
dw = chip->dw;
- if (!dw || !dw->irq || !dw->ops || !dw->ops->irq_vector)
+ if (!dw || !dw->irq || !dw->core || !dw->core->irq_vector)
return -EINVAL;
raw_spin_lock_init(&dw->lock);
- /* Find out how many write channels are supported by hardware */
- dw->wr_ch_cnt = dw_edma_v0_core_ch_count(dw, EDMA_DIR_WRITE);
- if (!dw->wr_ch_cnt)
- return -EINVAL;
+ dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt,
+ dw_edma_v0_core_ch_count(dw, EDMA_DIR_WRITE));
+ dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt, EDMA_MAX_WR_CH);
+
+ dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt,
+ dw_edma_v0_core_ch_count(dw, EDMA_DIR_READ));
+ dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt, EDMA_MAX_RD_CH);
- /* Find out how many read channels are supported by hardware */
- dw->rd_ch_cnt = dw_edma_v0_core_ch_count(dw, EDMA_DIR_READ);
- if (!dw->rd_ch_cnt)
+ if (!dw->wr_ch_cnt && !dw->rd_ch_cnt)
return -EINVAL;
dev_vdbg(dev, "Channels:\twrite=%d, read=%d\n",
@@ -939,7 +938,7 @@ int dw_edma_probe(struct dw_edma_chip *c
err_irq_free:
for (i = (dw->nr_irqs - 1); i >= 0; i--)
- free_irq(dw->ops->irq_vector(dev, i), &dw->irq[i]);
+ free_irq(dw->core->irq_vector(dev, i), &dw->irq[i]);
dw->nr_irqs = 0;
@@ -959,7 +958,7 @@ int dw_edma_remove(struct dw_edma_chip *
/* Free irqs */
for (i = (dw->nr_irqs - 1); i >= 0; i--)
- free_irq(dw->ops->irq_vector(dev, i), &dw->irq[i]);
+ free_irq(dw->core->irq_vector(dev, i), &dw->irq[i]);
/* Power management */
pm_runtime_disable(dev);
--- a/drivers/dma/dw-edma/dw-edma-core.h
+++ b/drivers/dma/dw-edma/dw-edma-core.h
@@ -15,6 +15,8 @@
#include "../virt-dma.h"
#define EDMA_LL_SZ 24
+#define EDMA_MAX_WR_CH 8
+#define EDMA_MAX_RD_CH 8
enum dw_edma_dir {
EDMA_DIR_WRITE = 0,
@@ -40,6 +42,7 @@ enum dw_edma_status {
struct dw_edma_chan;
struct dw_edma_chunk;
+struct dw_edma;
struct dw_edma_burst {
struct list_head list;
@@ -79,14 +82,12 @@ struct dw_edma_desc {
struct dw_edma_chan {
struct virt_dma_chan vc;
struct dw_edma_chip *chip;
+ struct dw_edma *dw;
int id;
enum dw_edma_dir dir;
- off_t ll_off;
u32 ll_max;
- off_t dt_off;
-
struct msi_msg msi;
enum dw_edma_request request;
@@ -117,8 +118,10 @@ struct dw_edma {
u16 rd_ch_cnt;
struct dw_edma_region rg_region; /* Registers */
- struct dw_edma_region ll_region; /* Linked list */
- struct dw_edma_region dt_region; /* Data */
+ struct dw_edma_region ll_region_wr[EDMA_MAX_WR_CH];
+ struct dw_edma_region ll_region_rd[EDMA_MAX_RD_CH];
+ struct dw_edma_region dt_region_wr[EDMA_MAX_WR_CH];
+ struct dw_edma_region dt_region_rd[EDMA_MAX_RD_CH];
struct dw_edma_irq *irq;
int nr_irqs;
@@ -127,9 +130,12 @@ struct dw_edma {
enum dw_edma_mode mode;
struct dw_edma_chan *chan;
- const struct dw_edma_core_ops *ops;
raw_spinlock_t lock; /* Only for legacy */
+
+ struct dw_edma_chip *chip;
+
+ const struct dw_edma_core_ops *core;
};
struct dw_edma_sg {
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -16,42 +16,73 @@
#include "dw-edma-core.h"
+#define DW_BLOCK(a, b, c) \
+ { \
+ .bar = a, \
+ .off = b, \
+ .sz = c, \
+ },
+
+struct dw_edma_block {
+ enum pci_barno bar;
+ off_t off;
+ size_t sz;
+};
+
struct dw_edma_pcie_data {
/* eDMA registers location */
- enum pci_barno rg_bar;
- off_t rg_off;
- size_t rg_sz;
+ struct dw_edma_block rg;
/* eDMA memory linked list location */
- enum pci_barno ll_bar;
- off_t ll_off;
- size_t ll_sz;
+ struct dw_edma_block ll_wr[EDMA_MAX_WR_CH];
+ struct dw_edma_block ll_rd[EDMA_MAX_RD_CH];
/* eDMA memory data location */
- enum pci_barno dt_bar;
- off_t dt_off;
- size_t dt_sz;
+ struct dw_edma_block dt_wr[EDMA_MAX_WR_CH];
+ struct dw_edma_block dt_rd[EDMA_MAX_RD_CH];
/* Other */
u32 version;
enum dw_edma_mode mode;
u8 irqs;
+ u16 wr_ch_cnt;
+ u16 rd_ch_cnt;
};
static const struct dw_edma_pcie_data snps_edda_data = {
/* eDMA registers location */
- .rg_bar = BAR_0,
- .rg_off = 0x00001000, /* 4 Kbytes */
- .rg_sz = 0x00002000, /* 8 Kbytes */
+ .rg.bar = BAR_0,
+ .rg.off = 0x00001000, /* 4 Kbytes */
+ .rg.sz = 0x00002000, /* 8 Kbytes */
/* eDMA memory linked list location */
- .ll_bar = BAR_2,
- .ll_off = 0x00000000, /* 0 Kbytes */
- .ll_sz = 0x00800000, /* 8 Mbytes */
+ .ll_wr = {
+ /* Channel 0 - BAR 2, offset 0 Mbytes, size 2 Mbytes */
+ DW_BLOCK(BAR_2, 0x00000000, 0x00200000)
+ /* Channel 1 - BAR 2, offset 2 Mbytes, size 2 Mbytes */
+ DW_BLOCK(BAR_2, 0x00200000, 0x00200000)
+ },
+ .ll_rd = {
+ /* Channel 0 - BAR 2, offset 4 Mbytes, size 2 Mbytes */
+ DW_BLOCK(BAR_2, 0x00400000, 0x00200000)
+ /* Channel 1 - BAR 2, offset 6 Mbytes, size 2 Mbytes */
+ DW_BLOCK(BAR_2, 0x00600000, 0x00200000)
+ },
/* eDMA memory data location */
- .dt_bar = BAR_2,
- .dt_off = 0x00800000, /* 8 Mbytes */
- .dt_sz = 0x03800000, /* 56 Mbytes */
+ .dt_wr = {
+ /* Channel 0 - BAR 2, offset 8 Mbytes, size 14 Mbytes */
+ DW_BLOCK(BAR_2, 0x00800000, 0x00e00000)
+ /* Channel 1 - BAR 2, offset 22 Mbytes, size 14 Mbytes */
+ DW_BLOCK(BAR_2, 0x01600000, 0x00e00000)
+ },
+ .dt_rd = {
+ /* Channel 0 - BAR 2, offset 36 Mbytes, size 14 Mbytes */
+ DW_BLOCK(BAR_2, 0x02400000, 0x00e00000)
+ /* Channel 1 - BAR 2, offset 50 Mbytes, size 14 Mbytes */
+ DW_BLOCK(BAR_2, 0x03200000, 0x00e00000)
+ },
/* Other */
.version = 0,
.mode = EDMA_MODE_UNROLL,
.irqs = 1,
+ .wr_ch_cnt = 2,
+ .rd_ch_cnt = 2,
};
static int dw_edma_pcie_irq_vector(struct device *dev, unsigned int nr)
@@ -71,6 +102,7 @@ static int dw_edma_pcie_probe(struct pci
struct dw_edma_chip *chip;
int err, nr_irqs;
struct dw_edma *dw;
+ int i, mask;
/* Enable PCI device */
err = pcim_enable_device(pdev);
@@ -80,10 +112,16 @@ static int dw_edma_pcie_probe(struct pci
}
/* Mapping PCI BAR regions */
- err = pcim_iomap_regions(pdev, BIT(pdata->rg_bar) |
- BIT(pdata->ll_bar) |
- BIT(pdata->dt_bar),
- pci_name(pdev));
+ mask = BIT(pdata->rg.bar);
+ for (i = 0; i < pdata->wr_ch_cnt; i++) {
+ mask |= BIT(pdata->ll_wr[i].bar);
+ mask |= BIT(pdata->dt_wr[i].bar);
+ }
+ for (i = 0; i < pdata->rd_ch_cnt; i++) {
+ mask |= BIT(pdata->ll_rd[i].bar);
+ mask |= BIT(pdata->dt_rd[i].bar);
+ }
+ err = pcim_iomap_regions(pdev, mask, pci_name(pdev));
if (err) {
pci_err(pdev, "eDMA BAR I/O remapping failed\n");
return err;
@@ -139,28 +177,57 @@ static int dw_edma_pcie_probe(struct pci
chip->id = pdev->devfn;
chip->irq = pdev->irq;
- dw->rg_region.vaddr = pcim_iomap_table(pdev)[pdata->rg_bar];
- dw->rg_region.vaddr += pdata->rg_off;
- dw->rg_region.paddr = pdev->resource[pdata->rg_bar].start;
- dw->rg_region.paddr += pdata->rg_off;
- dw->rg_region.sz = pdata->rg_sz;
-
- dw->ll_region.vaddr = pcim_iomap_table(pdev)[pdata->ll_bar];
- dw->ll_region.vaddr += pdata->ll_off;
- dw->ll_region.paddr = pdev->resource[pdata->ll_bar].start;
- dw->ll_region.paddr += pdata->ll_off;
- dw->ll_region.sz = pdata->ll_sz;
-
- dw->dt_region.vaddr = pcim_iomap_table(pdev)[pdata->dt_bar];
- dw->dt_region.vaddr += pdata->dt_off;
- dw->dt_region.paddr = pdev->resource[pdata->dt_bar].start;
- dw->dt_region.paddr += pdata->dt_off;
- dw->dt_region.sz = pdata->dt_sz;
-
+ dw->chip = chip;
dw->version = pdata->version;
dw->mode = pdata->mode;
dw->nr_irqs = nr_irqs;
- dw->ops = &dw_edma_pcie_core_ops;
+ dw->core = &dw_edma_pcie_core_ops;
+ dw->wr_ch_cnt = pdata->wr_ch_cnt;
+ dw->rd_ch_cnt = pdata->rd_ch_cnt;
+
+ dw->rg_region.vaddr = pcim_iomap_table(pdev)[pdata->rg.bar];
+ dw->rg_region.vaddr += pdata->rg.off;
+ dw->rg_region.paddr = pdev->resource[pdata->rg.bar].start;
+ dw->rg_region.paddr += pdata->rg.off;
+ dw->rg_region.sz = pdata->rg.sz;
+
+ for (i = 0; i < dw->wr_ch_cnt; i++) {
+ struct dw_edma_region *ll_region = &dw->ll_region_wr[i];
+ struct dw_edma_region *dt_region = &dw->dt_region_wr[i];
+ const struct dw_edma_block *ll_block = &pdata->ll_wr[i];
+ const struct dw_edma_block *dt_block = &pdata->dt_wr[i];
+
+ ll_region->vaddr = pcim_iomap_table(pdev)[ll_block->bar];
+ ll_region->vaddr += ll_block->off;
+ ll_region->paddr = pdev->resource[ll_block->bar].start;
+ ll_region->paddr += ll_block->off;
+ ll_region->sz = ll_block->sz;
+
+ dt_region->vaddr = pcim_iomap_table(pdev)[dt_block->bar];
+ dt_region->vaddr += dt_block->off;
+ dt_region->paddr = pdev->resource[dt_block->bar].start;
+ dt_region->paddr += dt_block->off;
+ dt_region->sz = dt_block->sz;
+ }
+
+ for (i = 0; i < dw->rd_ch_cnt; i++) {
+ struct dw_edma_region *ll_region = &dw->ll_region_rd[i];
+ struct dw_edma_region *dt_region = &dw->dt_region_rd[i];
+ const struct dw_edma_block *ll_block = &pdata->ll_rd[i];
+ const struct dw_edma_block *dt_block = &pdata->dt_rd[i];
+
+ ll_region->vaddr = pcim_iomap_table(pdev)[ll_block->bar];
+ ll_region->vaddr += ll_block->off;
+ ll_region->paddr = pdev->resource[ll_block->bar].start;
+ ll_region->paddr += ll_block->off;
+ ll_region->sz = ll_block->sz;
+
+ dt_region->vaddr = pcim_iomap_table(pdev)[dt_block->bar];
+ dt_region->vaddr += dt_block->off;
+ dt_region->paddr = pdev->resource[dt_block->bar].start;
+ dt_region->paddr += dt_block->off;
+ dt_region->sz = dt_block->sz;
+ }
/* Debug info */
pci_dbg(pdev, "Version:\t%u\n", dw->version);
@@ -169,16 +236,32 @@ static int dw_edma_pcie_probe(struct pci
dw->mode == EDMA_MODE_LEGACY ? "Legacy" : "Unroll");
pci_dbg(pdev, "Registers:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
- pdata->rg_bar, pdata->rg_off, pdata->rg_sz,
+ pdata->rg.bar, pdata->rg.off, pdata->rg.sz,
dw->rg_region.vaddr, &dw->rg_region.paddr);
- pci_dbg(pdev, "L. List:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
- pdata->ll_bar, pdata->ll_off, pdata->ll_sz,
- dw->ll_region.vaddr, &dw->ll_region.paddr);
-
- pci_dbg(pdev, "Data:\tBAR=%u, off=0x%.8lx, sz=0x%zx bytes, addr(v=%p, p=%pa)\n",
- pdata->dt_bar, pdata->dt_off, pdata->dt_sz,
- dw->dt_region.vaddr, &dw->dt_region.paddr);
+ for (i = 0; i < dw->wr_ch_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, pdata->ll_wr[i].bar, pdata->ll_wr[i].off,
+ dw->ll_region_wr[i].sz, dw->ll_region_wr[i].vaddr,
+ &dw->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, pdata->dt_wr[i].bar, pdata->dt_wr[i].off,
+ dw->dt_region_wr[i].sz, dw->dt_region_wr[i].vaddr,
+ &dw->dt_region_wr[i].paddr);
+ }
+
+ for (i = 0; i < dw->rd_ch_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, pdata->ll_rd[i].bar, pdata->ll_rd[i].off,
+ dw->ll_region_rd[i].sz, dw->ll_region_rd[i].vaddr,
+ &dw->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, pdata->dt_rd[i].bar, pdata->dt_rd[i].off,
+ dw->dt_region_rd[i].sz, dw->dt_region_rd[i].vaddr,
+ &dw->dt_region_rd[i].paddr);
+ }
pci_dbg(pdev, "Nr. IRQs:\t%u\n", dw->nr_irqs);
--- a/drivers/dma/dw-edma/dw-edma-v0-core.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
@@ -34,7 +34,7 @@ static inline struct dw_edma_v0_regs __i
#define GET(dw, name) \
readl(&(__dw_regs(dw)->name))
-#define SET_RW(dw, dir, name, value) \
+#define SET_RW_32(dw, dir, name, value) \
do { \
if ((dir) == EDMA_DIR_WRITE) \
SET(dw, wr_##name, value); \
@@ -42,7 +42,7 @@ static inline struct dw_edma_v0_regs __i
SET(dw, rd_##name, value); \
} while (0)
-#define GET_RW(dw, dir, name) \
+#define GET_RW_32(dw, dir, name) \
((dir) == EDMA_DIR_WRITE \
? GET(dw, wr_##name) \
: GET(dw, rd_##name))
@@ -115,7 +115,7 @@ static inline u32 readl_ch(struct dw_edm
return value;
}
-#define SET_CH(dw, dir, ch, name, value) \
+#define SET_CH_32(dw, dir, ch, name, value) \
writel_ch(dw, dir, ch, value, &(__dw_ch_regs(dw, dir, ch)->name))
#define GET_CH(dw, dir, ch, name) \
@@ -167,26 +167,26 @@ void dw_edma_v0_core_clear_done_int(stru
{
struct dw_edma *dw = chan->chip->dw;
- SET_RW(dw, chan->dir, int_clear,
- FIELD_PREP(EDMA_V0_DONE_INT_MASK, BIT(chan->id)));
+ SET_RW_32(dw, chan->dir, int_clear,
+ FIELD_PREP(EDMA_V0_DONE_INT_MASK, BIT(chan->id)));
}
void dw_edma_v0_core_clear_abort_int(struct dw_edma_chan *chan)
{
struct dw_edma *dw = chan->chip->dw;
- SET_RW(dw, chan->dir, int_clear,
- FIELD_PREP(EDMA_V0_ABORT_INT_MASK, BIT(chan->id)));
+ SET_RW_32(dw, chan->dir, int_clear,
+ FIELD_PREP(EDMA_V0_ABORT_INT_MASK, BIT(chan->id)));
}
u32 dw_edma_v0_core_status_done_int(struct dw_edma *dw, enum dw_edma_dir dir)
{
- return FIELD_GET(EDMA_V0_DONE_INT_MASK, GET_RW(dw, dir, int_status));
+ return FIELD_GET(EDMA_V0_DONE_INT_MASK, GET_RW_32(dw, dir, int_status));
}
u32 dw_edma_v0_core_status_abort_int(struct dw_edma *dw, enum dw_edma_dir dir)
{
- return FIELD_GET(EDMA_V0_ABORT_INT_MASK, GET_RW(dw, dir, int_status));
+ return FIELD_GET(EDMA_V0_ABORT_INT_MASK, GET_RW_32(dw, dir, int_status));
}
static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
@@ -236,35 +236,35 @@ static void dw_edma_v0_core_write_chunk(
void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
{
struct dw_edma_chan *chan = chunk->chan;
- struct dw_edma *dw = chan->chip->dw;
+ struct dw_edma *dw = chan->dw;
u32 tmp;
dw_edma_v0_core_write_chunk(chunk);
if (first) {
/* Enable engine */
- SET_RW(dw, chan->dir, engine_en, BIT(0));
+ SET_RW_32(dw, chan->dir, engine_en, BIT(0));
/* Interrupt unmask - done, abort */
- tmp = GET_RW(dw, chan->dir, int_mask);
+ tmp = GET_RW_32(dw, chan->dir, int_mask);
tmp &= ~FIELD_PREP(EDMA_V0_DONE_INT_MASK, BIT(chan->id));
tmp &= ~FIELD_PREP(EDMA_V0_ABORT_INT_MASK, BIT(chan->id));
- SET_RW(dw, chan->dir, int_mask, tmp);
+ SET_RW_32(dw, chan->dir, int_mask, tmp);
/* Linked list error */
- tmp = GET_RW(dw, chan->dir, linked_list_err_en);
+ tmp = GET_RW_32(dw, chan->dir, linked_list_err_en);
tmp |= FIELD_PREP(EDMA_V0_LINKED_LIST_ERR_MASK, BIT(chan->id));
- SET_RW(dw, chan->dir, linked_list_err_en, tmp);
+ SET_RW_32(dw, chan->dir, linked_list_err_en, tmp);
/* Channel control */
- SET_CH(dw, chan->dir, chan->id, ch_control1,
- (DW_EDMA_V0_CCS | DW_EDMA_V0_LLE));
+ SET_CH_32(dw, chan->dir, chan->id, ch_control1,
+ (DW_EDMA_V0_CCS | DW_EDMA_V0_LLE));
/* Linked list - low, high */
- SET_CH(dw, chan->dir, chan->id, llp_low,
- lower_32_bits(chunk->ll_region.paddr));
- SET_CH(dw, chan->dir, chan->id, llp_high,
- upper_32_bits(chunk->ll_region.paddr));
+ SET_CH_32(dw, chan->dir, chan->id, llp_low,
+ lower_32_bits(chunk->ll_region.paddr));
+ SET_CH_32(dw, chan->dir, chan->id, llp_high,
+ upper_32_bits(chunk->ll_region.paddr));
}
/* Doorbell */
- SET_RW(dw, chan->dir, doorbell,
- FIELD_PREP(EDMA_V0_DOORBELL_CH_MASK, chan->id));
+ SET_RW_32(dw, chan->dir, doorbell,
+ FIELD_PREP(EDMA_V0_DOORBELL_CH_MASK, chan->id));
}
int dw_edma_v0_core_device_config(struct dw_edma_chan *chan)
@@ -273,31 +273,31 @@ int dw_edma_v0_core_device_config(struct
u32 tmp = 0;
/* MSI done addr - low, high */
- SET_RW(dw, chan->dir, done_imwr_low, chan->msi.address_lo);
- SET_RW(dw, chan->dir, done_imwr_high, chan->msi.address_hi);
+ SET_RW_32(dw, chan->dir, done_imwr_low, chan->msi.address_lo);
+ SET_RW_32(dw, chan->dir, done_imwr_high, chan->msi.address_hi);
/* MSI abort addr - low, high */
- SET_RW(dw, chan->dir, abort_imwr_low, chan->msi.address_lo);
- SET_RW(dw, chan->dir, abort_imwr_high, chan->msi.address_hi);
+ SET_RW_32(dw, chan->dir, abort_imwr_low, chan->msi.address_lo);
+ SET_RW_32(dw, chan->dir, abort_imwr_high, chan->msi.address_hi);
/* MSI data - low, high */
switch (chan->id) {
case 0:
case 1:
- tmp = GET_RW(dw, chan->dir, ch01_imwr_data);
+ tmp = GET_RW_32(dw, chan->dir, ch01_imwr_data);
break;
case 2:
case 3:
- tmp = GET_RW(dw, chan->dir, ch23_imwr_data);
+ tmp = GET_RW_32(dw, chan->dir, ch23_imwr_data);
break;
case 4:
case 5:
- tmp = GET_RW(dw, chan->dir, ch45_imwr_data);
+ tmp = GET_RW_32(dw, chan->dir, ch45_imwr_data);
break;
case 6:
case 7:
- tmp = GET_RW(dw, chan->dir, ch67_imwr_data);
+ tmp = GET_RW_32(dw, chan->dir, ch67_imwr_data);
break;
}
@@ -316,22 +316,22 @@ int dw_edma_v0_core_device_config(struct
switch (chan->id) {
case 0:
case 1:
- SET_RW(dw, chan->dir, ch01_imwr_data, tmp);
+ SET_RW_32(dw, chan->dir, ch01_imwr_data, tmp);
break;
case 2:
case 3:
- SET_RW(dw, chan->dir, ch23_imwr_data, tmp);
+ SET_RW_32(dw, chan->dir, ch23_imwr_data, tmp);
break;
case 4:
case 5:
- SET_RW(dw, chan->dir, ch45_imwr_data, tmp);
+ SET_RW_32(dw, chan->dir, ch45_imwr_data, tmp);
break;
case 6:
case 7:
- SET_RW(dw, chan->dir, ch67_imwr_data, tmp);
+ SET_RW_32(dw, chan->dir, ch67_imwr_data, tmp);
break;
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 100/235] dmaengine: dw-edma: Remove unused irq field in struct dw_edma_chip
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (98 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 099/235] dmaengine: dw-edma: Improve the linked list and data blocks definition Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 101/235] dmaengine: dw-edma: Add spinlock to protect DONE_INT_MASK and ABORT_INT_MASK Greg Kroah-Hartman
` (137 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Serge Semin, Manivannan Sadhasivam,
Frank Li, Bjorn Helgaas, Vinod Koul, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Frank Li <Frank.Li@nxp.com>
[ Upstream commit 5a0e4529d9aee8ce348f628ad476c9ddb6cf457d ]
The "irq" field of struct dw_edma_chip was never used. Remove it.
Link: https://lore.kernel.org/r/20220524152159.2370739-2-Frank.Li@nxp.com
Tested-by: Serge Semin <fancer.lancer@gmail.com>
Tested-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Serge Semin <fancer.lancer@gmail.com>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Acked-By: Vinod Koul <vkoul@kernel.org>
Stable-dep-of: 8ffba0171c6b ("dmaengine: dw-edma: Add spinlock to protect DONE_INT_MASK and ABORT_INT_MASK")
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 | 1 -
include/linux/dma/edma.h | 2 --
2 files changed, 3 deletions(-)
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -175,7 +175,6 @@ static int dw_edma_pcie_probe(struct pci
chip->dw = dw;
chip->dev = dev;
chip->id = pdev->devfn;
- chip->irq = pdev->irq;
dw->chip = chip;
dw->version = pdata->version;
--- a/include/linux/dma/edma.h
+++ b/include/linux/dma/edma.h
@@ -18,13 +18,11 @@ struct dw_edma;
* struct dw_edma_chip - representation of DesignWare eDMA controller hardware
* @dev: struct device of the eDMA controller
* @id: instance ID
- * @irq: irq line
* @dw: struct dw_edma that is filed by dw_edma_probe()
*/
struct dw_edma_chip {
struct device *dev;
int id;
- int irq;
struct dw_edma *dw;
};
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 101/235] dmaengine: dw-edma: Add spinlock to protect DONE_INT_MASK and ABORT_INT_MASK
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (99 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 100/235] dmaengine: dw-edma: Remove unused irq field in struct dw_edma_chip Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 102/235] i2c: imx: separate atomic, dma and non-dma use case Greg Kroah-Hartman
` (136 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Frank Li, Koichiro Den, Vinod Koul,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Frank Li <Frank.Li@nxp.com>
[ Upstream commit 8ffba0171c6bbce5f093c6dba5a02c0805b31203 ]
The DONE_INT_MASK and ABORT_INT_MASK registers are shared by all DMA
channels, and modifying them requires a read-modify-write sequence.
Because this operation is not atomic, concurrent calls to
dw_edma_v0_core_start() can introduce race conditions if two channels
update these registers simultaneously.
Add a spinlock to serialize access to these registers and prevent race
conditions.
Fixes: 7e4b8a4fbe2c ("dmaengine: Add Synopsys eDMA IP version 0 support")
Cc: stable@vger.kernel.org
Signed-off-by: Frank Li <Frank.Li@nxp.com>
[den: update dw_edma.lock comment]
Link: https://lore.kernel.org/dmaengine/20260109-edma_ll-v2-1-5c0b27b2c664@nxp.com/
Signed-off-by: Koichiro Den <den@valinux.co.jp>
Link: https://patch.msgid.link/20260521142153.2957432-5-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-core.h | 2 +-
drivers/dma/dw-edma/dw-edma-v0-core.c | 6 ++++++
2 files changed, 7 insertions(+), 1 deletion(-)
--- a/drivers/dma/dw-edma/dw-edma-core.h
+++ b/drivers/dma/dw-edma/dw-edma-core.h
@@ -131,7 +131,7 @@ struct dw_edma {
struct dw_edma_chan *chan;
- raw_spinlock_t lock; /* Only for legacy */
+ raw_spinlock_t lock; /* Protect v0 shared registers */
struct dw_edma_chip *chip;
--- a/drivers/dma/dw-edma/dw-edma-v0-core.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
@@ -237,6 +237,7 @@ void dw_edma_v0_core_start(struct dw_edm
{
struct dw_edma_chan *chan = chunk->chan;
struct dw_edma *dw = chan->dw;
+ unsigned long flags;
u32 tmp;
dw_edma_v0_core_write_chunk(chunk);
@@ -245,6 +246,8 @@ void dw_edma_v0_core_start(struct dw_edm
/* Enable engine */
SET_RW_32(dw, chan->dir, engine_en, BIT(0));
/* Interrupt unmask - done, abort */
+ raw_spin_lock_irqsave(&dw->lock, flags);
+
tmp = GET_RW_32(dw, chan->dir, int_mask);
tmp &= ~FIELD_PREP(EDMA_V0_DONE_INT_MASK, BIT(chan->id));
tmp &= ~FIELD_PREP(EDMA_V0_ABORT_INT_MASK, BIT(chan->id));
@@ -253,6 +256,9 @@ void dw_edma_v0_core_start(struct dw_edm
tmp = GET_RW_32(dw, chan->dir, linked_list_err_en);
tmp |= FIELD_PREP(EDMA_V0_LINKED_LIST_ERR_MASK, BIT(chan->id));
SET_RW_32(dw, chan->dir, linked_list_err_en, tmp);
+
+ raw_spin_unlock_irqrestore(&dw->lock, flags);
+
/* Channel control */
SET_CH_32(dw, chan->dir, chan->id, ch_control1,
(DW_EDMA_V0_CCS | DW_EDMA_V0_LLE));
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 102/235] i2c: imx: separate atomic, dma and non-dma use case
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (100 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 101/235] dmaengine: dw-edma: Add spinlock to protect DONE_INT_MASK and ABORT_INT_MASK Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 103/235] i2c: imx: fix locked bus on SMBus block-read of 0 (atomic) Greg Kroah-Hartman
` (135 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Stefan Eichenberger, Frank Li,
Oleksij Rempel, Andi Shyti, Sasha Levin
5.10-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
@@ -717,6 +717,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)
{
@@ -727,6 +764,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;
@@ -837,50 +879,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;
@@ -947,6 +963,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)
{
@@ -954,6 +976,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;
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
@@ -1008,15 +1031,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] 239+ messages in thread
* [PATCH 5.10 103/235] i2c: imx: fix locked bus on SMBus block-read of 0 (atomic)
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (101 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 102/235] i2c: imx: separate atomic, dma and non-dma use case Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 104/235] thunderbolt: Keep XDomain reference during the lifetime of a service Greg Kroah-Hartman
` (134 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Vincent Jardin, Oleksij Rempel,
Carlos Song, Stefan Eichenberger, Andi Shyti, Sasha Levin
5.10-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
@@ -890,6 +890,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)
@@ -911,8 +912,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);
@@ -960,7 +973,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] 239+ messages in thread
* [PATCH 5.10 104/235] thunderbolt: Keep XDomain reference during the lifetime of a service
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (102 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 103/235] i2c: imx: fix locked bus on SMBus block-read of 0 (atomic) Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 105/235] thunderbolt: Remove XDomain from the bus without holding tb->lock Greg Kroah-Hartman
` (133 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Mika Westerberg, Sasha Levin
5.10-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
@@ -784,6 +784,7 @@ static void tb_service_release(struct de
ida_simple_remove(&xd->service_ids, svc->id);
kfree(svc->key);
kfree(svc);
+ tb_xdomain_put(xd);
}
struct device_type tb_service_type = {
@@ -892,7 +893,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);
if (device_register(&svc->dev)) {
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 105/235] thunderbolt: Remove XDomain from the bus without holding tb->lock
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (103 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 104/235] thunderbolt: Keep XDomain reference during the lifetime of a service Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 106/235] thunderbolt: Prevent XDomain delayed work use-after-free on disconnect Greg Kroah-Hartman
` (132 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Mika Westerberg, Sasha Levin
5.10-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/domain.c | 30 +++++++++++++++++++++
drivers/thunderbolt/icm.c | 5 +++
drivers/thunderbolt/switch.c | 14 ++++++++++
drivers/thunderbolt/tb.c | 58 +++++++++++++++++++++---------------------
drivers/thunderbolt/tb.h | 2 +
drivers/thunderbolt/xdomain.c | 48 ++++++++++++++++++++++------------
6 files changed, 111 insertions(+), 46 deletions(-)
--- a/drivers/thunderbolt/domain.c
+++ b/drivers/thunderbolt/domain.c
@@ -823,6 +823,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
@@ -695,6 +695,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);
}
@@ -1682,6 +1683,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,
@@ -2023,6 +2026,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
@@ -2737,6 +2737,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
@@ -1208,6 +1208,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);
@@ -1375,6 +1377,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);
@@ -1388,6 +1408,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);
list_for_each_entry_safe(tunnel, n, &tcm->tunnel_list, list)
tb_tunnel_restart(tunnel);
@@ -1406,28 +1427,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);
@@ -1447,14 +1446,15 @@ 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))
+ if (tb_domain_unregister_unplugged_xdomains(tb)) {
+ mutex_lock(&tb->lock);
tb_scan_switch(tb->root_switch);
- mutex_unlock(&tb->lock);
+ mutex_unlock(&tb->lock);
+ }
}
static int tb_runtime_suspend(struct tb *tb)
@@ -1475,11 +1475,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
@@ -623,6 +623,7 @@ int tb_domain_disconnect_pcie_paths(stru
int tb_domain_approve_xdomain_paths(struct tb *tb, struct tb_xdomain *xd);
int tb_domain_disconnect_xdomain_paths(struct tb *tb, struct tb_xdomain *xd);
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)
{
@@ -939,6 +940,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
@@ -1358,32 +1358,46 @@ 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)
{
stop_handshake(xd);
- device_for_each_child_reverse(&xd->dev, xd, unregister_service);
+ 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);
+ }
+}
- /*
- * 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);
+/**
+ * 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)
+{
+ device_for_each_child_reverse(&xd->dev, xd, unregister_service);
- if (!device_is_registered(&xd->dev))
- put_device(&xd->dev);
- else
- device_unregister(&xd->dev);
+ device_unregister(&xd->dev);
}
/**
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 106/235] thunderbolt: Prevent XDomain delayed work use-after-free on disconnect
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (104 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 105/235] thunderbolt: Remove XDomain from the bus without holding tb->lock Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 107/235] scsi: lpfc: Fix memory leak in lpfc_sli4_driver_resource_setup() Greg Kroah-Hartman
` (131 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Michael Bommarito, Mika Westerberg,
Sasha Levin
5.10-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 | 20 ++++++++++++++++----
include/linux/thunderbolt.h | 3 +++
2 files changed, 19 insertions(+), 4 deletions(-)
--- a/drivers/thunderbolt/xdomain.c
+++ b/drivers/thunderbolt/xdomain.c
@@ -604,8 +604,12 @@ static void tb_xdp_handle_request(struct
*/
xd = tb_xdomain_find_by_uuid_locked(tb, &xchg->src_uuid);
if (xd) {
- queue_delayed_work(tb->wq, &xd->get_properties_work,
- msecs_to_jiffies(50));
+ mutex_lock(&xd->lock);
+ if (!xd->removing)
+ queue_delayed_work(tb->wq,
+ &xd->get_properties_work,
+ msecs_to_jiffies(50));
+ mutex_unlock(&xd->lock);
tb_xdomain_put(xd);
}
@@ -1369,6 +1373,10 @@ static int unregister_service(struct dev
*/
void tb_xdomain_remove(struct tb_xdomain *xd)
{
+ mutex_lock(&xd->lock);
+ xd->removing = true;
+ mutex_unlock(&xd->lock);
+
stop_handshake(xd);
if (!device_is_registered(&xd->dev)) {
@@ -1646,8 +1654,12 @@ static int update_xdomain(struct device
xd = tb_to_xdomain(dev);
if (xd) {
- queue_delayed_work(xd->tb->wq, &xd->properties_changed_work,
- msecs_to_jiffies(50));
+ mutex_lock(&xd->lock);
+ if (!xd->removing)
+ queue_delayed_work(xd->tb->wq,
+ &xd->properties_changed_work,
+ msecs_to_jiffies(50));
+ mutex_unlock(&xd->lock);
}
return 0;
--- a/include/linux/thunderbolt.h
+++ b/include/linux/thunderbolt.h
@@ -181,6 +181,8 @@ void tb_unregister_property_dir(const ch
* @device_name: Name of the device (or %NULL if not known)
* @is_unplugged: The XDomain is unplugged
* @resume: The XDomain is being resumed
+ * @removing: Set by tb_xdomain_remove() under @lock to prevent
+ * concurrent delayed work queueing
* @needs_uuid: If the XDomain does not have @remote_uuid it will be
* queried first
* @transmit_path: HopID which the remote end expects us to transmit
@@ -225,6 +227,7 @@ struct tb_xdomain {
const char *device_name;
bool is_unplugged;
bool resume;
+ bool removing;
bool needs_uuid;
u16 transmit_path;
u16 transmit_ring;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 107/235] scsi: lpfc: Fix memory leak in lpfc_sli4_driver_resource_setup()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (105 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 106/235] thunderbolt: Prevent XDomain delayed work use-after-free on disconnect Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 108/235] ovl: use linked upper dentry in copy-up tmpfile Greg Kroah-Hartman
` (130 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Abdun Nihaal, Justin Tee,
Martin K. Petersen, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdun Nihaal <nihaal@cse.iitm.ac.in>
[ Upstream commit 1bd28625e25be549ee7c47532e7c3ef91c682410 ]
The memory allocated for mboxq using mempool_alloc() is not freed in
some of the early exit error paths. Fix that by moving the
mempool_free() call to an earlier point after last use.
Fixes: d79c9e9d4b3d ("scsi: lpfc: Support dynamic unbounded SGL lists on G7 hardware.")
Cc: stable@vger.kernel.org
Signed-off-by: Abdun Nihaal <nihaal@cse.iitm.ac.in>
Reviewed-by: Justin Tee <justin.tee@broadcom.com>
Link: https://patch.msgid.link/20260707065304.949135-1-nihaal@cse.iitm.ac.in
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/scsi/lpfc/lpfc_init.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -6811,6 +6811,7 @@ lpfc_sli4_driver_resource_setup(struct l
goto out_free_bsmbx;
}
}
+ mempool_free(mboxq, phba->mbox_mem_pool);
/*
* 1 for cmd, 1 for rsp, NVME adds an extra one
@@ -6932,8 +6933,6 @@ lpfc_sli4_driver_resource_setup(struct l
if (!phba->lpfc_cmd_rsp_buf_pool)
goto out_free_sg_dma_buf;
- mempool_free(mboxq, phba->mbox_mem_pool);
-
/* Verify OAS is supported */
lpfc_sli4_oas_verify(phba);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 108/235] ovl: use linked upper dentry in copy-up tmpfile
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (106 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 107/235] scsi: lpfc: Fix memory leak in lpfc_sli4_driver_resource_setup() Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 109/235] scsi: target: core: pr: Initialize arrays at declaration time Greg Kroah-Hartman
` (129 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Souvik Banerjee, Amir Goldstein,
Miklos Szeredi, Christian Brauner (Amutable), Sasha Levin
5.10-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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/overlayfs/copy_up.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -648,7 +648,7 @@ cleanup:
static int ovl_copy_up_tmpfile(struct ovl_copy_up_ctx *c)
{
struct inode *udir = d_inode(c->destdir);
- struct dentry *temp, *upper;
+ struct dentry *temp, *upper, *newdentry = NULL;
struct ovl_cu_creds cc;
int err;
@@ -672,6 +672,14 @@ static int ovl_copy_up_tmpfile(struct ov
err = PTR_ERR(upper);
if (!IS_ERR(upper)) {
err = ovl_do_link(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);
@@ -681,9 +689,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), temp);
-
- return 0;
+ ovl_inode_update(d_inode(c->dentry), newdentry);
out_dput:
dput(temp);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 109/235] scsi: target: core: pr: Initialize arrays at declaration time
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (107 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 108/235] ovl: use linked upper dentry in copy-up tmpfile Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 110/235] scsi: target: core: Generate correct identifiers for PR OUT transport IDs Greg Kroah-Hartman
` (128 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Mike Christie, Johannes Thumshirn,
Chaitanya Kulkarni, Martin K. Petersen, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
[ Upstream commit 4db6dfe62c5f76ce9eef28967c2e2000efde10d5 ]
Avoids calling memset().
Link: https://lore.kernel.org/r/20210228055645.22253-21-chaitanya.kulkarni@wdc.com
Link: https://lore.kernel.org/r/20210228055645.22253-22-chaitanya.kulkarni@wdc.com
Link: https://lore.kernel.org/r/20210228055645.22253-23-chaitanya.kulkarni@wdc.com
Reviewed-by: Mike Christie <michael.christie@oracle.com>
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Stable-dep-of: d04a179085c2 ("scsi: target: Bound PR-OUT TransportID parsing to the received buffer")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/target/target_core_pr.c | 36 +++++++++++++-----------------------
1 file changed, 13 insertions(+), 23 deletions(-)
--- a/drivers/target/target_core_pr.c
+++ b/drivers/target/target_core_pr.c
@@ -895,9 +895,8 @@ static void core_scsi3_aptpl_reserve(
struct se_node_acl *node_acl,
struct t10_pr_registration *pr_reg)
{
- char i_buf[PR_REG_ISID_ID_LEN];
+ char i_buf[PR_REG_ISID_ID_LEN] = { };
- memset(i_buf, 0, PR_REG_ISID_ID_LEN);
core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN);
spin_lock(&dev->dev_reservation_lock);
@@ -927,12 +926,10 @@ static int __core_scsi3_check_aptpl_regi
{
struct t10_pr_registration *pr_reg, *pr_reg_tmp;
struct t10_reservation *pr_tmpl = &dev->t10_pr;
- unsigned char i_port[PR_APTPL_MAX_IPORT_LEN];
- unsigned char t_port[PR_APTPL_MAX_TPORT_LEN];
+ unsigned char i_port[PR_APTPL_MAX_IPORT_LEN] = { };
+ unsigned char t_port[PR_APTPL_MAX_TPORT_LEN] = { };
u16 tpgt;
- memset(i_port, 0, PR_APTPL_MAX_IPORT_LEN);
- memset(t_port, 0, PR_APTPL_MAX_TPORT_LEN);
/*
* Copy Initiator Port information from struct se_node_acl
*/
@@ -1022,9 +1019,8 @@ static void __core_scsi3_dump_registrati
enum register_type register_type)
{
struct se_portal_group *se_tpg = nacl->se_tpg;
- char i_buf[PR_REG_ISID_ID_LEN];
+ char i_buf[PR_REG_ISID_ID_LEN] = { };
- memset(&i_buf[0], 0, PR_REG_ISID_ID_LEN);
core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN);
pr_debug("SPC-3 PR [%s] Service Action: REGISTER%s Initiator"
@@ -1203,10 +1199,10 @@ static struct t10_pr_registration *core_
struct se_session *sess)
{
struct se_portal_group *tpg = nacl->se_tpg;
- unsigned char buf[PR_REG_ISID_LEN], *isid_ptr = NULL;
+ unsigned char buf[PR_REG_ISID_LEN] = { };
+ unsigned char *isid_ptr = NULL;
if (tpg->se_tpg_tfo->sess_get_initiator_sid != NULL) {
- memset(&buf[0], 0, PR_REG_ISID_LEN);
tpg->se_tpg_tfo->sess_get_initiator_sid(sess, &buf[0],
PR_REG_ISID_LEN);
isid_ptr = &buf[0];
@@ -1284,11 +1280,10 @@ static void __core_scsi3_free_registrati
struct t10_reservation *pr_tmpl = &dev->t10_pr;
struct se_node_acl *nacl = pr_reg->pr_reg_nacl;
struct se_dev_entry *deve;
- char i_buf[PR_REG_ISID_ID_LEN];
+ char i_buf[PR_REG_ISID_ID_LEN] = { };
lockdep_assert_held(&pr_tmpl->registration_lock);
- memset(i_buf, 0, PR_REG_ISID_ID_LEN);
core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN);
if (!list_empty(&pr_reg->pr_reg_list))
@@ -2060,7 +2055,8 @@ core_scsi3_emulate_pro_register(struct s
struct se_portal_group *se_tpg;
struct t10_pr_registration *pr_reg, *pr_reg_p, *pr_reg_tmp;
struct t10_reservation *pr_tmpl = &dev->t10_pr;
- unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL;
+ unsigned char isid_buf[PR_REG_ISID_LEN] = { };
+ unsigned char *isid_ptr = NULL;
sense_reason_t ret = TCM_NO_SENSE;
int pr_holder = 0, type;
@@ -2071,7 +2067,6 @@ core_scsi3_emulate_pro_register(struct s
se_tpg = se_sess->se_tpg;
if (se_tpg->se_tpg_tfo->sess_get_initiator_sid) {
- memset(&isid_buf[0], 0, PR_REG_ISID_LEN);
se_tpg->se_tpg_tfo->sess_get_initiator_sid(se_sess, &isid_buf[0],
PR_REG_ISID_LEN);
isid_ptr = &isid_buf[0];
@@ -2283,11 +2278,9 @@ core_scsi3_pro_reserve(struct se_cmd *cm
struct se_lun *se_lun = cmd->se_lun;
struct t10_pr_registration *pr_reg, *pr_res_holder;
struct t10_reservation *pr_tmpl = &dev->t10_pr;
- char i_buf[PR_REG_ISID_ID_LEN];
+ char i_buf[PR_REG_ISID_ID_LEN] = { };
sense_reason_t ret;
- memset(i_buf, 0, PR_REG_ISID_ID_LEN);
-
if (!se_sess || !se_lun) {
pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
@@ -2458,12 +2451,11 @@ static void __core_scsi3_complete_pro_re
int unreg)
{
const struct target_core_fabric_ops *tfo = se_nacl->se_tpg->se_tpg_tfo;
- char i_buf[PR_REG_ISID_ID_LEN];
+ char i_buf[PR_REG_ISID_ID_LEN] = { };
int pr_res_type = 0, pr_res_scope = 0;
lockdep_assert_held(&dev->dev_reservation_lock);
- memset(i_buf, 0, PR_REG_ISID_ID_LEN);
core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN);
/*
* Go ahead and release the current PR reservation holder.
@@ -2769,11 +2761,10 @@ static void __core_scsi3_complete_pro_pr
{
struct se_node_acl *nacl = pr_reg->pr_reg_nacl;
const struct target_core_fabric_ops *tfo = nacl->se_tpg->se_tpg_tfo;
- char i_buf[PR_REG_ISID_ID_LEN];
+ char i_buf[PR_REG_ISID_ID_LEN] = { };
lockdep_assert_held(&dev->dev_reservation_lock);
- memset(i_buf, 0, PR_REG_ISID_ID_LEN);
core_pr_dump_initiator_port(pr_reg, i_buf, PR_REG_ISID_ID_LEN);
/*
* Do an implicit RELEASE of the existing reservation.
@@ -3159,7 +3150,7 @@ core_scsi3_emulate_pro_register_and_move
struct t10_reservation *pr_tmpl = &dev->t10_pr;
unsigned char *buf;
const unsigned char *initiator_str;
- char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN];
+ char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN] = { };
u32 tid_len, tmp_tid_len;
int new_reg = 0, type, scope, matching_iname;
sense_reason_t ret;
@@ -3171,7 +3162,6 @@ core_scsi3_emulate_pro_register_and_move
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
}
- memset(i_buf, 0, PR_REG_ISID_ID_LEN);
se_tpg = se_sess->se_tpg;
tf_ops = se_tpg->se_tpg_tfo;
/*
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 110/235] scsi: target: core: Generate correct identifiers for PR OUT transport IDs
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (108 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 109/235] scsi: target: core: pr: Initialize arrays at declaration time Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 111/235] scsi: target: Bound PR-OUT TransportID parsing to the received buffer Greg Kroah-Hartman
` (127 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Maurizio Lombardi, Dmitry Bogdanov,
Martin K. Petersen, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maurizio Lombardi <mlombard@redhat.com>
[ Upstream commit 6e0f6aa44b68335df404a2df955055f416b5f2aa ]
Fix target_parse_pr_out_transport_id() to return a string representing
the transport ID in a human-readable format (e.g., naa.xxxxxxxx...) for
various SCSI protocol types (SAS, FCP, SRP, SBP).
Previously, the function returned a pointer to the raw binary buffer,
which was incorrectly compared against human-readable strings, causing
comparisons to fail. Now, the function writes a properly formatted
string into a buffer provided by the caller. The output format depends
on the transport protocol:
* SAS: 64-bit identifier, "naa." prefix.
* FCP: 64-bit identifier, colon separated values.
* SBP: 64-bit identifier, no prefix.
* SRP: 128-bit identifier, "0x" prefix.
* iSCSI: IQN string.
Signed-off-by: Maurizio Lombardi <mlombard@redhat.com>
Link: https://lore.kernel.org/r/20250714133738.11054-1-mlombard@redhat.com
Reviewed-by: Dmitry Bogdanov <d.bogdanov@yadro.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Stable-dep-of: d04a179085c2 ("scsi: target: Bound PR-OUT TransportID parsing to the received buffer")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/target/target_core_fabric_lib.c | 63 ++++++++++++++++++++++++--------
drivers/target/target_core_internal.h | 4 +-
drivers/target/target_core_pr.c | 18 +++++----
3 files changed, 60 insertions(+), 25 deletions(-)
--- a/drivers/target/target_core_fabric_lib.c
+++ b/drivers/target/target_core_fabric_lib.c
@@ -257,11 +257,41 @@ static int iscsi_get_pr_transport_id_len
return len;
}
-static char *iscsi_parse_pr_out_transport_id(
+static void sas_parse_pr_out_transport_id(char *buf, char *i_str)
+{
+ char hex[17] = {};
+
+ bin2hex(hex, buf + 4, 8);
+ snprintf(i_str, TRANSPORT_IQN_LEN, "naa.%s", hex);
+}
+
+static void srp_parse_pr_out_transport_id(char *buf, char *i_str)
+{
+ char hex[33] = {};
+
+ bin2hex(hex, buf + 8, 16);
+ snprintf(i_str, TRANSPORT_IQN_LEN, "0x%s", hex);
+}
+
+static void fcp_parse_pr_out_transport_id(char *buf, char *i_str)
+{
+ snprintf(i_str, TRANSPORT_IQN_LEN, "%8phC", buf + 8);
+}
+
+static void sbp_parse_pr_out_transport_id(char *buf, char *i_str)
+{
+ char hex[17] = {};
+
+ bin2hex(hex, buf + 8, 8);
+ snprintf(i_str, TRANSPORT_IQN_LEN, "%s", hex);
+}
+
+static bool iscsi_parse_pr_out_transport_id(
struct se_portal_group *se_tpg,
char *buf,
u32 *out_tid_len,
- char **port_nexus_ptr)
+ char **port_nexus_ptr,
+ char *i_str)
{
char *p;
int i;
@@ -282,7 +312,7 @@ static char *iscsi_parse_pr_out_transpor
if ((format_code != 0x00) && (format_code != 0x40)) {
pr_err("Illegal format code: 0x%02x for iSCSI"
" Initiator Transport ID\n", format_code);
- return NULL;
+ return false;
}
/*
* If the caller wants the TransportID Length, we set that value for the
@@ -306,7 +336,7 @@ static char *iscsi_parse_pr_out_transpor
pr_err("Unable to locate \",i,0x\" separator"
" for Initiator port identifier: %s\n",
&buf[4]);
- return NULL;
+ return false;
}
*p = '\0'; /* Terminate iSCSI Name */
p += 5; /* Skip over ",i,0x" separator */
@@ -339,7 +369,8 @@ static char *iscsi_parse_pr_out_transpor
} else
*port_nexus_ptr = NULL;
- return &buf[4];
+ strscpy(i_str, &buf[4], TRANSPORT_IQN_LEN);
+ return true;
}
int target_get_pr_transport_id_len(struct se_node_acl *nacl,
@@ -387,33 +418,35 @@ int target_get_pr_transport_id(struct se
}
}
-const char *target_parse_pr_out_transport_id(struct se_portal_group *tpg,
- char *buf, u32 *out_tid_len, char **port_nexus_ptr)
+bool target_parse_pr_out_transport_id(struct se_portal_group *tpg,
+ char *buf, u32 *out_tid_len, char **port_nexus_ptr, char *i_str)
{
- u32 offset;
-
switch (tpg->proto_id) {
case SCSI_PROTOCOL_SAS:
/*
* Assume the FORMAT CODE 00b from spc4r17, 7.5.4.7 TransportID
* for initiator ports using SCSI over SAS Serial SCSI Protocol.
*/
- offset = 4;
+ sas_parse_pr_out_transport_id(buf, i_str);
break;
- case SCSI_PROTOCOL_SBP:
case SCSI_PROTOCOL_SRP:
+ srp_parse_pr_out_transport_id(buf, i_str);
+ break;
case SCSI_PROTOCOL_FCP:
- offset = 8;
+ fcp_parse_pr_out_transport_id(buf, i_str);
+ break;
+ case SCSI_PROTOCOL_SBP:
+ sbp_parse_pr_out_transport_id(buf, i_str);
break;
case SCSI_PROTOCOL_ISCSI:
return iscsi_parse_pr_out_transport_id(tpg, buf, out_tid_len,
- port_nexus_ptr);
+ port_nexus_ptr, i_str);
default:
pr_err("Unknown proto_id: 0x%02x\n", tpg->proto_id);
- return NULL;
+ return false;
}
*port_nexus_ptr = NULL;
*out_tid_len = 24;
- return buf + offset;
+ return true;
}
--- a/drivers/target/target_core_internal.h
+++ b/drivers/target/target_core_internal.h
@@ -102,8 +102,8 @@ int target_get_pr_transport_id_len(struc
int target_get_pr_transport_id(struct se_node_acl *nacl,
struct t10_pr_registration *pr_reg, int *format_code,
unsigned char *buf);
-const char *target_parse_pr_out_transport_id(struct se_portal_group *tpg,
- char *buf, u32 *out_tid_len, char **port_nexus_ptr);
+bool target_parse_pr_out_transport_id(struct se_portal_group *tpg,
+ char *buf, u32 *out_tid_len, char **port_nexus_ptr, char *i_str);
/* target_core_hba.c */
struct se_hba *core_alloc_hba(const char *, u32, u32);
--- a/drivers/target/target_core_pr.c
+++ b/drivers/target/target_core_pr.c
@@ -1486,11 +1486,12 @@ core_scsi3_decode_spec_i_port(
LIST_HEAD(tid_dest_list);
struct pr_transport_id_holder *tidh_new, *tidh, *tidh_tmp;
unsigned char *buf, *ptr, proto_ident;
- const unsigned char *i_str = NULL;
+ unsigned char i_str[TRANSPORT_IQN_LEN];
char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN];
sense_reason_t ret;
u32 tpdl, tid_len = 0;
u32 dest_rtpi = 0;
+ bool tid_found;
/*
* Allocate a struct pr_transport_id_holder and setup the
@@ -1579,9 +1580,9 @@ core_scsi3_decode_spec_i_port(
dest_rtpi = tmp_lun->lun_rtpi;
iport_ptr = NULL;
- i_str = target_parse_pr_out_transport_id(tmp_tpg,
- ptr, &tid_len, &iport_ptr);
- if (!i_str)
+ tid_found = target_parse_pr_out_transport_id(tmp_tpg,
+ ptr, &tid_len, &iport_ptr, i_str);
+ if (!tid_found)
continue;
/*
* Determine if this SCSI device server requires that
@@ -3149,13 +3150,14 @@ core_scsi3_emulate_pro_register_and_move
struct t10_pr_registration *pr_reg, *pr_res_holder, *dest_pr_reg;
struct t10_reservation *pr_tmpl = &dev->t10_pr;
unsigned char *buf;
- const unsigned char *initiator_str;
+ unsigned char initiator_str[TRANSPORT_IQN_LEN];
char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN] = { };
u32 tid_len, tmp_tid_len;
int new_reg = 0, type, scope, matching_iname;
sense_reason_t ret;
unsigned short rtpi;
unsigned char proto_ident;
+ bool tid_found;
if (!se_sess || !se_lun) {
pr_err("SPC-3 PR: se_sess || struct se_lun is NULL!\n");
@@ -3274,9 +3276,9 @@ core_scsi3_emulate_pro_register_and_move
ret = TCM_INVALID_PARAMETER_LIST;
goto out;
}
- initiator_str = target_parse_pr_out_transport_id(dest_se_tpg,
- &buf[24], &tmp_tid_len, &iport_ptr);
- if (!initiator_str) {
+ tid_found = target_parse_pr_out_transport_id(dest_se_tpg,
+ &buf[24], &tmp_tid_len, &iport_ptr, initiator_str);
+ if (!tid_found) {
pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate"
" initiator_str from Transport ID\n");
ret = TCM_INVALID_PARAMETER_LIST;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 111/235] scsi: target: Bound PR-OUT TransportID parsing to the received buffer
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (109 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 110/235] scsi: target: core: Generate correct identifiers for PR OUT transport IDs Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 112/235] dm-integrity: dont increment hash_offset twice Greg Kroah-Hartman
` (126 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Bryam Vargas, John Garry,
David Disseldorp, Martin K. Petersen, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <hexlabsecurity@proton.me>
[ Upstream commit d04a179085c262c9ed577d0a4cbc6482ff1fd9a3 ]
core_scsi3_decode_spec_i_port() and core_scsi3_emulate_register_and_move()
hand the raw PERSISTENT RESERVE OUT parameter buffer to
target_parse_pr_out_transport_id() without telling it how many bytes are
valid. For an iSCSI TransportID (FORMAT CODE 01b),
iscsi_parse_pr_out_transport_id() locates the ",i,0x" ISID separator with
an unbounded strstr() (and on the error path prints the name with a further
unbounded "%s"). An initiator can submit a TransportID whose iSCSI name
contains neither a ",i,0x" substring nor a NUL terminator, filling the
parameter list to its end, so the scan runs off the end of the buffer.
When the parameter list spans more than one page the buffer is a multi-page
vmap (transport_kmap_data_sg()), so the over-read walks into the trailing
vmalloc guard page and oopses (KASAN: vmalloc-out-of-bounds in strstr). It
is reachable by any fabric that delivers a PR OUT to a device exported
through an iSCSI TPG, including a guest via vhost-scsi.
Pass the number of received bytes down to the parser and validate the iSCSI
TransportID's own self-described length (ADDITIONAL LENGTH + 4) once, up
front: reject it if it is below the spc4r17 minimum or larger than the
received buffer, then bound the separator search, the ISID walk and the
name copy by that length. This is the length check the callers already
perform after the parse (core_scsi3_decode_spec_i_port() compares tid_len
against tpdl, core_scsi3_emulate_register_and_move() validates it against
data_length), moved ahead of the scan. Also drop the unbounded "%s" of the
unterminated name.
Add per-format explicit name-length checks before copying into i_str,
rather than silently truncating with min_t: for FORMAT CODE 00b reject if
the descriptor body (tid_len - 4 bytes) cannot fit in
i_str[TRANSPORT_IQN_LEN]; for FORMAT CODE 01b reject if the name portion
(from &buf[4] up to the separator) cannot fit. Both checks make the bounds
intent explicit at each format branch.
While here, also reject a FORMAT CODE 01b TransportID whose ",i,0x"
separator sits at the very end of the descriptor: that leaves an empty ISID
and points the returned port nexus pointer at buf + tid_len, one past the
descriptor, which the registration code (__core_scsi3_locate_pr_reg(),
__core_scsi3_alloc_registration()) then dereferences as the ISID string --
the same over-read of the parameter buffer for a malformed descriptor.
Fixes: c66ac9db8d4a ("[SCSI] target: Add LIO target core v4.0.0-rc6")
Cc: stable@vger.kernel.org
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
Reviewed-by: John Garry <john.g.garry@oracle.com>
Reviewed-by: David Disseldorp <ddiss@suse.de>
Link: https://patch.msgid.link/20260611-b4-disp-9f20739e-v6-1-f6630e2aae44@proton.me
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/target/target_core_fabric_lib.c | 89 ++++++++++++++++++++++++--------
drivers/target/target_core_internal.h | 3 -
drivers/target/target_core_pr.c | 4 -
3 files changed, 73 insertions(+), 23 deletions(-)
--- a/drivers/target/target_core_fabric_lib.c
+++ b/drivers/target/target_core_fabric_lib.c
@@ -289,13 +289,24 @@ static void sbp_parse_pr_out_transport_i
static bool iscsi_parse_pr_out_transport_id(
struct se_portal_group *se_tpg,
char *buf,
+ u32 buf_len,
u32 *out_tid_len,
char **port_nexus_ptr,
char *i_str)
{
char *p;
+ u32 tid_len;
int i;
- u8 format_code = (buf[0] & 0xc0);
+ u8 format_code;
+
+ /*
+ * The 4-byte iSCSI TransportID header (FORMAT CODE + 2-byte ADDITIONAL
+ * LENGTH) must be present before any of it can be parsed.
+ */
+ if (buf_len < 4)
+ return false;
+
+ format_code = buf[0] & 0xc0;
/*
* Check for FORMAT CODE 00b or 01b from spc4r17, section 7.5.4.6:
*
@@ -315,15 +326,17 @@ static bool iscsi_parse_pr_out_transport
return false;
}
/*
- * If the caller wants the TransportID Length, we set that value for the
- * entire iSCSI Tarnsport ID now.
+ * Reconstruct the self-described TransportID length from the ADDITIONAL
+ * LENGTH field plus the 4-byte header. Reject it if it is below the
+ * spc4r17 section 7.5.4.6 minimum (ADDITIONAL LENGTH shall be at least
+ * 20) or if it runs past the bytes actually received, so that every
+ * access below stays inside the TransportID.
*/
- if (out_tid_len) {
- /* The shift works thanks to integer promotion rules */
- *out_tid_len = get_unaligned_be16(&buf[2]);
- /* Add four bytes for iSCSI Transport ID header */
- *out_tid_len += 4;
- }
+ tid_len = get_unaligned_be16(&buf[2]) + 4;
+ if (tid_len < 24 || tid_len > buf_len)
+ return false;
+ if (out_tid_len)
+ *out_tid_len = tid_len;
/*
* Check for ',i,0x' separator between iSCSI Name and iSCSI Initiator
@@ -331,16 +344,32 @@ static bool iscsi_parse_pr_out_transport
* format.
*/
if (format_code == 0x40) {
- p = strstr(&buf[4], ",i,0x");
+ p = strnstr(&buf[4], ",i,0x", tid_len - 4);
if (!p) {
- pr_err("Unable to locate \",i,0x\" separator"
- " for Initiator port identifier: %s\n",
- &buf[4]);
+ pr_err("Unable to locate \",i,0x\" separator in iSCSI TransportID\n");
+ return false;
+ }
+ /*
+ * The iSCSI name runs from &buf[4] up to the separator; reject it
+ * if it cannot fit in i_str[TRANSPORT_IQN_LEN].
+ */
+ if (p - &buf[4] >= TRANSPORT_IQN_LEN) {
+ pr_err("iSCSI Initiator port name too long in TransportID\n");
return false;
}
*p = '\0'; /* Terminate iSCSI Name */
p += 5; /* Skip over ",i,0x" separator */
+ /*
+ * The ISID must follow the separator. A ",i,0x" sitting at the
+ * very end of the TransportID leaves no ISID and would point the
+ * port nexus at buf + tid_len, i.e. past the descriptor, which
+ * the registration code then reads as the ISID string.
+ */
+ if (p >= buf + tid_len) {
+ pr_err("Missing ISID in iSCSI Initiator port TransportID\n");
+ return false;
+ }
*port_nexus_ptr = p;
/*
* Go ahead and do the lower case conversion of the received
@@ -348,7 +377,7 @@ static bool iscsi_parse_pr_out_transport
* for comparison against the running iSCSI session's ISID from
* iscsi_target.c:lio_sess_get_initiator_sid()
*/
- for (i = 0; i < 12; i++) {
+ for (i = 0; i < 12 && p < buf + tid_len; i++) {
/*
* The first ISCSI INITIATOR SESSION ID field byte
* containing an ASCII null character terminates the
@@ -366,10 +395,22 @@ static bool iscsi_parse_pr_out_transport
*p = tolower(*p);
p++;
}
- } else
+ strscpy(i_str, &buf[4], TRANSPORT_IQN_LEN);
+ } else {
*port_nexus_ptr = NULL;
-
- strscpy(i_str, &buf[4], TRANSPORT_IQN_LEN);
+ /*
+ * FORMAT CODE 00b: the name occupies buf[4..tid_len-1]. The
+ * declared length tid_len - 4 must fit in i_str[TRANSPORT_IQN_LEN].
+ * (For 01b the same tid_len bound would be over-restrictive: the
+ * descriptor also carries the separator and ISID, so a legal
+ * <=223-byte name gives tid_len up to 244.)
+ */
+ if (tid_len - 4 >= TRANSPORT_IQN_LEN) {
+ pr_err("iSCSI Initiator port name too long in TransportID\n");
+ return false;
+ }
+ strscpy(i_str, &buf[4], tid_len - 4);
+ }
return true;
}
@@ -419,8 +460,16 @@ int target_get_pr_transport_id(struct se
}
bool target_parse_pr_out_transport_id(struct se_portal_group *tpg,
- char *buf, u32 *out_tid_len, char **port_nexus_ptr, char *i_str)
+ char *buf, u32 buf_len, u32 *out_tid_len,
+ char **port_nexus_ptr, char *i_str)
{
+ /*
+ * The fixed-length SAS/SRP/FCP/SBP TransportIDs are 24 bytes; the iSCSI
+ * format is variable and bounds itself against buf_len below.
+ */
+ if (tpg->proto_id != SCSI_PROTOCOL_ISCSI && buf_len < 24)
+ return false;
+
switch (tpg->proto_id) {
case SCSI_PROTOCOL_SAS:
/*
@@ -439,8 +488,8 @@ bool target_parse_pr_out_transport_id(st
sbp_parse_pr_out_transport_id(buf, i_str);
break;
case SCSI_PROTOCOL_ISCSI:
- return iscsi_parse_pr_out_transport_id(tpg, buf, out_tid_len,
- port_nexus_ptr, i_str);
+ return iscsi_parse_pr_out_transport_id(tpg, buf, buf_len,
+ out_tid_len, port_nexus_ptr, i_str);
default:
pr_err("Unknown proto_id: 0x%02x\n", tpg->proto_id);
return false;
--- a/drivers/target/target_core_internal.h
+++ b/drivers/target/target_core_internal.h
@@ -103,7 +103,8 @@ int target_get_pr_transport_id(struct se
struct t10_pr_registration *pr_reg, int *format_code,
unsigned char *buf);
bool target_parse_pr_out_transport_id(struct se_portal_group *tpg,
- char *buf, u32 *out_tid_len, char **port_nexus_ptr, char *i_str);
+ char *buf, u32 buf_len, u32 *out_tid_len,
+ char **port_nexus_ptr, char *i_str);
/* target_core_hba.c */
struct se_hba *core_alloc_hba(const char *, u32, u32);
--- a/drivers/target/target_core_pr.c
+++ b/drivers/target/target_core_pr.c
@@ -1581,7 +1581,7 @@ core_scsi3_decode_spec_i_port(
iport_ptr = NULL;
tid_found = target_parse_pr_out_transport_id(tmp_tpg,
- ptr, &tid_len, &iport_ptr, i_str);
+ ptr, tpdl, &tid_len, &iport_ptr, i_str);
if (!tid_found)
continue;
/*
@@ -3277,7 +3277,7 @@ core_scsi3_emulate_pro_register_and_move
goto out;
}
tid_found = target_parse_pr_out_transport_id(dest_se_tpg,
- &buf[24], &tmp_tid_len, &iport_ptr, initiator_str);
+ &buf[24], tid_len, &tmp_tid_len, &iport_ptr, initiator_str);
if (!tid_found) {
pr_err("SPC-3 PR REGISTER_AND_MOVE: Unable to locate"
" initiator_str from Transport ID\n");
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 112/235] dm-integrity: dont increment hash_offset twice
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (110 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 111/235] scsi: target: Bound PR-OUT TransportID parsing to the received buffer Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 113/235] dm-verity: make error counter atomic Greg Kroah-Hartman
` (125 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Mikulas Patocka, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikulas Patocka <mpatocka@redhat.com>
[ Upstream commit edf025f083854f80032b73a1aad69a3c90db236f ]
hash_offset is already incremented in the loop "for (i = 0; i < to_copy;
i++, ts--)". Do not increment it again.
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Assisted-by: Claude:claude-opus-4.6
Fixes: 84597a44a9d8 ("dm-integrity: dm integrity: add optional discard support")
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 | 4 ----
1 file changed, 4 deletions(-)
--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -1377,10 +1377,6 @@ thorough_test:
*metadata_offset = 0;
}
- if (unlikely(!is_power_of_2(ic->tag_size))) {
- hash_offset = (hash_offset + to_copy) % ic->tag_size;
- }
-
total_size -= to_copy;
} while (unlikely(total_size));
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 113/235] dm-verity: make error counter atomic
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (111 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 112/235] dm-integrity: dont increment hash_offset twice Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 114/235] Input: ims-pcu - fix race condition in reset_device sysfs callback Greg Kroah-Hartman
` (124 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Mikulas Patocka, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikulas Patocka <mpatocka@redhat.com>
[ Upstream commit 8ec4d9c5a5cf4b61fc087f871465b1f79b393325 ]
The error counter "v->corrupted_errs" was not atomic, thus it could be
subject to race conditions. The call to
dm_audit_log_target("max-corrupted-errors") may be skipped due to the
races.
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Assisted-by: Claude:claude-opus-4.6
Fixes: 65ff5b7ddf05 ("dm verity: add error handling modes for corrupted blocks")
Cc: stable@vger.kernel.org
[ kept 5.15's braceless single-statement DMERR body instead of upstream's braced block containing the absent dm_audit_log_target() call ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/md/dm-verity-target.c | 12 +++++++-----
drivers/md/dm-verity.h | 2 +-
2 files changed, 8 insertions(+), 6 deletions(-)
--- a/drivers/md/dm-verity-target.c
+++ b/drivers/md/dm-verity-target.c
@@ -217,14 +217,16 @@ static int verity_handle_err(struct dm_v
char *envp[] = { verity_env, NULL };
const char *type_str = "";
struct mapped_device *md = dm_table_get_md(v->ti->table);
+ int ce;
/* Corruption should be visible in device status in all modes */
v->hash_failed = 1;
- if (v->corrupted_errs >= DM_VERITY_MAX_CORRUPTED_ERRS)
- goto out;
-
- v->corrupted_errs++;
+ ce = atomic_read(&v->corrupted_errs);
+ do {
+ if (ce >= DM_VERITY_MAX_CORRUPTED_ERRS)
+ goto out;
+ } while (!atomic_try_cmpxchg(&v->corrupted_errs, &ce, ce + 1));
switch (type) {
case DM_VERITY_BLOCK_TYPE_DATA:
@@ -240,7 +242,7 @@ static int verity_handle_err(struct dm_v
DMERR_LIMIT("%s: %s block %llu is corrupted", v->data_dev->name,
type_str, block);
- if (v->corrupted_errs == DM_VERITY_MAX_CORRUPTED_ERRS)
+ if (ce + 1 == DM_VERITY_MAX_CORRUPTED_ERRS)
DMERR("%s: reached maximum errors", v->data_dev->name);
snprintf(verity_env, DM_VERITY_ENV_LENGTH, "%s=%d,%llu",
--- a/drivers/md/dm-verity.h
+++ b/drivers/md/dm-verity.h
@@ -55,7 +55,7 @@ struct dm_verity {
unsigned int ahash_reqsize;/* the size of temporary space for crypto */
int hash_failed; /* set to 1 if hash of any block failed */
enum verity_mode mode; /* mode for handling verification errors */
- unsigned corrupted_errs;/* Number of errors for corrupted blocks */
+ atomic_t corrupted_errs;/* Number of errors for corrupted blocks */
struct workqueue_struct *verify_wq;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 114/235] Input: ims-pcu - fix race condition in reset_device sysfs callback
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (112 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 113/235] dm-verity: make error counter atomic Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 115/235] wifi: libertas_tf: fix use-after-free in lbtf_free_adapter() Greg Kroah-Hartman
` (123 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sashiko bot, Dmitry Torokhov,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
[ Upstream commit 411b8c4b274737c3bf08e1e025801161603cfffc ]
The ims_pcu_reset_device() sysfs callback calls ims_pcu_execute_command()
without acquiring pcu->cmd_mutex. This can lead to data races and
corruption of the shared command buffer if triggered concurrently with
other commands.
Acquire pcu->cmd_mutex before calling ims_pcu_execute_command().
Fixes: 628329d52474 ("Input: add IMS Passenger Control Unit driver")
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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/input/misc/ims-pcu.c | 2 ++
1 file changed, 2 insertions(+)
--- a/drivers/input/misc/ims-pcu.c
+++ b/drivers/input/misc/ims-pcu.c
@@ -1193,6 +1193,8 @@ static ssize_t ims_pcu_reset_device(stru
dev_info(pcu->dev, "Attempting to reset device\n");
+ guard(mutex)(&pcu->cmd_mutex);
+
error = ims_pcu_execute_command(pcu, PCU_RESET, &reset_byte, 1);
if (error) {
dev_info(pcu->dev,
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 115/235] wifi: libertas_tf: fix use-after-free in lbtf_free_adapter()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (113 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 114/235] Input: ims-pcu - fix race condition in reset_device sysfs callback Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 116/235] mmc: vub300: fix use-after-free on disconnect Greg Kroah-Hartman
` (122 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Maoyi Xie, Johannes Berg,
Sasha Levin
5.10-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] 239+ messages in thread
* [PATCH 5.10 116/235] mmc: vub300: fix use-after-free on disconnect
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (114 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 115/235] wifi: libertas_tf: fix use-after-free in lbtf_free_adapter() Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 117/235] mmc: vub300: rename probe error labels Greg Kroah-Hartman
` (121 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Binbin Zhou, Johan Hovold,
Ulf Hansson
5.10-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
@@ -2281,7 +2281,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),
@@ -2290,14 +2290,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",
@@ -2312,7 +2312,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;
@@ -2320,7 +2320,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);
@@ -2350,7 +2350,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] 239+ messages in thread
* [PATCH 5.10 117/235] mmc: vub300: rename probe error labels
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (115 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 116/235] mmc: vub300: fix use-after-free on disconnect Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 118/235] mmc: vub300: fix use-after-free on probe failure Greg Kroah-Hartman
` (120 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Johan Hovold, Ulf Hansson
5.10-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
@@ -2116,19 +2116,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;
@@ -2345,23 +2345,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] 239+ messages in thread
* [PATCH 5.10 118/235] mmc: vub300: fix use-after-free on probe failure
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (116 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 117/235] mmc: vub300: rename probe error labels Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 119/235] firmware_loader: introduce __free() cleanup hanler Greg Kroah-Hartman
` (119 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Guangshuo Li, Johan Hovold,
Ulf Hansson
5.10-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
@@ -2345,12 +2345,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] 239+ messages in thread
* [PATCH 5.10 119/235] firmware_loader: introduce __free() cleanup hanler
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (117 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 118/235] mmc: vub300: fix use-after-free on probe failure Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 120/235] Input: ims-pcu - fix firmware leak in async update Greg Kroah-Hartman
` (118 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Dmitry Torokhov, Luis Chamberalin,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
[ Upstream commit 8dde8fa0cc3edce73c050b9882d06c1a575f6402 ]
Define cleanup handler using facilities from linux/cleanup.h to simplify
error handling in code using firmware loader. This will allow writing code
like this:
int driver_update_firmware(...)
{
const struct firmware *fw_entry __free(firmware) = NULL;
int error;
...
error = request_firmware(&fw_entry, fw_name, dev);
if (error) {
dev_err(dev, "failed to request firmware %s: %d",
fw_name, error);
return error;
}
error = check_firmware_valid(fw_entry);
if (error)
return error;
guard(mutex)(&instance->lock);
error = use_firmware(instance, fw);
if (error)
return error;
return 0;
}
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Acked-by: Luis Chamberalin <mcgrof@kernel.org>
Link: https://lore.kernel.org/r/ZaeQw7VXhnirX4pQ@google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Stable-dep-of: d48795b5cd68 ("Input: ims-pcu - fix firmware leak in async update")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/firmware.h | 3 +++
1 file changed, 3 insertions(+)
--- a/include/linux/firmware.h
+++ b/include/linux/firmware.h
@@ -4,6 +4,7 @@
#include <linux/types.h>
#include <linux/compiler.h>
+#include <linux/cleanup.h>
#include <linux/gfp.h>
#define FW_ACTION_NOHOTPLUG 0
@@ -118,4 +119,6 @@ static inline int request_partial_firmwa
int firmware_request_cache(struct device *device, const char *name);
+DEFINE_FREE(firmware, struct firmware *, release_firmware(_T))
+
#endif
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 120/235] Input: ims-pcu - fix firmware leak in async update
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (118 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 119/235] firmware_loader: introduce __free() cleanup hanler Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 121/235] net: Add helper function to parse netlink msg of ip_tunnel_encap Greg Kroah-Hartman
` (117 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sashiko bot, Dmitry Torokhov,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
[ Upstream commit d48795b5cd6828d36b707e8d62fc9e5c90e004ab ]
The firmware object was not being released if validation failed.
Use __free(firmware) to ensure the firmware is always released.
Fixes: 628329d52474 ("Input: add IMS Passenger Control Unit driver")
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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/input/misc/ims-pcu.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
--- a/drivers/input/misc/ims-pcu.c
+++ b/drivers/input/misc/ims-pcu.c
@@ -964,9 +964,10 @@ out:
return retval;
}
-static void ims_pcu_process_async_firmware(const struct firmware *fw,
+static void ims_pcu_process_async_firmware(const struct firmware *_fw,
void *context)
{
+ const struct firmware *fw __free(firmware) = _fw;
struct ims_pcu *pcu = context;
int error;
@@ -987,8 +988,6 @@ static void ims_pcu_process_async_firmwa
ims_pcu_handle_firmware_update(pcu, fw);
mutex_unlock(&pcu->cmd_mutex);
- release_firmware(fw);
-
out:
complete(&pcu->async_firmware_done);
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 121/235] net: Add helper function to parse netlink msg of ip_tunnel_encap
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (119 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 120/235] Input: ims-pcu - fix firmware leak in async update Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 122/235] net: ipip: require CAP_NET_ADMIN in the device netns for changelink Greg Kroah-Hartman
` (116 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Liu Jian, David S. Miller,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Liu Jian <liujian56@huawei.com>
[ Upstream commit 537dd2d9fb9f4aa7939fb4fcf552ebe4f497bd7e ]
Add ip_tunnel_netlink_encap_parms to parse netlink msg of ip_tunnel_encap.
Reduces duplicate code, no actual functional changes.
Signed-off-by: Liu Jian <liujian56@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Stable-dep-of: 8211a2632466 ("net: ipip: require CAP_NET_ADMIN in the device netns for changelink")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/net/ip_tunnels.h | 3 +++
net/ipv4/ip_tunnel_core.c | 35 +++++++++++++++++++++++++++++++++++
net/ipv4/ipip.c | 38 ++------------------------------------
net/ipv6/ip6_tunnel.c | 37 ++-----------------------------------
net/ipv6/sit.c | 38 ++------------------------------------
5 files changed, 44 insertions(+), 107 deletions(-)
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -297,6 +297,9 @@ int ip_tunnel_newlink(struct net_device
struct ip_tunnel_parm *p, __u32 fwmark);
void ip_tunnel_setup(struct net_device *dev, unsigned int net_id);
+bool ip_tunnel_netlink_encap_parms(struct nlattr *data[],
+ struct ip_tunnel_encap *encap);
+
extern const struct header_ops ip_tunnel_header_ops;
__be16 ip_tunnel_parse_protocol(const struct sk_buff *skb);
--- a/net/ipv4/ip_tunnel_core.c
+++ b/net/ipv4/ip_tunnel_core.c
@@ -1099,3 +1099,38 @@ EXPORT_SYMBOL(ip_tunnel_parse_protocol);
const struct header_ops ip_tunnel_header_ops = { .parse_protocol = ip_tunnel_parse_protocol };
EXPORT_SYMBOL(ip_tunnel_header_ops);
+
+/* This function returns true when ENCAP attributes are present in the nl msg */
+bool ip_tunnel_netlink_encap_parms(struct nlattr *data[],
+ struct ip_tunnel_encap *encap)
+{
+ bool ret = false;
+
+ memset(encap, 0, sizeof(*encap));
+
+ if (!data)
+ return ret;
+
+ if (data[IFLA_IPTUN_ENCAP_TYPE]) {
+ ret = true;
+ encap->type = nla_get_u16(data[IFLA_IPTUN_ENCAP_TYPE]);
+ }
+
+ if (data[IFLA_IPTUN_ENCAP_FLAGS]) {
+ ret = true;
+ encap->flags = nla_get_u16(data[IFLA_IPTUN_ENCAP_FLAGS]);
+ }
+
+ if (data[IFLA_IPTUN_ENCAP_SPORT]) {
+ ret = true;
+ encap->sport = nla_get_be16(data[IFLA_IPTUN_ENCAP_SPORT]);
+ }
+
+ if (data[IFLA_IPTUN_ENCAP_DPORT]) {
+ ret = true;
+ encap->dport = nla_get_be16(data[IFLA_IPTUN_ENCAP_DPORT]);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(ip_tunnel_netlink_encap_parms);
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -446,40 +446,6 @@ static void ipip_netlink_parms(struct nl
*fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]);
}
-/* This function returns true when ENCAP attributes are present in the nl msg */
-static bool ipip_netlink_encap_parms(struct nlattr *data[],
- struct ip_tunnel_encap *ipencap)
-{
- bool ret = false;
-
- memset(ipencap, 0, sizeof(*ipencap));
-
- if (!data)
- return ret;
-
- if (data[IFLA_IPTUN_ENCAP_TYPE]) {
- ret = true;
- ipencap->type = nla_get_u16(data[IFLA_IPTUN_ENCAP_TYPE]);
- }
-
- if (data[IFLA_IPTUN_ENCAP_FLAGS]) {
- ret = true;
- ipencap->flags = nla_get_u16(data[IFLA_IPTUN_ENCAP_FLAGS]);
- }
-
- if (data[IFLA_IPTUN_ENCAP_SPORT]) {
- ret = true;
- ipencap->sport = nla_get_be16(data[IFLA_IPTUN_ENCAP_SPORT]);
- }
-
- if (data[IFLA_IPTUN_ENCAP_DPORT]) {
- ret = true;
- ipencap->dport = nla_get_be16(data[IFLA_IPTUN_ENCAP_DPORT]);
- }
-
- return ret;
-}
-
static int ipip_newlink(struct net *src_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
@@ -489,7 +455,7 @@ static int ipip_newlink(struct net *src_
struct ip_tunnel_encap ipencap;
__u32 fwmark = 0;
- if (ipip_netlink_encap_parms(data, &ipencap)) {
+ if (ip_tunnel_netlink_encap_parms(data, &ipencap)) {
int err = ip_tunnel_encap_setup(t, &ipencap);
if (err < 0)
@@ -510,7 +476,7 @@ static int ipip_changelink(struct net_de
bool collect_md;
__u32 fwmark = t->fwmark;
- if (ipip_netlink_encap_parms(data, &ipencap)) {
+ if (ip_tunnel_netlink_encap_parms(data, &ipencap)) {
int err = ip_tunnel_encap_setup(t, &ipencap);
if (err < 0)
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -2037,39 +2037,6 @@ static void ip6_tnl_netlink_parms(struct
parms->fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]);
}
-static bool ip6_tnl_netlink_encap_parms(struct nlattr *data[],
- struct ip_tunnel_encap *ipencap)
-{
- bool ret = false;
-
- memset(ipencap, 0, sizeof(*ipencap));
-
- if (!data)
- return ret;
-
- if (data[IFLA_IPTUN_ENCAP_TYPE]) {
- ret = true;
- ipencap->type = nla_get_u16(data[IFLA_IPTUN_ENCAP_TYPE]);
- }
-
- if (data[IFLA_IPTUN_ENCAP_FLAGS]) {
- ret = true;
- ipencap->flags = nla_get_u16(data[IFLA_IPTUN_ENCAP_FLAGS]);
- }
-
- if (data[IFLA_IPTUN_ENCAP_SPORT]) {
- ret = true;
- ipencap->sport = nla_get_be16(data[IFLA_IPTUN_ENCAP_SPORT]);
- }
-
- if (data[IFLA_IPTUN_ENCAP_DPORT]) {
- ret = true;
- ipencap->dport = nla_get_be16(data[IFLA_IPTUN_ENCAP_DPORT]);
- }
-
- return ret;
-}
-
static int ip6_tnl_newlink(struct net *src_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
@@ -2082,7 +2049,7 @@ static int ip6_tnl_newlink(struct net *s
nt = netdev_priv(dev);
- if (ip6_tnl_netlink_encap_parms(data, &ipencap)) {
+ if (ip_tunnel_netlink_encap_parms(data, &ipencap)) {
err = ip6_tnl_encap_setup(nt, &ipencap);
if (err < 0)
return err;
@@ -2119,7 +2086,7 @@ static int ip6_tnl_changelink(struct net
if (dev == ip6n->fb_tnl_dev)
return -EINVAL;
- if (ip6_tnl_netlink_encap_parms(data, &ipencap)) {
+ if (ip_tunnel_netlink_encap_parms(data, &ipencap)) {
int err = ip6_tnl_encap_setup(t, &ipencap);
if (err < 0)
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -1536,40 +1536,6 @@ static void ipip6_netlink_parms(struct n
*fwmark = nla_get_u32(data[IFLA_IPTUN_FWMARK]);
}
-/* This function returns true when ENCAP attributes are present in the nl msg */
-static bool ipip6_netlink_encap_parms(struct nlattr *data[],
- struct ip_tunnel_encap *ipencap)
-{
- bool ret = false;
-
- memset(ipencap, 0, sizeof(*ipencap));
-
- if (!data)
- return ret;
-
- if (data[IFLA_IPTUN_ENCAP_TYPE]) {
- ret = true;
- ipencap->type = nla_get_u16(data[IFLA_IPTUN_ENCAP_TYPE]);
- }
-
- if (data[IFLA_IPTUN_ENCAP_FLAGS]) {
- ret = true;
- ipencap->flags = nla_get_u16(data[IFLA_IPTUN_ENCAP_FLAGS]);
- }
-
- if (data[IFLA_IPTUN_ENCAP_SPORT]) {
- ret = true;
- ipencap->sport = nla_get_be16(data[IFLA_IPTUN_ENCAP_SPORT]);
- }
-
- if (data[IFLA_IPTUN_ENCAP_DPORT]) {
- ret = true;
- ipencap->dport = nla_get_be16(data[IFLA_IPTUN_ENCAP_DPORT]);
- }
-
- return ret;
-}
-
#ifdef CONFIG_IPV6_SIT_6RD
/* This function returns true when 6RD attributes are present in the nl msg */
static bool ipip6_netlink_6rd_parms(struct nlattr *data[],
@@ -1621,7 +1587,7 @@ static int ipip6_newlink(struct net *src
nt = netdev_priv(dev);
- if (ipip6_netlink_encap_parms(data, &ipencap)) {
+ if (ip_tunnel_netlink_encap_parms(data, &ipencap)) {
err = ip_tunnel_encap_setup(nt, &ipencap);
if (err < 0)
return err;
@@ -1676,7 +1642,7 @@ static int ipip6_changelink(struct net_d
if (dev == sitn->fb_tunnel_dev)
return -EINVAL;
- if (ipip6_netlink_encap_parms(data, &ipencap)) {
+ if (ip_tunnel_netlink_encap_parms(data, &ipencap)) {
err = ip_tunnel_encap_setup(t, &ipencap);
if (err < 0)
return err;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 122/235] net: ipip: require CAP_NET_ADMIN in the device netns for changelink
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (120 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 121/235] net: Add helper function to parse netlink msg of ip_tunnel_encap Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 123/235] net: ip6_tunnel: " Greg Kroah-Hartman
` (115 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Xiao Liang, Maoyi Xie,
Kuniyuki Iwashima, Jakub Kicinski, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maoyi Xie <maoyixie.tju@gmail.com>
[ Upstream commit 8211a26324667980a463c069469a818e71207e02 ]
ipip_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 ipip_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: 6c742e714d8c ("ipip: 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-3-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/ipv4/ipip.c | 3 +++
1 file changed, 3 insertions(+)
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -476,6 +476,9 @@ static int ipip_changelink(struct net_de
bool collect_md;
__u32 fwmark = t->fwmark;
+ if (!rtnl_dev_link_net_capable(dev, t->net))
+ return -EPERM;
+
if (ip_tunnel_netlink_encap_parms(data, &ipencap)) {
int err = ip_tunnel_encap_setup(t, &ipencap);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 123/235] net: ip6_tunnel: require CAP_NET_ADMIN in the device netns for changelink
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (121 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 122/235] net: ipip: require CAP_NET_ADMIN in the device netns for changelink Greg Kroah-Hartman
@ 2026-08-20 14:55 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 124/235] net/sched: taprio: avoid calling child->ops->dequeue(child) twice Greg Kroah-Hartman
` (114 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:55 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Xiao Liang, Maoyi Xie,
Kuniyuki Iwashima, Jakub Kicinski, Sasha Levin
5.10-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
@@ -2083,6 +2083,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] 239+ messages in thread
* [PATCH 5.10 124/235] net/sched: taprio: avoid calling child->ops->dequeue(child) twice
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (122 preceding siblings ...)
2026-08-20 14:55 ` [PATCH 5.10 123/235] net: ip6_tunnel: " Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 125/235] net/sched: sch_taprio: Replace direct dequeue call with peek and qdisc_dequeue_peeked Greg Kroah-Hartman
` (113 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Vladimir Oltean, Kurt Kanzenbach,
David S. Miller, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vladimir Oltean <vladimir.oltean@nxp.com>
[ Upstream commit 4c22942734f0814d3c928c25a80f48df0a6ce45e ]
Simplify taprio_dequeue_from_txq() by noticing that we can goto one call
earlier than the previous skb_found label. This is possible because
we've unified the treatment of the child->ops->dequeue(child) return
call, we always try other TXQs now, instead of abandoning the root
dequeue completely if we failed in the peek() case.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Kurt Kanzenbach <kurt@linutronix.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
Stable-dep-of: e056e1dfcddc ("net/sched: sch_taprio: Replace direct dequeue call with peek and qdisc_dequeue_peeked")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/sched/sch_taprio.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -559,12 +559,8 @@ static struct sk_buff *taprio_dequeue_fr
if (unlikely(!child))
return NULL;
- if (TXTIME_ASSIST_IS_ENABLED(q->flags)) {
- skb = child->ops->dequeue(child);
- if (!skb)
- return NULL;
- goto skb_found;
- }
+ if (TXTIME_ASSIST_IS_ENABLED(q->flags))
+ goto skip_peek_checks;
skb = child->ops->peek(child);
if (!skb)
@@ -591,11 +587,11 @@ static struct sk_buff *taprio_dequeue_fr
atomic_sub_return(len, &entry->budget) < 0)
return NULL;
+skip_peek_checks:
skb = child->ops->dequeue(child);
if (unlikely(!skb))
return NULL;
-skb_found:
qdisc_bstats_update(sch, skb);
qdisc_qstats_backlog_dec(sch, skb);
sch->q.qlen--;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 125/235] net/sched: sch_taprio: Replace direct dequeue call with peek and qdisc_dequeue_peeked
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (123 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 124/235] net/sched: taprio: avoid calling child->ops->dequeue(child) twice Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 126/235] gpio: tegra: do not call pinctrl for GPIO direction Greg Kroah-Hartman
` (112 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Vladimir Oltean, Bryam Vargas,
Victor Nogueira, Jamal Hadi Salim, Jakub Kicinski, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <hexlabsecurity@proton.me>
[ Upstream commit e056e1dfcddca877dd46d704e8ec9860cfc9ec44 ]
When taprio's software path peeks a non-work-conserving child qdisc, the
child stashes the peeked skb in its gso_skb; taprio_dequeue_from_txq()
then takes the packet with a direct child ->dequeue() call, which ignores
that stash, orphans the peeked skb and desyncs the child's qlen/backlog.
With a qfq child this re-enters the child on an emptied list and
dereferences NULL, panicking the kernel from softirq on ordinary egress.
Take the packet through qdisc_dequeue_peeked(), as sch_red and sch_sfb
now do. The helper returns the child's stashed skb first and is a no-op
when there is none, so a work-conserving child is unaffected and the
gated path now consumes the skb whose length was charged to the budget.
Fixes: 5a781ccbd19e ("tc: Add support for configuring the taprio scheduler")
Cc: stable@vger.kernel.org
Cc: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me>
Reviewed-by: Victor Nogueira <victor@mojatatu.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Link: https://patch.msgid.link/20260625-b4-disp-31bcb279-v1-1-85c40b83c529@proton.me
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/sched/sch_taprio.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/net/sched/sch_taprio.c
+++ b/net/sched/sch_taprio.c
@@ -588,7 +588,7 @@ static struct sk_buff *taprio_dequeue_fr
return NULL;
skip_peek_checks:
- skb = child->ops->dequeue(child);
+ skb = qdisc_dequeue_peeked(child);
if (unlikely(!skb))
return NULL;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 126/235] gpio: tegra: do not call pinctrl for GPIO direction
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (124 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 125/235] net/sched: sch_taprio: Replace direct dequeue call with peek and qdisc_dequeue_peeked Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 127/235] bootconfig: do not put quotes on cmdline items unless necessary Greg Kroah-Hartman
` (111 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Runyu Xiao, Bartosz Golaszewski,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Runyu Xiao <runyu.xiao@seu.edu.cn>
[ Upstream commit d3e91a95b2b0fc6336dbf3ec90d831a1654d2720 ]
tegra_gpio_direction_input() and tegra_gpio_direction_output() already
program the GPIO controller direction registers directly. The additional
pinctrl_gpio_direction_input/output() calls do not add a Tegra pinctrl
operation, because the Tegra pinmux ops provide GPIO request/free
handling but no gpio_set_direction hook.
The extra call still enters the pinctrl core and takes pctldev->mutex.
Shared GPIO users can call the direction path while holding their
per-line spinlock, so this otherwise redundant pinctrl direction call can
sleep in an atomic context.
This was found by our static analysis tool and then confirmed by manual
review of tegra_gpio_probe(), the Tegra GPIO direction callbacks and the
Tegra pinctrl ops. The reviewed path has a default non-sleeping
struct gpio_chip while the direction callback still enters the pinctrl
mutex path.
A directed runtime validation kept the same non-sleeping chip registration
and drove:
gpio_shared_proxy_direction_output()
gpiod_direction_output_raw_commit()
tegra_gpio_direction_output()
pinctrl_gpio_direction_output()
Lockdep reported a sleep-in-atomic warning with the shared GPIO spinlock
held and pinctrl_get_device_gpio_range() plus tegra_gpio_direction_output()
on the stack.
Do not mark the whole chip as can_sleep to paper over this: can_sleep
describes whether get()/set() may sleep, and Tegra value access is MMIO.
Remove the redundant pinctrl direction calls and keep pinctrl involvement
in the existing request/free path.
Fixes: 11da90541283 ("gpio: tegra: Fix offset of pinctrl calls")
Cc: stable@vger.kernel.org
Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn>
Link: https://patch.msgid.link/20260619152439.1239561-1-runyu.xiao@seu.edu.cn
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpio/gpio-tegra.c | 18 ++----------------
1 file changed, 2 insertions(+), 16 deletions(-)
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -168,18 +168,11 @@ static int tegra_gpio_direction_input(st
unsigned int offset)
{
struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
- int ret;
tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 0);
tegra_gpio_enable(tgi, offset);
- ret = pinctrl_gpio_direction_input(chip->base + offset);
- if (ret < 0)
- dev_err(tgi->dev,
- "Failed to set pinctrl input direction of GPIO %d: %d",
- chip->base + offset, ret);
-
- return ret;
+ return 0;
}
static int tegra_gpio_direction_output(struct gpio_chip *chip,
@@ -187,19 +180,12 @@ static int tegra_gpio_direction_output(s
int value)
{
struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
- int ret;
tegra_gpio_set(chip, offset, value);
tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 1);
tegra_gpio_enable(tgi, offset);
- ret = pinctrl_gpio_direction_output(chip->base + offset);
- if (ret < 0)
- dev_err(tgi->dev,
- "Failed to set pinctrl output direction of GPIO %d: %d",
- chip->base + offset, ret);
-
- return ret;
+ return 0;
}
static int tegra_gpio_get_direction(struct gpio_chip *chip,
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 127/235] bootconfig: do not put quotes on cmdline items unless necessary
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (125 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 126/235] gpio: tegra: do not call pinctrl for GPIO direction Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 128/235] bootconfig: move xbc_snprint_cmdline() to lib/bootconfig.c Greg Kroah-Hartman
` (110 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Rasmus Villemoes, Masami Hiramatsu,
Andrew Morton, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rasmus Villemoes <linux@rasmusvillemoes.dk>
[ Upstream commit 212f863fa8811c780abacc1d0404c573fdc0a2de ]
When trying to migrate to using bootconfig to embed the kernel's and
PID1's command line with the kernel image itself, and so allowing changing
that without modifying the bootloader, I noticed that /proc/cmdline
changed from e.g.
console=ttymxc0,115200n8 cma=128M quiet -- --log-level=notice
to
console="ttymxc0,115200n8" cma="128M" quiet -- --log-level="notice"
The kernel parameters are parsed just fine, and the quotes are indeed
stripped from the actual argv[] given to PID1. However, the quoting
doesn't really serve any purpose and looks excessive, and might confuse
some (naive) userspace tool trying to parse /proc/cmdline. So do not
quote the value unless it contains whitespace.
Link: https://lkml.kernel.org/r/20240320101952.62135-1-linux@rasmusvillemoes.dk
Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.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>
---
init/main.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
--- a/init/main.c
+++ b/init/main.c
@@ -323,7 +323,7 @@ static int __init xbc_snprint_cmdline(ch
{
struct xbc_node *knode, *vnode;
char *end = buf + size;
- const char *val;
+ const char *val, *q;
int ret;
xbc_node_for_each_key_value(root, knode, val) {
@@ -341,8 +341,14 @@ static int __init xbc_snprint_cmdline(ch
continue;
}
xbc_array_for_each_value(vnode, val) {
- ret = snprintf(buf, rest(buf, end), "%s=\"%s\" ",
- xbc_namebuf, 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;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 128/235] bootconfig: move xbc_snprint_cmdline() to lib/bootconfig.c
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (126 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 127/235] bootconfig: do not put quotes on cmdline items unless necessary Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 129/235] bootconfig: fix NULL-pointer arithmetic in xbc_snprint_cmdline() Greg Kroah-Hartman
` (109 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Breno Leitao,
Masami Hiramatsu (Google), Sasha Levin
5.10-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
@@ -202,6 +202,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
@@ -314,51 +314,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
@@ -329,6 +329,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, u32 flag)
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 129/235] bootconfig: fix NULL-pointer arithmetic in xbc_snprint_cmdline()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (127 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 128/235] bootconfig: move xbc_snprint_cmdline() to lib/bootconfig.c Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 130/235] espintcp: use sk_msg_free_partial to fix partial send Greg Kroah-Hartman
` (108 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Breno Leitao,
Masami Hiramatsu (Google), Sasha Levin
5.10-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
@@ -348,10 +348,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);
@@ -360,10 +368,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) {
@@ -373,15 +382,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] 239+ messages in thread
* [PATCH 5.10 130/235] espintcp: use sk_msg_free_partial to fix partial send
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (128 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 129/235] bootconfig: fix NULL-pointer arithmetic in xbc_snprint_cmdline() Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 131/235] net: ipa: fix SMEM state handle leaks in SMP2P init Greg Kroah-Hartman
` (107 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Aaron Esau, Yiming Qian,
Sabrina Dubroca, Steffen Klassert, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sabrina Dubroca <sd@queasysnail.net>
[ Upstream commit 007800408002d871f5699bdb944f985896730b8f ]
sk_msg_free_partial() ensures consistency of the skmsg at every
iteration, without having to manually handle uncharges and offsets.
This simplifies the code, and fixes some bugs in skmsg accounting when
we don't send the full contents.
Cc: stable@vger.kernel.org
Fixes: e27cca96cd68 ("xfrm: add espintcp (RFC 8229)")
Reported-by: Aaron Esau <aaron1esau@gmail.com>
Reported-by: Yiming Qian <yimingqian591@gmail.com>
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
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/espintcp.c | 32 ++++++--------------------------
1 file changed, 6 insertions(+), 26 deletions(-)
--- a/net/xfrm/espintcp.c
+++ b/net/xfrm/espintcp.c
@@ -208,41 +208,21 @@ static int espintcp_sendskmsg_locked(str
{
struct sk_msg *skmsg = &emsg->skmsg;
struct scatterlist *sg;
- int done = 0;
int ret;
flags |= MSG_SENDPAGE_NOTLAST;
- sg = &skmsg->sg.data[skmsg->sg.start];
do {
- size_t size = sg->length - emsg->offset;
- int offset = sg->offset + emsg->offset;
- struct page *p;
-
- emsg->offset = 0;
-
+ sg = &skmsg->sg.data[skmsg->sg.start];
if (sg_is_last(sg))
flags &= ~MSG_SENDPAGE_NOTLAST;
- p = sg_page(sg);
-retry:
- ret = do_tcp_sendpages(sk, p, offset, size, flags);
- if (ret < 0) {
- emsg->offset = offset - sg->offset;
- skmsg->sg.start += done;
+ ret = do_tcp_sendpages(sk, sg_page(sg), sg->offset,
+ sg->length, flags);
+ if (ret < 0)
return ret;
- }
-
- if (ret != size) {
- offset += ret;
- size -= ret;
- goto retry;
- }
- done++;
- put_page(p);
- sk_mem_uncharge(sk, sg->length);
- sg = sg_next(sg);
- } while (sg);
+ sk_msg_free_partial(sk, skmsg, ret);
+ } while (skmsg->sg.size);
memset(emsg, 0, sizeof(*emsg));
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 131/235] net: ipa: fix SMEM state handle leaks in SMP2P init
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (129 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 130/235] espintcp: use sk_msg_free_partial to fix partial send Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 132/235] octeontx2-pf: fix SQB pointer leak on init failure Greg Kroah-Hartman
` (106 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Haoxiang Li, Larysa Zaremba,
Alex Elder, Jakub Kicinski, Sasha Levin
5.10-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
@@ -222,19 +222,27 @@ int ipa_smp2p_init(struct ipa *ipa, bool
&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;
@@ -279,6 +287,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;
}
@@ -295,6 +307,8 @@ void ipa_smp2p_exit(struct ipa *ipa)
ipa_smp2p_clock_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] 239+ messages in thread
* [PATCH 5.10 132/235] octeontx2-pf: fix SQB pointer leak on init failure
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (130 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 131/235] net: ipa: fix SMEM state handle leaks in SMP2P init Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 133/235] fs/resctrl: Fix double-add of pseudo-locked regions RMID to free list Greg Kroah-Hartman
` (105 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Ratheesh Kannoth, Dawei Feng,
Paolo Abeni, Sasha Levin
5.10-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 | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -1357,14 +1357,13 @@ 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:
if (otx2_txschq_stop(pf))
dev_err(pf->dev, "%s failed to stop TX schedulers\n", __func__);
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] 239+ messages in thread
* [PATCH 5.10 133/235] fs/resctrl: Fix double-add of pseudo-locked regions RMID to free list
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (131 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 132/235] octeontx2-pf: fix SQB pointer leak on init failure Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 134/235] usb: gadget: bdc: fix checkpatch.pl spacing error Greg Kroah-Hartman
` (104 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Reinette Chatre,
Borislav Petkov (AMD), stable, Sasha Levin
5.10-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
@@ -2376,10 +2376,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
@@ -2388,7 +2384,13 @@ static void rmdir_all_sub(void)
cpumask_or(&rdtgroup_default.cpu_mask,
&rdtgroup_default.cpu_mask, &rdtgrp->cpu_mask);
- free_rmid(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->mon.rmid);
+ }
kernfs_remove(rdtgrp->kn);
list_del(&rdtgrp->rdtgroup_list);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 134/235] usb: gadget: bdc: fix checkpatch.pl spacing error
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (132 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 133/235] fs/resctrl: Fix double-add of pseudo-locked regions RMID to free list Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 135/235] usb: gadget: udc: bdc: free IRQ and drain func_wake_notify before teardown Greg Kroah-Hartman
` (103 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Florian Fainelli, Felipe Balbi,
Chunfeng Yun, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chunfeng Yun <chunfeng.yun@mediatek.com>
[ Upstream commit 14a46f82d74e9bd8ce03cdbfcdb9f8408c1fc205 ]
fix checkpatch.pl error:
ERROR:SPACING: space prohibited before that ','
Cc: Florian Fainelli <f.fainelli@gmail.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Acked-by: Felipe Balbi <balbi@kernel.org>
Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
Link: https://lore.kernel.org/r/1610505748-30616-10-git-send-email-chunfeng.yun@mediatek.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Stable-dep-of: 0583f2fbf8f8 ("usb: gadget: udc: bdc: free IRQ and drain func_wake_notify before teardown")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/gadget/udc/bdc/bdc_udc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/usb/gadget/udc/bdc/bdc_udc.c
+++ b/drivers/usb/gadget/udc/bdc/bdc_udc.c
@@ -531,7 +531,7 @@ 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);
+ IRQF_SHARED, BRCM_BDC_NAME, bdc);
if (ret) {
dev_err(bdc->dev,
"failed to request irq #%d %d\n",
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 135/235] usb: gadget: udc: bdc: free IRQ and drain func_wake_notify before teardown
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (133 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 134/235] usb: gadget: bdc: fix checkpatch.pl spacing error Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 136/235] USB: serial: keyspan_pda: refactor write-room handling Greg Kroah-Hartman
` (102 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, stable, Fan Wu, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fan Wu <fanwu01@zju.edu.cn>
[ Upstream commit 0583f2fbf8f86ae3a0ce054f96783dd83e65d9bb ]
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: Sasha Levin <sashal@kernel.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 int 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] 239+ messages in thread
* [PATCH 5.10 136/235] USB: serial: keyspan_pda: refactor write-room handling
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (134 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 135/235] usb: gadget: udc: bdc: free IRQ and drain func_wake_notify before teardown Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 137/235] USB: serial: keyspan_pda: fix write implementation Greg Kroah-Hartman
` (101 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sebastian Andrzej Siewior,
Johan Hovold, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <johan@kernel.org>
[ Upstream commit 79fe6826a5ebee2724d432a736ec04d8dca143ba ]
Add helper to retrieve the available device transfer-buffer space.
Acked-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
Stable-dep-of: 42a97c0480f9 ("USB: serial: keyspan_pda: fix data loss on receive throttling")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/serial/keyspan_pda.c | 113 +++++++++++++++++----------------------
1 file changed, 50 insertions(+), 63 deletions(-)
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -98,6 +98,42 @@ static const struct usb_device_id id_tab
};
#endif
+static int keyspan_pda_get_write_room(struct keyspan_pda_private *priv)
+{
+ struct usb_serial_port *port = priv->port;
+ struct usb_serial *serial = priv->serial;
+ u8 *room;
+ int rc;
+
+ room = kmalloc(1, GFP_KERNEL);
+ if (!room)
+ return -ENOMEM;
+
+ rc = usb_control_msg(serial->dev,
+ usb_rcvctrlpipe(serial->dev, 0),
+ 6, /* write_room */
+ USB_TYPE_VENDOR | USB_RECIP_INTERFACE
+ | USB_DIR_IN,
+ 0, /* value: 0 means "remaining room" */
+ 0, /* index */
+ room,
+ 1,
+ 2000);
+ if (rc != 1) {
+ if (rc >= 0)
+ rc = -EIO;
+ dev_dbg(&port->dev, "roomquery failed: %d\n", rc);
+ goto out_free;
+ }
+
+ dev_dbg(&port->dev, "roomquery says %d\n", *room);
+ rc = *room;
+out_free:
+ kfree(room);
+
+ return rc;
+}
+
static void keyspan_pda_request_unthrottle(struct work_struct *work)
{
struct keyspan_pda_private *priv =
@@ -436,7 +472,6 @@ static int keyspan_pda_tiocmset(struct t
static int keyspan_pda_write(struct tty_struct *tty,
struct usb_serial_port *port, const unsigned char *buf, int count)
{
- struct usb_serial *serial = port->serial;
int request_unthrottle = 0;
int rc = 0;
struct keyspan_pda_private *priv;
@@ -479,38 +514,11 @@ static int keyspan_pda_write(struct tty_
device how much room it really has. This is done only on
scheduler time, since usb_control_msg() sleeps. */
if (count > priv->tx_room && !in_interrupt()) {
- u8 *room;
-
- room = kmalloc(1, GFP_KERNEL);
- if (!room) {
- rc = -ENOMEM;
+ rc = keyspan_pda_get_write_room(priv);
+ if (rc < 0)
goto exit;
- }
- rc = usb_control_msg(serial->dev,
- usb_rcvctrlpipe(serial->dev, 0),
- 6, /* write_room */
- USB_TYPE_VENDOR | USB_RECIP_INTERFACE
- | USB_DIR_IN,
- 0, /* value: 0 means "remaining room" */
- 0, /* index */
- room,
- 1,
- 2000);
- if (rc > 0) {
- dev_dbg(&port->dev, "roomquery says %d\n", *room);
- priv->tx_room = *room;
- }
- kfree(room);
- if (rc < 0) {
- dev_dbg(&port->dev, "roomquery failed\n");
- goto exit;
- }
- if (rc == 0) {
- dev_dbg(&port->dev, "roomquery returned 0 bytes\n");
- rc = -EIO; /* device didn't return any data */
- goto exit;
- }
+ priv->tx_room = rc;
}
if (count >= priv->tx_room) {
@@ -612,48 +620,27 @@ static void keyspan_pda_dtr_rts(struct u
static int keyspan_pda_open(struct tty_struct *tty,
struct usb_serial_port *port)
{
- struct usb_serial *serial = port->serial;
- u8 *room;
- int rc = 0;
- struct keyspan_pda_private *priv;
+ struct keyspan_pda_private *priv = usb_get_serial_port_data(port);
+ int rc;
/* find out how much room is in the Tx ring */
- room = kmalloc(1, GFP_KERNEL);
- if (!room)
- return -ENOMEM;
+ rc = keyspan_pda_get_write_room(priv);
+ if (rc < 0)
+ return rc;
- rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
- 6, /* write_room */
- USB_TYPE_VENDOR | USB_RECIP_INTERFACE
- | USB_DIR_IN,
- 0, /* value */
- 0, /* index */
- room,
- 1,
- 2000);
- if (rc < 0) {
- dev_dbg(&port->dev, "%s - roomquery failed\n", __func__);
- goto error;
- }
- if (rc == 0) {
- dev_dbg(&port->dev, "%s - roomquery returned 0 bytes\n", __func__);
- rc = -EIO;
- goto error;
- }
- priv = usb_get_serial_port_data(port);
- priv->tx_room = *room;
- priv->tx_throttled = *room ? 0 : 1;
+ priv->tx_room = rc;
+ priv->tx_throttled = rc ? 0 : 1;
/*Start reading from the device*/
rc = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (rc) {
dev_dbg(&port->dev, "%s - usb_submit_urb(read int) failed\n", __func__);
- goto error;
+ return rc;
}
-error:
- kfree(room);
- return rc;
+
+ return 0;
}
+
static void keyspan_pda_close(struct usb_serial_port *port)
{
struct keyspan_pda_private *priv = usb_get_serial_port_data(port);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 137/235] USB: serial: keyspan_pda: fix write implementation
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (135 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 136/235] USB: serial: keyspan_pda: refactor write-room handling Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 138/235] USB: serial: keyspan_pda: add write-fifo support Greg Kroah-Hartman
` (100 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sebastian Andrzej Siewior,
Johan Hovold, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <johan@kernel.org>
[ Upstream commit 7184933b52a6b3e64171819b77f0bab018696cb2 ]
Fix stalled writes by checking the available buffer space after
requesting an unthrottle notification in case the device buffer is
already empty so that no notification is ever sent (e.g. when doing
single character writes).
This also means we can drop the room query from write() which was
conditioned on in_interrupt() and prevented writing using this driver
from atomic contexts (e.g. PPP).
Acked-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
Stable-dep-of: 42a97c0480f9 ("USB: serial: keyspan_pda: fix data loss on receive throttling")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/serial/keyspan_pda.c | 111 ++++++++++++++++++---------------------
1 file changed, 52 insertions(+), 59 deletions(-)
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -44,7 +44,6 @@
struct keyspan_pda_private {
int tx_room;
- int tx_throttled;
struct work_struct unthrottle_work;
struct usb_serial *serial;
struct usb_serial_port *port;
@@ -138,9 +137,13 @@ static void keyspan_pda_request_unthrott
{
struct keyspan_pda_private *priv =
container_of(work, struct keyspan_pda_private, unthrottle_work);
+ struct usb_serial_port *port = priv->port;
struct usb_serial *serial = priv->serial;
+ unsigned long flags;
int result;
+ dev_dbg(&port->dev, "%s\n", __func__);
+
/* ask the device to tell us when the tx buffer becomes
sufficiently empty */
result = usb_control_msg(serial->dev,
@@ -156,8 +159,19 @@ static void keyspan_pda_request_unthrott
if (result < 0)
dev_dbg(&serial->dev->dev, "%s - error %d from usb_control_msg\n",
__func__, result);
-}
+ /*
+ * Need to check available space after requesting notification in case
+ * buffer is already empty so that no notification is sent.
+ */
+ result = keyspan_pda_get_write_room(priv);
+ if (result > KEYSPAN_TX_THRESHOLD) {
+ spin_lock_irqsave(&port->lock, flags);
+ priv->tx_room = max(priv->tx_room, result);
+ spin_unlock_irqrestore(&port->lock, flags);
+ usb_serial_port_softint(port);
+ }
+}
static void keyspan_pda_rx_interrupt(struct urb *urb)
{
@@ -212,7 +226,6 @@ static void keyspan_pda_rx_interrupt(str
break;
case 2: /* tx unthrottle interrupt */
spin_lock_irqsave(&port->lock, flags);
- priv->tx_throttled = 0;
priv->tx_room = max(priv->tx_room, KEYSPAN_TX_THRESHOLD);
spin_unlock_irqrestore(&port->lock, flags);
/* queue up a wakeup at scheduler time */
@@ -472,35 +485,42 @@ static int keyspan_pda_tiocmset(struct t
static int keyspan_pda_write(struct tty_struct *tty,
struct usb_serial_port *port, const unsigned char *buf, int count)
{
- int request_unthrottle = 0;
- int rc = 0;
struct keyspan_pda_private *priv;
unsigned long flags;
+ int room;
+ int rc;
priv = usb_get_serial_port_data(port);
- /* guess how much room is left in the device's ring buffer, and if we
- want to send more than that, check first, updating our notion of
- what is left. If our write will result in no room left, ask the
- device to give us an interrupt when the room available rises above
- a threshold, and hold off all writers (eventually, those using
- select() or poll() too) until we receive that unthrottle interrupt.
- Block if we can't write anything at all, otherwise write as much as
- we can. */
+ /*
+ * Guess how much room is left in the device's ring buffer. If our
+ * write will result in no room left, ask the device to give us an
+ * interrupt when the room available rises above a threshold but also
+ * query how much room is currently available (in case our guess was
+ * too conservative and the buffer is already empty when the
+ * unthrottle work is scheduled).
+ */
if (count == 0) {
dev_dbg(&port->dev, "write request of 0 bytes\n");
return 0;
}
+ if (count > port->bulk_out_size)
+ count = port->bulk_out_size;
+
/* we might block because of:
the TX urb is in-flight (wait until it completes)
the device is full (wait until it says there is room)
*/
spin_lock_irqsave(&port->lock, flags);
- if (!test_bit(0, &port->write_urbs_free) || priv->tx_throttled) {
+ room = priv->tx_room;
+ if (!test_bit(0, &port->write_urbs_free) || room == 0) {
spin_unlock_irqrestore(&port->lock, flags);
return 0;
}
clear_bit(0, &port->write_urbs_free);
+ if (count > room)
+ count = room;
+ priv->tx_room -= count;
spin_unlock_irqrestore(&port->lock, flags);
/* At this point the URB is in our control, nobody else can submit it
@@ -508,58 +528,30 @@ static int keyspan_pda_write(struct tty_
finished). Also, the tx process is not throttled. So we are
ready to write. */
- count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
+ dev_dbg(&port->dev, "%s - count = %d, txroom = %d\n", __func__, count, room);
- /* Check if we might overrun the Tx buffer. If so, ask the
- device how much room it really has. This is done only on
- scheduler time, since usb_control_msg() sleeps. */
- if (count > priv->tx_room && !in_interrupt()) {
- rc = keyspan_pda_get_write_room(priv);
- if (rc < 0)
- goto exit;
+ memcpy(port->write_urb->transfer_buffer, buf, count);
+ port->write_urb->transfer_buffer_length = count;
- priv->tx_room = rc;
- }
+ rc = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ if (rc) {
+ dev_dbg(&port->dev, "usb_submit_urb(write bulk) failed\n");
- if (count >= priv->tx_room) {
- /* we're about to completely fill the Tx buffer, so
- we'll be throttled afterwards. */
- count = priv->tx_room;
- request_unthrottle = 1;
- }
+ spin_lock_irqsave(&port->lock, flags);
+ priv->tx_room = max(priv->tx_room, room + count);
+ spin_unlock_irqrestore(&port->lock, flags);
- if (count) {
- /* now transfer data */
- memcpy(port->write_urb->transfer_buffer, buf, count);
- /* send the data out the bulk port */
- port->write_urb->transfer_buffer_length = count;
-
- priv->tx_room -= count;
-
- rc = usb_submit_urb(port->write_urb, GFP_ATOMIC);
- if (rc) {
- dev_dbg(&port->dev, "usb_submit_urb(write bulk) failed\n");
- goto exit;
- }
- } else {
- /* There wasn't any room left, so we are throttled until
- the buffer empties a bit */
- request_unthrottle = 1;
+ set_bit(0, &port->write_urbs_free);
+
+ return rc;
}
- if (request_unthrottle) {
- priv->tx_throttled = 1; /* block writers */
+ if (count == room)
schedule_work(&priv->unthrottle_work);
- }
- rc = count;
-exit:
- if (rc <= 0)
- set_bit(0, &port->write_urbs_free);
- return rc;
+ return count;
}
-
static void keyspan_pda_write_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
@@ -579,7 +571,7 @@ static int keyspan_pda_write_room(struct
int room = 0;
spin_lock_irqsave(&port->lock, flags);
- if (test_bit(0, &port->write_urbs_free) && !priv->tx_throttled)
+ if (test_bit(0, &port->write_urbs_free))
room = priv->tx_room;
spin_unlock_irqrestore(&port->lock, flags);
@@ -599,7 +591,7 @@ static int keyspan_pda_chars_in_buffer(s
n_tty.c:normal_poll() ) that we're not writeable. */
spin_lock_irqsave(&port->lock, flags);
- if (!test_bit(0, &port->write_urbs_free) || priv->tx_throttled)
+ if (!test_bit(0, &port->write_urbs_free) || priv->tx_room == 0)
ret = 256;
spin_unlock_irqrestore(&port->lock, flags);
return ret;
@@ -628,8 +620,9 @@ static int keyspan_pda_open(struct tty_s
if (rc < 0)
return rc;
+ spin_lock_irq(&port->lock);
priv->tx_room = rc;
- priv->tx_throttled = rc ? 0 : 1;
+ spin_unlock_irq(&port->lock);
/*Start reading from the device*/
rc = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 138/235] USB: serial: keyspan_pda: add write-fifo support
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (136 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 137/235] USB: serial: keyspan_pda: fix write implementation Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 139/235] USB: serial: keyspan_pda: clean up comments and whitespace Greg Kroah-Hartman
` (99 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sebastian Andrzej Siewior,
Johan Hovold, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <johan@kernel.org>
[ Upstream commit 034e38e8f68767fb5438ae3e608ee82919674177 ]
Use the port write fifo and generic chars_and_buffer and write_room
implementations when writing. This not only allows for more efficient
transfers, but more importantly fixes the remaining issues related to
the conservative write_room() implementation which could prevent the
line discipline from making forward progress (e.g. waiting for n > 1
bytes of space to become available).
Note that this also allows using the driver for the system console
without dropping data when the write URB is busy (including when adding
carriage return on line feed).
Acked-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
Stable-dep-of: 42a97c0480f9 ("USB: serial: keyspan_pda: fix data loss on receive throttling")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/serial/keyspan_pda.c | 134 ++++++++++++++++++---------------------
1 file changed, 65 insertions(+), 69 deletions(-)
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -5,6 +5,7 @@
* Copyright (C) 1999 - 2001 Greg Kroah-Hartman <greg@kroah.com>
* Copyright (C) 1999, 2000 Brian Warner <warner@lothar.com>
* Copyright (C) 2000 Al Borchers <borchers@steinerpoint.com>
+ * Copyright (C) 2020 Johan Hovold <johan@kernel.org>
*
* See Documentation/usb/usb-serial.rst for more information on using this
* driver
@@ -37,7 +38,7 @@
#undef XIRCOM
#endif
-#define DRIVER_AUTHOR "Brian Warner <warner@lothar.com>"
+#define DRIVER_AUTHOR "Brian Warner <warner@lothar.com>, Johan Hovold <johan@kernel.org>"
#define DRIVER_DESC "USB Keyspan PDA Converter driver"
#define KEYSPAN_TX_THRESHOLD 16
@@ -49,6 +50,7 @@ struct keyspan_pda_private {
struct usb_serial_port *port;
};
+static int keyspan_pda_write_start(struct usb_serial_port *port);
#define KEYSPAN_VENDOR_ID 0x06cd
#define KEYSPAN_PDA_FAKE_ID 0x0103
@@ -228,6 +230,9 @@ static void keyspan_pda_rx_interrupt(str
spin_lock_irqsave(&port->lock, flags);
priv->tx_room = max(priv->tx_room, KEYSPAN_TX_THRESHOLD);
spin_unlock_irqrestore(&port->lock, flags);
+
+ keyspan_pda_write_start(port);
+
/* queue up a wakeup at scheduler time */
usb_serial_port_softint(port);
break;
@@ -247,31 +252,30 @@ exit:
__func__, retval);
}
-
static void keyspan_pda_rx_throttle(struct tty_struct *tty)
{
- /* stop receiving characters. We just turn off the URB request, and
- let chars pile up in the device. If we're doing hardware
- flowcontrol, the device will signal the other end when its buffer
- fills up. If we're doing XON/XOFF, this would be a good time to
- send an XOFF, although it might make sense to foist that off
- upon the device too. */
struct usb_serial_port *port = tty->driver_data;
+ /*
+ * Stop receiving characters. We just turn off the URB request, and
+ * let chars pile up in the device. If we're doing hardware
+ * flowcontrol, the device will signal the other end when its buffer
+ * fills up. If we're doing XON/XOFF, this would be a good time to
+ * send an XOFF, although it might make sense to foist that off upon
+ * the device too.
+ */
usb_kill_urb(port->interrupt_in_urb);
}
-
static void keyspan_pda_rx_unthrottle(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- /* just restart the receive interrupt URB */
+ /* 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");
}
-
static speed_t keyspan_pda_setbaud(struct usb_serial *serial, speed_t baud)
{
int rc;
@@ -482,15 +486,15 @@ static int keyspan_pda_tiocmset(struct t
return rc;
}
-static int keyspan_pda_write(struct tty_struct *tty,
- struct usb_serial_port *port, const unsigned char *buf, int count)
+static int keyspan_pda_write_start(struct usb_serial_port *port)
{
- struct keyspan_pda_private *priv;
+ struct keyspan_pda_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
+ struct urb *urb;
+ int count;
int room;
int rc;
- priv = usb_get_serial_port_data(port);
/*
* Guess how much room is left in the device's ring buffer. If our
* write will result in no room left, ask the device to give us an
@@ -499,105 +503,92 @@ static int keyspan_pda_write(struct tty_
* too conservative and the buffer is already empty when the
* unthrottle work is scheduled).
*/
- if (count == 0) {
- dev_dbg(&port->dev, "write request of 0 bytes\n");
- return 0;
- }
-
- if (count > port->bulk_out_size)
- count = port->bulk_out_size;
/* we might block because of:
the TX urb is in-flight (wait until it completes)
the device is full (wait until it says there is room)
*/
spin_lock_irqsave(&port->lock, flags);
+
room = priv->tx_room;
- if (!test_bit(0, &port->write_urbs_free) || room == 0) {
+ count = kfifo_len(&port->write_fifo);
+
+ if (!test_bit(0, &port->write_urbs_free) || count == 0 || room == 0) {
spin_unlock_irqrestore(&port->lock, flags);
return 0;
}
- clear_bit(0, &port->write_urbs_free);
+ __clear_bit(0, &port->write_urbs_free);
+
if (count > room)
count = room;
+ if (count > port->bulk_out_size)
+ count = port->bulk_out_size;
+
+ urb = port->write_urb;
+ count = kfifo_out(&port->write_fifo, urb->transfer_buffer, count);
+ urb->transfer_buffer_length = count;
+
+ port->tx_bytes += count;
priv->tx_room -= count;
- spin_unlock_irqrestore(&port->lock, flags);
- /* At this point the URB is in our control, nobody else can submit it
- again (the only sudden transition was the one from EINPROGRESS to
- finished). Also, the tx process is not throttled. So we are
- ready to write. */
+ spin_unlock_irqrestore(&port->lock, flags);
dev_dbg(&port->dev, "%s - count = %d, txroom = %d\n", __func__, count, room);
- memcpy(port->write_urb->transfer_buffer, buf, count);
- port->write_urb->transfer_buffer_length = count;
-
- rc = usb_submit_urb(port->write_urb, GFP_ATOMIC);
+ rc = usb_submit_urb(urb, GFP_ATOMIC);
if (rc) {
dev_dbg(&port->dev, "usb_submit_urb(write bulk) failed\n");
spin_lock_irqsave(&port->lock, flags);
+ port->tx_bytes -= count;
priv->tx_room = max(priv->tx_room, room + count);
+ __set_bit(0, &port->write_urbs_free);
spin_unlock_irqrestore(&port->lock, flags);
- set_bit(0, &port->write_urbs_free);
-
return rc;
}
if (count == room)
schedule_work(&priv->unthrottle_work);
- return count;
+ return 0;
}
static void keyspan_pda_write_bulk_callback(struct urb *urb)
{
struct usb_serial_port *port = urb->context;
+ unsigned long flags;
- set_bit(0, &port->write_urbs_free);
+ spin_lock_irqsave(&port->lock, flags);
+ port->tx_bytes -= urb->transfer_buffer_length;
+ __set_bit(0, &port->write_urbs_free);
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ keyspan_pda_write_start(port);
/* queue up a wakeup at scheduler time */
usb_serial_port_softint(port);
}
-
-static int keyspan_pda_write_room(struct tty_struct *tty)
+static int keyspan_pda_write(struct tty_struct *tty, struct usb_serial_port *port,
+ const unsigned char *buf, int count)
{
- struct usb_serial_port *port = tty->driver_data;
- struct keyspan_pda_private *priv = usb_get_serial_port_data(port);
- unsigned long flags;
- int room = 0;
-
- spin_lock_irqsave(&port->lock, flags);
- if (test_bit(0, &port->write_urbs_free))
- room = priv->tx_room;
- spin_unlock_irqrestore(&port->lock, flags);
+ int rc;
- return room;
-}
+ dev_dbg(&port->dev, "%s - count = %d\n", __func__, count);
-static int keyspan_pda_chars_in_buffer(struct tty_struct *tty)
-{
- struct usb_serial_port *port = tty->driver_data;
- struct keyspan_pda_private *priv;
- unsigned long flags;
- int ret = 0;
+ if (!count)
+ return 0;
- priv = usb_get_serial_port_data(port);
+ count = kfifo_in_locked(&port->write_fifo, buf, count, &port->lock);
- /* when throttled, return at least WAKEUP_CHARS to tell select() (via
- n_tty.c:normal_poll() ) that we're not writeable. */
+ rc = keyspan_pda_write_start(port);
+ if (rc)
+ return rc;
- spin_lock_irqsave(&port->lock, flags);
- if (!test_bit(0, &port->write_urbs_free) || priv->tx_room == 0)
- ret = 256;
- spin_unlock_irqrestore(&port->lock, flags);
- return ret;
+ return count;
}
-
static void keyspan_pda_dtr_rts(struct usb_serial_port *port, int on)
{
struct usb_serial *serial = port->serial;
@@ -638,12 +629,19 @@ static void keyspan_pda_close(struct usb
{
struct keyspan_pda_private *priv = usb_get_serial_port_data(port);
- usb_kill_urb(port->write_urb);
+ /*
+ * Stop the interrupt URB first as its completion handler may submit
+ * the write URB.
+ */
usb_kill_urb(port->interrupt_in_urb);
+ usb_kill_urb(port->write_urb);
cancel_work_sync(&priv->unthrottle_work);
-}
+ spin_lock_irq(&port->lock);
+ kfifo_reset(&port->write_fifo);
+ spin_unlock_irq(&port->lock);
+}
/* download the firmware to a "fake" device (pre-renumeration) */
static int keyspan_pda_fake_startup(struct usb_serial *serial)
@@ -757,10 +755,8 @@ static struct usb_serial_driver keyspan_
.open = keyspan_pda_open,
.close = keyspan_pda_close,
.write = keyspan_pda_write,
- .write_room = keyspan_pda_write_room,
.write_bulk_callback = keyspan_pda_write_bulk_callback,
.read_int_callback = keyspan_pda_rx_interrupt,
- .chars_in_buffer = keyspan_pda_chars_in_buffer,
.throttle = keyspan_pda_rx_throttle,
.unthrottle = keyspan_pda_rx_unthrottle,
.set_termios = keyspan_pda_set_termios,
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 139/235] USB: serial: keyspan_pda: clean up comments and whitespace
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (137 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 138/235] USB: serial: keyspan_pda: add write-fifo support Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 140/235] USB: serial: keyspan_pda: fix data loss on receive throttling Greg Kroah-Hartman
` (98 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sebastian Andrzej Siewior,
Johan Hovold, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <johan@kernel.org>
[ Upstream commit 491d6927f0de587c1d322d8b29a1187b7e06a221 ]
Clean up comment style, remove some stale or redundant comments and drop
superfluous white space.
Acked-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
Stable-dep-of: 42a97c0480f9 ("USB: serial: keyspan_pda: fix data loss on receive throttling")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/serial/keyspan_pda.c | 97 ++++++++++++++++++---------------------
1 file changed, 47 insertions(+), 50 deletions(-)
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -11,7 +11,6 @@
* driver
*/
-
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
@@ -146,8 +145,10 @@ static void keyspan_pda_request_unthrott
dev_dbg(&port->dev, "%s\n", __func__);
- /* ask the device to tell us when the tx buffer becomes
- sufficiently empty */
+ /*
+ * Ask the device to tell us when the tx buffer becomes
+ * sufficiently empty.
+ */
result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
7, /* request_unthrottle */
@@ -233,7 +234,6 @@ static void keyspan_pda_rx_interrupt(str
keyspan_pda_write_start(port);
- /* queue up a wakeup at scheduler time */
usb_serial_port_softint(port);
break;
default:
@@ -317,8 +317,6 @@ static speed_t keyspan_pda_setbaud(struc
baud = 9600;
}
- /* rather than figure out how to sleep while waiting for this
- to complete, I just use the "legacy" API. */
rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
0, /* set baud */
USB_TYPE_VENDOR
@@ -331,10 +329,10 @@ static speed_t keyspan_pda_setbaud(struc
2000); /* timeout */
if (rc < 0)
return 0;
+
return baud;
}
-
static void keyspan_pda_break_ctl(struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
@@ -346,6 +344,7 @@ static void keyspan_pda_break_ctl(struct
value = 1; /* start break */
else
value = 0; /* clear break */
+
result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
4, /* set break */
USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
@@ -353,39 +352,35 @@ static void keyspan_pda_break_ctl(struct
if (result < 0)
dev_dbg(&port->dev, "%s - error %d from usb_control_msg\n",
__func__, result);
- /* there is something funky about this.. the TCSBRK that 'cu' performs
- ought to translate into a break_ctl(-1),break_ctl(0) pair HZ/4
- seconds apart, but it feels like the break sent isn't as long as it
- is on /dev/ttyS0 */
}
-
static void keyspan_pda_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
struct usb_serial *serial = port->serial;
speed_t speed;
- /* cflag specifies lots of stuff: number of stop bits, parity, number
- of data bits, baud. What can the device actually handle?:
- CSTOPB (1 stop bit or 2)
- PARENB (parity)
- CSIZE (5bit .. 8bit)
- There is minimal hw support for parity (a PSW bit seems to hold the
- parity of whatever is in the accumulator). The UART either deals
- with 10 bits (start, 8 data, stop) or 11 bits (start, 8 data,
- 1 special, stop). So, with firmware changes, we could do:
- 8N1: 10 bit
- 8N2: 11 bit, extra bit always (mark?)
- 8[EOMS]1: 11 bit, extra bit is parity
- 7[EOMS]1: 10 bit, b0/b7 is parity
- 7[EOMS]2: 11 bit, b0/b7 is parity, extra bit always (mark?)
-
- HW flow control is dictated by the tty->termios.c_cflags & CRTSCTS
- bit.
-
- For now, just do baud. */
-
+ /*
+ * cflag specifies lots of stuff: number of stop bits, parity, number
+ * of data bits, baud. What can the device actually handle?:
+ * CSTOPB (1 stop bit or 2)
+ * PARENB (parity)
+ * CSIZE (5bit .. 8bit)
+ * There is minimal hw support for parity (a PSW bit seems to hold the
+ * parity of whatever is in the accumulator). The UART either deals
+ * with 10 bits (start, 8 data, stop) or 11 bits (start, 8 data,
+ * 1 special, stop). So, with firmware changes, we could do:
+ * 8N1: 10 bit
+ * 8N2: 11 bit, extra bit always (mark?)
+ * 8[EOMS]1: 11 bit, extra bit is parity
+ * 7[EOMS]1: 10 bit, b0/b7 is parity
+ * 7[EOMS]2: 11 bit, b0/b7 is parity, extra bit always (mark?)
+ *
+ * HW flow control is dictated by the tty->termios.c_cflags & CRTSCTS
+ * bit.
+ *
+ * For now, just do baud.
+ */
speed = tty_get_baud_rate(tty);
speed = keyspan_pda_setbaud(serial, speed);
@@ -394,17 +389,19 @@ static void keyspan_pda_set_termios(stru
/* It hasn't changed so.. */
speed = tty_termios_baud_rate(old_termios);
}
- /* Only speed can change so copy the old h/w parameters
- then encode the new speed */
+ /*
+ * Only speed can change so copy the old h/w parameters then encode
+ * the new speed.
+ */
tty_termios_copy_hw(&tty->termios, old_termios);
tty_encode_baud_rate(tty, speed, speed);
}
-
-/* modem control pins: DTR and RTS are outputs and can be controlled.
- DCD, RI, DSR, CTS are inputs and can be read. All outputs can also be
- read. The byte passed is: DTR(b7) DCD RI DSR CTS RTS(b2) unused unused */
-
+/*
+ * Modem control pins: DTR and RTS are outputs and can be controlled.
+ * DCD, RI, DSR, CTS are inputs and can be read. All outputs can also be
+ * read. The byte passed is: DTR(b7) DCD RI DSR CTS RTS(b2) unused unused.
+ */
static int keyspan_pda_get_modem_info(struct usb_serial *serial,
unsigned char *value)
{
@@ -428,7 +425,6 @@ static int keyspan_pda_get_modem_info(st
return rc;
}
-
static int keyspan_pda_set_modem_info(struct usb_serial *serial,
unsigned char value)
{
@@ -504,10 +500,11 @@ static int keyspan_pda_write_start(struc
* unthrottle work is scheduled).
*/
- /* we might block because of:
- the TX urb is in-flight (wait until it completes)
- the device is full (wait until it says there is room)
- */
+ /*
+ * We might block because of:
+ * the TX urb is in-flight (wait until it completes)
+ * the device is full (wait until it says there is room)
+ */
spin_lock_irqsave(&port->lock, flags);
room = priv->tx_room;
@@ -566,7 +563,6 @@ static void keyspan_pda_write_bulk_callb
keyspan_pda_write_start(port);
- /* queue up a wakeup at scheduler time */
usb_serial_port_softint(port);
}
@@ -615,7 +611,6 @@ static int keyspan_pda_open(struct tty_s
priv->tx_room = rc;
spin_unlock_irq(&port->lock);
- /*Start reading from the device*/
rc = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
if (rc) {
dev_dbg(&port->dev, "%s - usb_submit_urb(read int) failed\n", __func__);
@@ -673,10 +668,12 @@ static int keyspan_pda_fake_startup(stru
return -ENOENT;
}
- /* after downloading firmware Renumeration will occur in a
- moment and the new device will bind to the real driver */
+ /*
+ * After downloading firmware renumeration will occur in a moment and
+ * the new device will bind to the real driver.
+ */
- /* we want this device to fail to have a driver assigned to it. */
+ /* We want this device to fail to have a driver assigned to it. */
return 1;
}
@@ -755,7 +752,7 @@ static struct usb_serial_driver keyspan_
.open = keyspan_pda_open,
.close = keyspan_pda_close,
.write = keyspan_pda_write,
- .write_bulk_callback = keyspan_pda_write_bulk_callback,
+ .write_bulk_callback = keyspan_pda_write_bulk_callback,
.read_int_callback = keyspan_pda_rx_interrupt,
.throttle = keyspan_pda_rx_throttle,
.unthrottle = keyspan_pda_rx_unthrottle,
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 140/235] USB: serial: keyspan_pda: fix data loss on receive throttling
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (138 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 139/235] USB: serial: keyspan_pda: clean up comments and whitespace Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 141/235] KVM: x86: Drop @vcpu parameter from kvm_x86_ops.hwapic_isr_update() Greg Kroah-Hartman
` (97 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Johan Hovold, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <johan@kernel.org>
[ Upstream commit 42a97c0480f96a2977e6d51ce512adc780f1ef5d ]
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: Sasha Levin <sashal@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
@@ -47,6 +47,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);
@@ -184,6 +186,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);
@@ -245,16 +248,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
@@ -264,16 +275,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)
@@ -609,6 +633,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] 239+ messages in thread
* [PATCH 5.10 141/235] KVM: x86: Drop @vcpu parameter from kvm_x86_ops.hwapic_isr_update()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (139 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 140/235] USB: serial: keyspan_pda: fix data loss on receive throttling Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 142/235] KVM: x86: Check for in-kernel xAPIC when querying APICv for directed yield Greg Kroah-Hartman
` (96 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sean Christopherson, Paolo Bonzini,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <seanjc@google.com>
[ Upstream commit d39850f57d2102c6b46feb21237bc23bc42de4f7 ]
Drop the unused @vcpu parameter from hwapic_isr_update(). AMD/AVIC is
unlikely to implement the helper, and VMX/APICv doesn't need the vCPU as
it operates on the current VMCS. The result is somewhat odd, but allows
for a decent amount of (future) cleanup in the APIC code.
No functional change intended.
Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-Id: <20220614230548.3852141-3-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Stable-dep-of: e800decd9c0a ("KVM: x86: Only reset TSC Deadline Timer in apic_timer_expired on KVM_RUN")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/x86/include/asm/kvm_host.h | 2 +-
arch/x86/kvm/lapic.c | 10 ++++------
arch/x86/kvm/svm/avic.c | 2 +-
arch/x86/kvm/svm/svm.h | 2 +-
arch/x86/kvm/vmx/vmx.c | 2 +-
5 files changed, 8 insertions(+), 10 deletions(-)
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1179,7 +1179,7 @@ struct kvm_x86_ops {
void (*pre_update_apicv_exec_ctrl)(struct kvm *kvm, bool activate);
void (*refresh_apicv_exec_ctrl)(struct kvm_vcpu *vcpu);
void (*hwapic_irr_update)(struct kvm_vcpu *vcpu, int max_irr);
- void (*hwapic_isr_update)(struct kvm_vcpu *vcpu, int isr);
+ void (*hwapic_isr_update)(int isr);
bool (*guest_apic_has_interrupt)(struct kvm_vcpu *vcpu);
void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap);
void (*set_virtual_apic_mode)(struct kvm_vcpu *vcpu);
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -520,7 +520,7 @@ static inline void apic_set_isr(int vec,
* just set SVI.
*/
if (unlikely(vcpu->arch.apicv_active))
- kvm_x86_ops.hwapic_isr_update(vcpu, vec);
+ kvm_x86_ops.hwapic_isr_update(vec);
else {
++apic->isr_count;
BUG_ON(apic->isr_count > MAX_APIC_VECTOR);
@@ -568,8 +568,7 @@ static inline void apic_clear_isr(int ve
* and must be left alone.
*/
if (unlikely(vcpu->arch.apicv_active))
- kvm_x86_ops.hwapic_isr_update(vcpu,
- apic_find_highest_isr(apic));
+ kvm_x86_ops.hwapic_isr_update(apic_find_highest_isr(apic));
else {
--apic->isr_count;
BUG_ON(apic->isr_count < 0);
@@ -2383,7 +2382,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vc
if (vcpu->arch.apicv_active) {
kvm_x86_ops.apicv_post_state_restore(vcpu);
kvm_x86_ops.hwapic_irr_update(vcpu, -1);
- kvm_x86_ops.hwapic_isr_update(vcpu, -1);
+ kvm_x86_ops.hwapic_isr_update(-1);
}
vcpu->arch.apic_arb_prio = 0;
@@ -2651,8 +2650,7 @@ int kvm_apic_set_state(struct kvm_vcpu *
kvm_x86_ops.apicv_post_state_restore(vcpu);
kvm_x86_ops.hwapic_irr_update(vcpu,
apic_find_highest_irr(apic));
- kvm_x86_ops.hwapic_isr_update(vcpu,
- apic_find_highest_isr(apic));
+ kvm_x86_ops.hwapic_isr_update(apic_find_highest_isr(apic));
}
kvm_make_request(KVM_REQ_EVENT, vcpu);
if (ioapic_in_kernel(vcpu->kvm))
--- a/arch/x86/kvm/svm/avic.c
+++ b/arch/x86/kvm/svm/avic.c
@@ -603,7 +603,7 @@ void svm_hwapic_irr_update(struct kvm_vc
{
}
-void svm_hwapic_isr_update(struct kvm_vcpu *vcpu, int max_isr)
+void svm_hwapic_isr_update(int max_isr)
{
}
--- a/arch/x86/kvm/svm/svm.h
+++ b/arch/x86/kvm/svm/svm.h
@@ -457,7 +457,7 @@ bool svm_check_apicv_inhibit_reasons(ulo
void svm_pre_update_apicv_exec_ctrl(struct kvm *kvm, bool activate);
void svm_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap);
void svm_hwapic_irr_update(struct kvm_vcpu *vcpu, int max_irr);
-void svm_hwapic_isr_update(struct kvm_vcpu *vcpu, int max_isr);
+void svm_hwapic_isr_update(int max_isr);
int svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec);
bool svm_dy_apicv_has_pending_interrupt(struct kvm_vcpu *vcpu);
int svm_update_pi_irte(struct kvm *kvm, unsigned int host_irq,
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -6403,7 +6403,7 @@ static void vmx_set_apic_access_page_add
put_page(page);
}
-static void vmx_hwapic_isr_update(struct kvm_vcpu *vcpu, int max_isr)
+static void vmx_hwapic_isr_update(int max_isr)
{
u16 status;
u8 old;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 142/235] KVM: x86: Check for in-kernel xAPIC when querying APICv for directed yield
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (140 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 141/235] KVM: x86: Drop @vcpu parameter from kvm_x86_ops.hwapic_isr_update() Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 143/235] KVM: x86: Move "apicv_active" into "struct kvm_lapic" Greg Kroah-Hartman
` (95 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sean Christopherson, Paolo Bonzini,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <seanjc@google.com>
[ Upstream commit ae801e1303e939ad5ebd9f390bdcc57275ada33b ]
Use kvm_vcpu_apicv_active() to check if APICv is active when seeing if a
vCPU is a candidate for directed yield due to a pending ACPIv interrupt.
This will allow moving apicv_active into kvm_lapic without introducing a
potential NULL pointer deref (kvm_vcpu_apicv_active() effectively adds a
pre-check on the vCPU having an in-kernel APIC).
No functional change intended.
Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-Id: <20220614230548.3852141-4-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Stable-dep-of: e800decd9c0a ("KVM: x86: Only reset TSC Deadline Timer in apic_timer_expired on KVM_RUN")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/x86/kvm/x86.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -11122,7 +11122,8 @@ bool kvm_arch_dy_runnable(struct kvm_vcp
kvm_test_request(KVM_REQ_EVENT, vcpu))
return true;
- if (vcpu->arch.apicv_active && kvm_x86_ops.dy_apicv_has_pending_interrupt(vcpu))
+ if (kvm_vcpu_apicv_active(vcpu) &&
+ kvm_x86_ops.dy_apicv_has_pending_interrupt(vcpu))
return true;
return false;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 143/235] KVM: x86: Move "apicv_active" into "struct kvm_lapic"
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (141 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 142/235] KVM: x86: Check for in-kernel xAPIC when querying APICv for directed yield Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 144/235] KVM: Introduce vcpu->wants_to_run Greg Kroah-Hartman
` (94 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sean Christopherson, Paolo Bonzini,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <seanjc@google.com>
[ Upstream commit ce0a58f4756c14d7646cfdf279dbaada9d7712a0 ]
Move the per-vCPU apicv_active flag into KVM's local APIC instance.
APICv is fully dependent on an in-kernel local APIC, but that's not at
all clear when reading the current code due to the flag being stored in
the generic kvm_vcpu_arch struct.
No functional change intended.
Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-Id: <20220614230548.3852141-5-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Stable-dep-of: e800decd9c0a ("KVM: x86: Only reset TSC Deadline Timer in apic_timer_expired on KVM_RUN")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/x86/include/asm/kvm_host.h | 1 -
arch/x86/kvm/lapic.c | 31 ++++++++++---------------------
arch/x86/kvm/lapic.h | 3 ++-
arch/x86/kvm/svm/avic.c | 2 +-
arch/x86/kvm/vmx/vmx.c | 7 ++++---
arch/x86/kvm/x86.c | 12 ++++++------
6 files changed, 23 insertions(+), 33 deletions(-)
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -544,7 +544,6 @@ struct kvm_vcpu_arch {
u64 efer;
u64 apic_base;
struct kvm_lapic *apic; /* kernel irqchip context */
- bool apicv_active;
bool load_eoi_exitmap_pending;
DECLARE_BITMAP(ioapic_handled_vectors, 256);
unsigned long apic_attention;
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -482,14 +482,10 @@ static inline int apic_find_highest_irr(
static inline void apic_clear_irr(int vec, struct kvm_lapic *apic)
{
- struct kvm_vcpu *vcpu;
-
- vcpu = apic->vcpu;
-
- if (unlikely(vcpu->arch.apicv_active)) {
+ if (unlikely(apic->apicv_active)) {
/* need to update RVI */
kvm_lapic_clear_vector(vec, apic->regs + APIC_IRR);
- kvm_x86_ops.hwapic_irr_update(vcpu,
+ kvm_x86_ops.hwapic_irr_update(apic->vcpu,
apic_find_highest_irr(apic));
} else {
apic->irr_pending = false;
@@ -507,19 +503,15 @@ EXPORT_SYMBOL_GPL(kvm_apic_clear_irr);
static inline void apic_set_isr(int vec, struct kvm_lapic *apic)
{
- struct kvm_vcpu *vcpu;
-
if (__apic_test_and_set_vector(vec, apic->regs + APIC_ISR))
return;
- vcpu = apic->vcpu;
-
/*
* With APIC virtualization enabled, all caching is disabled
* because the processor can modify ISR under the hood. Instead
* just set SVI.
*/
- if (unlikely(vcpu->arch.apicv_active))
+ if (unlikely(apic->apicv_active))
kvm_x86_ops.hwapic_isr_update(vec);
else {
++apic->isr_count;
@@ -554,12 +546,9 @@ static inline int apic_find_highest_isr(
static inline void apic_clear_isr(int vec, struct kvm_lapic *apic)
{
- struct kvm_vcpu *vcpu;
if (!__apic_test_and_clear_vector(vec, apic->regs + APIC_ISR))
return;
- vcpu = apic->vcpu;
-
/*
* We do get here for APIC virtualization enabled if the guest
* uses the Hyper-V APIC enlightenment. In this case we may need
@@ -567,7 +556,7 @@ static inline void apic_clear_isr(int ve
* on the other hand isr_count and highest_isr_cache are unused
* and must be left alone.
*/
- if (unlikely(vcpu->arch.apicv_active))
+ if (unlikely(apic->apicv_active))
kvm_x86_ops.hwapic_isr_update(apic_find_highest_isr(apic));
else {
--apic->isr_count;
@@ -706,7 +695,7 @@ static void pv_eoi_clr_pending(struct kv
static int apic_has_interrupt_for_ppr(struct kvm_lapic *apic, u32 ppr)
{
int highest_irr;
- if (apic->vcpu->arch.apicv_active)
+ if (apic->apicv_active)
highest_irr = kvm_x86_ops.sync_pir_to_irr(apic->vcpu);
else
highest_irr = apic_find_highest_irr(apic);
@@ -1538,7 +1527,7 @@ static bool lapic_timer_int_injected(str
int vec = reg & APIC_VECTOR_MASK;
void *bitmap = apic->regs + APIC_ISR;
- if (vcpu->arch.apicv_active)
+ if (apic->apicv_active)
bitmap = apic->regs + APIC_IRR;
if (apic_test_vector(vec, bitmap))
@@ -1647,7 +1636,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 && vcpu->arch.apicv_active) {
+ if (!from_timer_fn && apic->apicv_active) {
WARN_ON(kvm_get_running_vcpu() != vcpu);
kvm_apic_inject_pending_timer_irqs(apic);
return;
@@ -2317,7 +2306,7 @@ void kvm_apic_update_apicv(struct kvm_vc
{
struct kvm_lapic *apic = vcpu->arch.apic;
- if (vcpu->arch.apicv_active) {
+ if (apic->apicv_active) {
/* irr_pending is always true when apicv is activated. */
apic->irr_pending = true;
apic->isr_count = 1;
@@ -2379,7 +2368,7 @@ void kvm_lapic_reset(struct kvm_vcpu *vc
vcpu->arch.apic_base | MSR_IA32_APICBASE_BSP);
vcpu->arch.pv_eoi.msr_val = 0;
apic_update_ppr(apic);
- if (vcpu->arch.apicv_active) {
+ if (apic->apicv_active) {
kvm_x86_ops.apicv_post_state_restore(vcpu);
kvm_x86_ops.hwapic_irr_update(vcpu, -1);
kvm_x86_ops.hwapic_isr_update(-1);
@@ -2646,7 +2635,7 @@ int kvm_apic_set_state(struct kvm_vcpu *
__start_apic_timer(apic, APIC_TMCCT);
kvm_apic_update_apicv(vcpu);
apic->highest_isr_cache = -1;
- if (vcpu->arch.apicv_active) {
+ if (apic->apicv_active) {
kvm_x86_ops.apicv_post_state_restore(vcpu);
kvm_x86_ops.hwapic_irr_update(vcpu,
apic_find_highest_irr(apic));
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -47,6 +47,7 @@ struct kvm_lapic {
struct kvm_timer lapic_timer;
u32 divide_count;
struct kvm_vcpu *vcpu;
+ bool apicv_active;
bool sw_enabled;
bool irr_pending;
bool lvt0_in_nmi_mode;
@@ -216,7 +217,7 @@ static inline int apic_x2apic_mode(struc
static inline bool kvm_vcpu_apicv_active(struct kvm_vcpu *vcpu)
{
- return vcpu->arch.apic && vcpu->arch.apicv_active;
+ return vcpu->arch.apic && vcpu->arch.apic->apicv_active;
}
static inline bool kvm_apic_has_events(struct kvm_vcpu *vcpu)
--- a/arch/x86/kvm/svm/avic.c
+++ b/arch/x86/kvm/svm/avic.c
@@ -673,7 +673,7 @@ void svm_load_eoi_exitmap(struct kvm_vcp
int svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
{
- if (!vcpu->arch.apicv_active)
+ if (!kvm_vcpu_apicv_active(vcpu))
return -1;
kvm_lapic_set_irr(vec, vcpu->arch.apic);
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -4116,7 +4116,8 @@ static int vmx_deliver_posted_interrupt(
if (!r)
return 0;
- if (!vcpu->arch.apicv_active)
+ /* Note, this is called iff the local APIC is in-kernel. */
+ if (!vcpu->arch.apic->apicv_active)
return -1;
if (pi_test_and_set_pir(vector, &vmx->pi_desc))
@@ -6457,7 +6458,7 @@ static int vmx_sync_pir_to_irr(struct kv
int max_irr;
bool max_irr_updated;
- WARN_ON(!vcpu->arch.apicv_active);
+ WARN_ON(!kvm_vcpu_apicv_active(vcpu));
if (pi_test_on(&vmx->pi_desc)) {
pi_clear_on(&vmx->pi_desc);
/*
@@ -6983,7 +6984,7 @@ reenter_guest:
* but it would incur the cost of a retpoline for now.
* Revisit once static calls are available.
*/
- if (vcpu->arch.apicv_active)
+ if (kvm_vcpu_apicv_active(vcpu))
vmx_sync_pir_to_irr(vcpu);
goto reenter_guest;
}
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4182,7 +4182,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *
static int kvm_vcpu_ioctl_get_lapic(struct kvm_vcpu *vcpu,
struct kvm_lapic_state *s)
{
- if (vcpu->arch.apicv_active)
+ if (kvm_vcpu_apicv_active(vcpu))
kvm_x86_ops.sync_pir_to_irr(vcpu);
return kvm_apic_get_state(vcpu, s);
@@ -8504,7 +8504,7 @@ static void update_cr8_intercept(struct
if (!lapic_in_kernel(vcpu))
return;
- if (vcpu->arch.apicv_active)
+ if (vcpu->arch.apic->apicv_active)
return;
if (!vcpu->arch.apic->vapic_addr)
@@ -8967,7 +8967,7 @@ void kvm_vcpu_update_apicv(struct kvm_vc
if (!lapic_in_kernel(vcpu))
return;
- vcpu->arch.apicv_active = kvm_apicv_activated(vcpu->kvm);
+ vcpu->arch.apic->apicv_active = kvm_apicv_activated(vcpu->kvm);
kvm_apic_update_apicv(vcpu);
kvm_x86_ops.refresh_apicv_exec_ctrl(vcpu);
}
@@ -9031,7 +9031,7 @@ static void vcpu_scan_ioapic(struct kvm_
if (irqchip_split(vcpu->kvm))
kvm_scan_ioapic_routes(vcpu, vcpu->arch.ioapic_handled_vectors);
else {
- if (vcpu->arch.apicv_active)
+ if (kvm_vcpu_apicv_active(vcpu))
kvm_x86_ops.sync_pir_to_irr(vcpu);
if (ioapic_in_kernel(vcpu->kvm))
kvm_ioapic_scan_entry(vcpu, vcpu->arch.ioapic_handled_vectors);
@@ -9275,7 +9275,7 @@ static int vcpu_enter_guest(struct kvm_v
* This handles the case where a posted interrupt was
* notified with kvm_vcpu_kick.
*/
- if (kvm_lapic_enabled(vcpu) && vcpu->arch.apicv_active)
+ if (kvm_lapic_enabled(vcpu) && kvm_vcpu_apicv_active(vcpu))
kvm_x86_ops.sync_pir_to_irr(vcpu);
if (kvm_vcpu_exit_request(vcpu)) {
@@ -10254,7 +10254,7 @@ int kvm_arch_vcpu_create(struct kvm_vcpu
if (r < 0)
goto fail_mmu_destroy;
if (kvm_apicv_activated(vcpu->kvm))
- vcpu->arch.apicv_active = true;
+ vcpu->arch.apic->apicv_active = true;
} else
static_key_slow_inc(&kvm_no_apic_vcpu);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 144/235] KVM: Introduce vcpu->wants_to_run
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (142 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 143/235] KVM: x86: Move "apicv_active" into "struct kvm_lapic" Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 145/235] KVM: x86: Only reset TSC Deadline Timer in apic_timer_expired on KVM_RUN Greg Kroah-Hartman
` (93 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Matlack, Sean Christopherson,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Matlack <dmatlack@google.com>
[ Upstream commit a6816314af5749cd88944bfdceb270c627cdf348 ]
Introduce vcpu->wants_to_run to indicate when a vCPU is in its core run
loop, i.e. when the vCPU is running the KVM_RUN ioctl and immediate_exit
was not set.
Replace all references to vcpu->run->immediate_exit with
!vcpu->wants_to_run to avoid TOCTOU races with userspace. For example, a
malicious userspace could invoked KVM_RUN with immediate_exit=true and
then after KVM reads it to set wants_to_run=false, flip it to false.
This would result in the vCPU running in KVM_RUN with
wants_to_run=false. This wouldn't cause any real bugs today but is a
dangerous landmine.
Signed-off-by: David Matlack <dmatlack@google.com>
Link: https://lore.kernel.org/r/20240503181734.1467938-2-dmatlack@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
Stable-dep-of: e800decd9c0a ("KVM: x86: Only reset TSC Deadline Timer in apic_timer_expired on KVM_RUN")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
arch/arm64/kvm/arm.c | 2 +-
arch/mips/kvm/mips.c | 2 +-
arch/powerpc/kvm/powerpc.c | 2 +-
arch/s390/kvm/kvm-s390.c | 2 +-
arch/x86/kvm/x86.c | 4 ++--
include/linux/kvm_host.h | 1 +
virt/kvm/kvm_main.c | 3 +++
7 files changed, 10 insertions(+), 6 deletions(-)
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -686,7 +686,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v
return ret;
}
- if (run->immediate_exit)
+ if (!vcpu->wants_to_run)
return -EINTR;
vcpu_load(vcpu);
--- a/arch/mips/kvm/mips.c
+++ b/arch/mips/kvm/mips.c
@@ -464,7 +464,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v
vcpu->mmio_needed = 0;
}
- if (vcpu->run->immediate_exit)
+ if (!vcpu->wants_to_run)
goto out;
lose_fpu(1);
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -1832,7 +1832,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v
kvm_sigset_activate(vcpu);
- if (run->immediate_exit)
+ if (!vcpu->wants_to_run)
r = -EINTR;
else
r = kvmppc_vcpu_run(vcpu);
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -4373,7 +4373,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v
struct kvm_run *kvm_run = vcpu->run;
int rc;
- if (kvm_run->immediate_exit)
+ if (!vcpu->wants_to_run)
return -EINTR;
if (kvm_run->kvm_valid_regs & ~KVM_SYNC_S390_VALID_FIELDS ||
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -9648,7 +9648,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v
kvm_load_guest_fpu(vcpu);
if (unlikely(vcpu->arch.mp_state == KVM_MP_STATE_UNINITIALIZED)) {
- if (kvm_run->immediate_exit) {
+ if (!vcpu->wants_to_run) {
r = -EINTR;
goto out;
}
@@ -9692,7 +9692,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_v
} else
WARN_ON(vcpu->arch.pio.count || vcpu->mmio_needed);
- if (kvm_run->immediate_exit)
+ if (!vcpu->wants_to_run)
r = -EINTR;
else
r = vcpu_run(vcpu);
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -318,6 +318,7 @@ struct kvm_vcpu {
bool dy_eligible;
} spin_loop;
#endif
+ bool wants_to_run;
bool preempted;
bool ready;
struct kvm_vcpu_arch arch;
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -3366,7 +3366,10 @@ static long kvm_vcpu_ioctl(struct file *
synchronize_rcu();
put_pid(oldpid);
}
+ vcpu->wants_to_run = !READ_ONCE(vcpu->run->immediate_exit);
r = kvm_arch_vcpu_ioctl_run(vcpu);
+ vcpu->wants_to_run = false;
+
trace_kvm_userspace_exit(vcpu->run->exit_reason, r);
break;
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 145/235] KVM: x86: Only reset TSC Deadline Timer in apic_timer_expired on KVM_RUN
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (143 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 144/235] KVM: Introduce vcpu->wants_to_run Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 146/235] drm/dp/mst: fix buffer overflows in sideband chunk accumulation Greg Kroah-Hartman
` (92 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Venkatesh Srinivas, James Houghton,
Chao Gao, Paolo Bonzini, Sasha Levin, David Matlack,
Sean Christopherson, Jim Mattson
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Venkatesh Srinivas <venkateshs@chromium.org>
[ Upstream commit e800decd9c0ac4349bcd8f8f9b29fd21fe93165e ]
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: Sasha Levin <sashal@kernel.org>
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
@@ -1636,7 +1636,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] 239+ messages in thread
* [PATCH 5.10 146/235] drm/dp/mst: fix buffer overflows in sideband chunk accumulation
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (144 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 145/235] KVM: x86: Only reset TSC Deadline Timer in apic_timer_expired on KVM_RUN Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 147/235] usb: gadget: f_tcm: synchronize delayed set_alt with teardown Greg Kroah-Hartman
` (91 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Ashutosh Desai, Lyude Paul,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ashutosh Desai <ashutoshdesai993@gmail.com>
[ Upstream commit 55bd5e685bda455b9b50c835f8c8442d52a344a3 ]
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: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/drm_dp_mst_topology.c | 9 +++++++++
1 file changed, 9 insertions(+)
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -778,6 +778,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;
@@ -788,6 +794,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] 239+ messages in thread
* [PATCH 5.10 147/235] usb: gadget: f_tcm: synchronize delayed set_alt with teardown
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (145 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 146/235] drm/dp/mst: fix buffer overflows in sideband chunk accumulation Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 148/235] drm/dp/mst: fix OOB reads on 2-byte fields in sideband reply parsers Greg Kroah-Hartman
` (90 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, stable, Cen Zhang, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cen Zhang <zzzccc427@gmail.com>
[ Upstream commit 79e2d75725c85607f8a9d87ae9cace62a19f767d ]
The f_tcm set_alt() path defers endpoint setup to a work item and
completes the delayed status response from process context. The delayed
work uses f_tcm private state and may complete the setup request after
disconnect or function teardown has already moved on.
Cancel and drain the delayed set_alt work when the function is unbound or
freed. For disable paths, which are reached under the composite device
lock, use a small state machine and a non-sleeping cancellation path
instead of cancel_work_sync(). If the work is already running, mark it
cancelled and let the worker own the cleanup; otherwise tcm_disable() can
cancel the queued work and clean up immediately.
Also serialize the final delayed-status completion with the cancellation
check while holding the composite device lock. This prevents a disconnect
from clearing delayed_status while the worker is about to complete the
control request.
Validation reproduced this kernel report:
BUG: KASAN: slab-use-after-free in tcm_delayed_set_alt+0x6c/0xef0
Call Trace:
<TASK>
dump_stack_lvl+0x66/0xa0
print_report+0xce/0x630
? tcm_delayed_set_alt+0x6c/0xef0
? srso_alias_return_thunk+0x5/0xfbef5
? __virt_addr_valid+0x188/0x320
? tcm_delayed_set_alt+0x6c/0xef0
kasan_report+0xe0/0x110
? tcm_delayed_set_alt+0x6c/0xef0
tcm_delayed_set_alt+0x6c/0xef0
? __pfx_tcm_delayed_set_alt+0x10/0x10
? process_one_work+0x4cb/0xb90
? rcu_is_watching+0x20/0x50
? tcm_delayed_set_alt+0x9/0xef0
process_one_work+0x4d7/0xb90
? __pfx_process_one_work+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? __list_add_valid_or_report+0x37/0xf0
? __pfx_tcm_delayed_set_alt+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
worker_thread+0x2d8/0x570
? __pfx_worker_thread+0x10/0x10
kthread+0x1ad/0x1f0
? __pfx_kthread+0x10/0x10
ret_from_fork+0x3c9/0x540
? __pfx_ret_from_fork+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? __switch_to+0x2e9/0x730
? __pfx_kthread+0x10/0x10
ret_from_fork_asm+0x1a/0x30
</TASK>
Allocated by task 544:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
__kasan_kmalloc+0x8f/0xa0
tcm_alloc+0x68/0x180
usb_get_function+0x36/0x60
config_usb_cfg_link+0x125/0x1b0
configfs_symlink+0x322/0x890
vfs_symlink+0xc2/0x270
filename_symlinkat+0x295/0x2f0
__x64_sys_symlinkat+0x62/0x90
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Freed by task 661:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
kasan_save_free_info+0x3b/0x60
__kasan_slab_free+0x43/0x70
kfree+0x2f9/0x530
config_usb_cfg_unlink+0x173/0x1e0
configfs_unlink+0x1fa/0x340
vfs_unlink+0x15c/0x510
filename_unlinkat+0x2ba/0x450
__x64_sys_unlinkat+0x63/0x90
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Fixes: c52661d60f63 ("usb-gadget: Initial merge of target module for UASP + BOT")
Cc: stable <stable@kernel.org>
Assisted-by: Codex:gpt-5.5
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Link: https://patch.msgid.link/20260627104153.3822495-1-zzzccc427@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[ adjusted context for 6.12's scalar `struct usbg_cdb cmd` and missing `stream_hash`, dropping the `hash_init()` context line ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/gadget/function/f_tcm.c | 192 ++++++++++++++++++++++++++++++------
drivers/usb/gadget/function/tcm.h | 13 ++
2 files changed, 177 insertions(+), 28 deletions(-)
--- a/drivers/usb/gadget/function/f_tcm.c
+++ b/drivers/usb/gadget/function/f_tcm.c
@@ -2065,31 +2065,158 @@ ep_fail:
return -ENOTSUPP;
}
-struct guas_setup_wq {
- struct work_struct work;
- struct f_uas *fu;
- unsigned int alt;
-};
+static void tcm_cleanup_old_alt(struct f_uas *fu)
+{
+ if (fu->flags & USBG_IS_UAS)
+ uasp_cleanup_old_alt(fu);
+ else if (fu->flags & USBG_IS_BOT)
+ bot_cleanup_old_alt(fu);
+ fu->flags = 0;
+}
+
+static void tcm_delayed_set_alt_done(struct f_uas *fu)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&fu->delayed_set_alt_lock, flags);
+ fu->delayed_set_alt_state = USBG_DELAYED_SET_ALT_IDLE;
+ fu->delayed_set_alt_cancel = false;
+ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
+}
+
+static bool tcm_delayed_set_alt_cancelled(struct f_uas *fu)
+{
+ bool cancelled;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fu->delayed_set_alt_lock, flags);
+ cancelled = fu->delayed_set_alt_cancel;
+ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
+
+ return cancelled;
+}
+
+static bool tcm_complete_delayed_status(struct f_uas *fu)
+{
+ struct usb_composite_dev *cdev = fu->function.config->cdev;
+ struct usb_request *req = cdev->req;
+ unsigned long cdev_flags;
+ bool cancelled;
+ int ret;
+
+ spin_lock_irqsave(&cdev->lock, cdev_flags);
+ spin_lock(&fu->delayed_set_alt_lock);
+ cancelled = fu->delayed_set_alt_cancel;
+ if (!cancelled) {
+ fu->delayed_set_alt_state = USBG_DELAYED_SET_ALT_IDLE;
+ fu->delayed_set_alt_cancel = false;
+ }
+ spin_unlock(&fu->delayed_set_alt_lock);
+
+ if (cancelled) {
+ spin_unlock_irqrestore(&cdev->lock, cdev_flags);
+ return false;
+ }
+
+ if (cdev->delayed_status == 0) {
+ WARN(cdev, "%s: Unexpected call\n", __func__);
+ } else if (--cdev->delayed_status == 0) {
+ req->length = 0;
+ req->context = cdev;
+ ret = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+ if (ret == 0) {
+ cdev->setup_pending = true;
+ } else {
+ req->status = 0;
+ req->complete(cdev->gadget->ep0, req);
+ }
+ }
+
+ spin_unlock_irqrestore(&cdev->lock, cdev_flags);
+
+ return true;
+}
+
+static bool tcm_cancel_delayed_set_alt(struct f_uas *fu)
+{
+ bool cleanup = false;
+ bool cancel = false;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fu->delayed_set_alt_lock, flags);
+ switch (fu->delayed_set_alt_state) {
+ case USBG_DELAYED_SET_ALT_IDLE:
+ cleanup = true;
+ break;
+ case USBG_DELAYED_SET_ALT_QUEUED:
+ case USBG_DELAYED_SET_ALT_RUNNING:
+ fu->delayed_set_alt_cancel = true;
+ cancel = true;
+ break;
+ }
+ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
+
+ if (cancel && cancel_work(&fu->delayed_set_alt)) {
+ spin_lock_irqsave(&fu->delayed_set_alt_lock, flags);
+ if (fu->delayed_set_alt_state == USBG_DELAYED_SET_ALT_QUEUED) {
+ fu->delayed_set_alt_state = USBG_DELAYED_SET_ALT_IDLE;
+ fu->delayed_set_alt_cancel = false;
+ cleanup = true;
+ }
+ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
+ }
+
+ return cleanup;
+}
+
+static void tcm_cancel_delayed_set_alt_sync(struct f_uas *fu)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&fu->delayed_set_alt_lock, flags);
+ if (fu->delayed_set_alt_state != USBG_DELAYED_SET_ALT_IDLE)
+ fu->delayed_set_alt_cancel = true;
+ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
+
+ cancel_work_sync(&fu->delayed_set_alt);
+
+ spin_lock_irqsave(&fu->delayed_set_alt_lock, flags);
+ fu->delayed_set_alt_state = USBG_DELAYED_SET_ALT_IDLE;
+ fu->delayed_set_alt_cancel = false;
+ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
+}
static void tcm_delayed_set_alt(struct work_struct *wq)
{
- struct guas_setup_wq *work = container_of(wq, struct guas_setup_wq,
- work);
- struct f_uas *fu = work->fu;
- int alt = work->alt;
+ struct f_uas *fu = container_of(wq, struct f_uas, delayed_set_alt);
+ unsigned long flags;
+ unsigned int alt;
+
+ spin_lock_irqsave(&fu->delayed_set_alt_lock, flags);
+ if (fu->delayed_set_alt_state != USBG_DELAYED_SET_ALT_QUEUED) {
+ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
+ return;
+ }
+ fu->delayed_set_alt_state = USBG_DELAYED_SET_ALT_RUNNING;
+ alt = fu->delayed_alt;
+ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
- kfree(work);
+ tcm_cleanup_old_alt(fu);
- if (fu->flags & USBG_IS_BOT)
- bot_cleanup_old_alt(fu);
- if (fu->flags & USBG_IS_UAS)
- uasp_cleanup_old_alt(fu);
+ if (tcm_delayed_set_alt_cancelled(fu))
+ goto out_done;
if (alt == USB_G_ALT_INT_BBB)
bot_set_alt(fu);
else if (alt == USB_G_ALT_INT_UAS)
uasp_set_alt(fu);
- usb_composite_setup_continue(fu->function.config->cdev);
+
+ if (tcm_complete_delayed_status(fu))
+ return;
+
+ tcm_cleanup_old_alt(fu);
+out_done:
+ tcm_delayed_set_alt_done(fu);
}
static int tcm_get_alt(struct usb_function *f, unsigned intf)
@@ -2115,15 +2242,20 @@ static int tcm_set_alt(struct usb_functi
return -EOPNOTSUPP;
if ((alt == USB_G_ALT_INT_BBB) || (alt == USB_G_ALT_INT_UAS)) {
- struct guas_setup_wq *work;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fu->delayed_set_alt_lock, flags);
+ if (fu->delayed_set_alt_state != USBG_DELAYED_SET_ALT_IDLE) {
+ spin_unlock_irqrestore(&fu->delayed_set_alt_lock,
+ flags);
+ return -EBUSY;
+ }
+ fu->delayed_alt = alt;
+ fu->delayed_set_alt_cancel = false;
+ fu->delayed_set_alt_state = USBG_DELAYED_SET_ALT_QUEUED;
+ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags);
- work = kmalloc(sizeof(*work), GFP_ATOMIC);
- if (!work)
- return -ENOMEM;
- INIT_WORK(&work->work, tcm_delayed_set_alt);
- work->fu = fu;
- work->alt = alt;
- schedule_work(&work->work);
+ schedule_work(&fu->delayed_set_alt);
return USB_GADGET_DELAYED_STATUS;
}
return -EOPNOTSUPP;
@@ -2133,11 +2265,8 @@ static void tcm_disable(struct usb_funct
{
struct f_uas *fu = to_f_uas(f);
- if (fu->flags & USBG_IS_UAS)
- uasp_cleanup_old_alt(fu);
- else if (fu->flags & USBG_IS_BOT)
- bot_cleanup_old_alt(fu);
- fu->flags = 0;
+ if (tcm_cancel_delayed_set_alt(fu))
+ tcm_cleanup_old_alt(fu);
}
static int tcm_setup(struct usb_function *f,
@@ -2285,11 +2414,16 @@ static void tcm_free(struct usb_function
{
struct f_uas *tcm = to_f_uas(f);
+ tcm_cancel_delayed_set_alt_sync(tcm);
kfree(tcm);
}
static void tcm_unbind(struct usb_configuration *c, struct usb_function *f)
{
+ struct f_uas *fu = to_f_uas(f);
+
+ tcm_cancel_delayed_set_alt_sync(fu);
+ tcm_cleanup_old_alt(fu);
usb_free_all_descriptors(f);
}
@@ -2322,6 +2456,8 @@ static struct usb_function *tcm_alloc(st
fu->function.disable = tcm_disable;
fu->function.free_func = tcm_free;
fu->tpg = tpg_instances[i].tpg;
+ INIT_WORK(&fu->delayed_set_alt, tcm_delayed_set_alt);
+ spin_lock_init(&fu->delayed_set_alt_lock);
mutex_unlock(&tpg_instances_lock);
return &fu->function;
--- a/drivers/usb/gadget/function/tcm.h
+++ b/drivers/usb/gadget/function/tcm.h
@@ -3,6 +3,7 @@
#define __TARGET_USB_GADGET_H__
#include <linux/kref.h>
+#include <linux/spinlock.h>
/* #include <linux/usb/uas.h> */
#include <linux/usb/composite.h>
#include <linux/usb/uas.h>
@@ -26,6 +27,12 @@ enum {
#define USB_G_DEFAULT_SESSION_TAGS 128
+enum {
+ USBG_DELAYED_SET_ALT_IDLE = 0,
+ USBG_DELAYED_SET_ALT_QUEUED,
+ USBG_DELAYED_SET_ALT_RUNNING,
+};
+
struct tcm_usbg_nexus {
struct se_session *tvn_se_sess;
};
@@ -117,6 +124,12 @@ struct f_uas {
#define USBG_IS_BOT (1 << 3)
#define USBG_BOT_CMD_PEND (1 << 4)
+ struct work_struct delayed_set_alt;
+ spinlock_t delayed_set_alt_lock; /* protects delayed_set_alt_* */
+ unsigned int delayed_alt;
+ unsigned int delayed_set_alt_state;
+ bool delayed_set_alt_cancel;
+
struct usbg_cdb cmd;
struct usb_ep *ep_in;
struct usb_ep *ep_out;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 148/235] drm/dp/mst: fix OOB reads on 2-byte fields in sideband reply parsers
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (146 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 147/235] usb: gadget: f_tcm: synchronize delayed set_alt with teardown Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 149/235] drm/dp/mst: fix OOB reads in remote DPCD/I2C " Greg Kroah-Hartman
` (89 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Ashutosh Desai, Lyude Paul,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ashutosh Desai <ashutoshdesai993@gmail.com>
[ Upstream commit 6b89ba3dba2f583626fb693e47e951ffb8bf591f ]
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: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/drm_dp_mst_topology.c | 17 ++++-------------
1 file changed, 4 insertions(+), 13 deletions(-)
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -920,16 +920,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);
@@ -947,12 +944,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);
@@ -966,12 +960,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] 239+ messages in thread
* [PATCH 5.10 149/235] drm/dp/mst: fix OOB reads in remote DPCD/I2C sideband reply parsers
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (147 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 148/235] drm/dp/mst: fix OOB reads on 2-byte fields in sideband reply parsers Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 150/235] dma-buf/drivers: make reserving a shared slot mandatory v4 Greg Kroah-Hartman
` (88 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Ashutosh Desai, Lyude Paul,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ashutosh Desai <ashutoshdesai993@gmail.com>
[ Upstream commit 1a8f537f5a1eeac941f262fe73078d6b08ba83c0 ]
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: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/drm_dp_mst_topology.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -868,7 +868,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);
@@ -904,7 +904,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] 239+ messages in thread
* [PATCH 5.10 150/235] dma-buf/drivers: make reserving a shared slot mandatory v4
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (148 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 149/235] drm/dp/mst: fix OOB reads in remote DPCD/I2C " Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 151/235] drm/virtio: use uninterruptible resv lock for plane updates Greg Kroah-Hartman
` (87 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Christian König, Daniel Vetter,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian König <christian.koenig@amd.com>
[ Upstream commit c8d4c18bfbc4ab467188dbe45cc8155759f49d9e ]
Audit all the users of dma_resv_add_excl_fence() and make sure they
reserve a shared slot also when only trying to add an exclusive fence.
This is the next step towards handling the exclusive fence like a
shared one.
v2: fix missed case in amdgpu
v3: and two more radeon, rename function
v4: add one more case to TTM, fix i915 after rebase
Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/20220406075132.3263-2-christian.koenig@amd.com
Stable-dep-of: a48bbcc7ac73 ("drm/virtio: use uninterruptible resv lock for plane updates")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/dma-buf/dma-resv.c | 8 ++++----
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 4 ++--
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 2 +-
drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c | 2 +-
drivers/gpu/drm/i915/i915_vma.c | 2 +-
drivers/gpu/drm/lima/lima_gem.c | 2 +-
drivers/gpu/drm/msm/msm_gem_submit.c | 2 +-
drivers/gpu/drm/nouveau/nouveau_fence.c | 2 +-
drivers/gpu/drm/qxl/qxl_release.c | 2 +-
drivers/gpu/drm/radeon/radeon_vm.c | 2 +-
drivers/gpu/drm/ttm/ttm_bo.c | 4 ++--
drivers/gpu/drm/ttm/ttm_execbuf_util.c | 4 ++--
drivers/gpu/drm/vc4/vc4_gem.c | 2 +-
drivers/gpu/drm/vgem/vgem_fence.c | 2 +-
include/linux/dma-resv.h | 2 +-
15 files changed, 21 insertions(+), 21 deletions(-)
--- a/drivers/dma-buf/dma-resv.c
+++ b/drivers/dma-buf/dma-resv.c
@@ -173,7 +173,7 @@ void dma_resv_fini(struct dma_resv *obj)
EXPORT_SYMBOL(dma_resv_fini);
/**
- * dma_resv_reserve_shared - Reserve space to add shared fences to
+ * dma_resv_reserve_fences - Reserve space to add shared fences to
* a dma_resv.
* @obj: reservation object
* @num_fences: number of fences we want to add
@@ -184,7 +184,7 @@ EXPORT_SYMBOL(dma_resv_fini);
* RETURNS
* Zero for success, or -errno
*/
-int dma_resv_reserve_shared(struct dma_resv *obj, unsigned int num_fences)
+int dma_resv_reserve_fences(struct dma_resv *obj, unsigned int num_fences)
{
struct dma_resv_list *old, *new;
unsigned int i, j, k, max;
@@ -250,7 +250,7 @@ int dma_resv_reserve_shared(struct dma_r
return 0;
}
-EXPORT_SYMBOL(dma_resv_reserve_shared);
+EXPORT_SYMBOL(dma_resv_reserve_fences);
/**
* dma_resv_add_shared_fence - Add a fence to a shared slot
@@ -258,7 +258,7 @@ EXPORT_SYMBOL(dma_resv_reserve_shared);
* @fence: the shared fence to add
*
* Add a fence to a shared slot, obj->lock must be held, and
- * dma_resv_reserve_shared() has been called.
+ * dma_resv_reserve_fences() has been called.
*/
void dma_resv_add_shared_fence(struct dma_resv *obj, struct dma_fence *fence)
{
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -950,7 +950,7 @@ static int init_kfd_vm(struct amdgpu_vm
AMDGPU_FENCE_OWNER_KFD, false);
if (ret)
goto wait_pd_fail;
- ret = dma_resv_reserve_shared(vm->root.base.bo->tbo.base.resv, 1);
+ ret = dma_resv_reserve_fences(vm->root.base.bo->tbo.base.resv, 1);
if (ret)
goto reserve_shared_fail;
amdgpu_bo_fence(vm->root.base.bo,
@@ -2205,7 +2205,7 @@ int amdgpu_amdkfd_add_gws_to_process(voi
* Add process eviction fence to bo so they can
* evict each other.
*/
- ret = dma_resv_reserve_shared(gws_bo->tbo.base.resv, 1);
+ ret = dma_resv_reserve_fences(gws_bo->tbo.base.resv, 1);
if (ret)
goto reserve_shared_fail;
amdgpu_bo_fence(gws_bo, &process_info->eviction_fence->base, true);
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -2904,7 +2904,7 @@ int amdgpu_vm_init(struct amdgpu_device
if (r)
goto error_free_root;
- r = dma_resv_reserve_shared(root->tbo.base.resv, 1);
+ r = dma_resv_reserve_fences(root->tbo.base.resv, 1);
if (r)
goto error_unreserve;
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
@@ -180,7 +180,7 @@ static int submit_fence_sync(struct etna
struct dma_resv *robj = bo->obj->base.resv;
if (!(bo->flags & ETNA_SUBMIT_BO_WRITE)) {
- ret = dma_resv_reserve_shared(robj, 1);
+ ret = dma_resv_reserve_fences(robj, 1);
if (ret)
return ret;
}
--- a/drivers/gpu/drm/i915/i915_vma.c
+++ b/drivers/gpu/drm/i915/i915_vma.c
@@ -1241,7 +1241,7 @@ int i915_vma_move_to_active(struct i915_
obj->write_domain = I915_GEM_DOMAIN_RENDER;
obj->read_domains = 0;
} else {
- err = dma_resv_reserve_shared(vma->resv, 1);
+ err = dma_resv_reserve_fences(vma->resv, 1);
if (unlikely(err))
return err;
--- a/drivers/gpu/drm/lima/lima_gem.c
+++ b/drivers/gpu/drm/lima/lima_gem.c
@@ -263,7 +263,7 @@ static int lima_gem_sync_bo(struct lima_
int err = 0;
if (!write) {
- err = dma_resv_reserve_shared(lima_bo_resv(bo), 1);
+ err = dma_resv_reserve_fences(lima_bo_resv(bo), 1);
if (err)
return err;
}
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -230,7 +230,7 @@ static int submit_fence_sync(struct msm_
* strange place to call it. OTOH this is a
* convenient can-fail point to hook it in.
*/
- ret = dma_resv_reserve_shared(msm_obj->base.resv,
+ ret = dma_resv_reserve_fences(msm_obj->base.resv,
1);
if (ret)
return ret;
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -349,7 +349,7 @@ nouveau_fence_sync(struct nouveau_bo *nv
int ret = 0, i;
if (!exclusive) {
- ret = dma_resv_reserve_shared(resv, 1);
+ ret = dma_resv_reserve_fences(resv, 1);
if (ret)
return ret;
--- a/drivers/gpu/drm/qxl/qxl_release.c
+++ b/drivers/gpu/drm/qxl/qxl_release.c
@@ -239,7 +239,7 @@ static int qxl_release_validate_bo(struc
return ret;
}
- ret = dma_resv_reserve_shared(bo->tbo.base.resv, 1);
+ ret = dma_resv_reserve_fences(bo->tbo.base.resv, 1);
if (ret)
return ret;
--- a/drivers/gpu/drm/radeon/radeon_vm.c
+++ b/drivers/gpu/drm/radeon/radeon_vm.c
@@ -831,7 +831,7 @@ static int radeon_vm_update_ptes(struct
int r;
radeon_sync_resv(rdev, &ib->sync, pt->tbo.base.resv, true);
- r = dma_resv_reserve_shared(pt->tbo.base.resv, 1);
+ r = dma_resv_reserve_fences(pt->tbo.base.resv, 1);
if (r)
return r;
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -830,7 +830,7 @@ static int ttm_bo_add_move_fence(struct
dma_resv_add_shared_fence(bo->base.resv, fence);
- ret = dma_resv_reserve_shared(bo->base.resv, 1);
+ ret = dma_resv_reserve_fences(bo->base.resv, 1);
if (unlikely(ret)) {
dma_fence_put(fence);
return ret;
@@ -950,7 +950,7 @@ int ttm_bo_mem_space(struct ttm_buffer_o
bool type_found = false;
int i, ret;
- ret = dma_resv_reserve_shared(bo->base.resv, 1);
+ ret = dma_resv_reserve_fences(bo->base.resv, 1);
if (unlikely(ret))
return ret;
--- a/drivers/gpu/drm/ttm/ttm_execbuf_util.c
+++ b/drivers/gpu/drm/ttm/ttm_execbuf_util.c
@@ -106,7 +106,7 @@ int ttm_eu_reserve_buffers(struct ww_acq
if (!entry->num_shared)
continue;
- ret = dma_resv_reserve_shared(bo->base.resv,
+ ret = dma_resv_reserve_fences(bo->base.resv,
entry->num_shared);
if (!ret)
continue;
@@ -123,7 +123,7 @@ int ttm_eu_reserve_buffers(struct ww_acq
}
if (!ret && entry->num_shared)
- ret = dma_resv_reserve_shared(bo->base.resv,
+ ret = dma_resv_reserve_fences(bo->base.resv,
entry->num_shared);
if (unlikely(ret != 0)) {
--- a/drivers/gpu/drm/vc4/vc4_gem.c
+++ b/drivers/gpu/drm/vc4/vc4_gem.c
@@ -644,7 +644,7 @@ retry:
for (i = 0; i < exec->bo_count; i++) {
bo = &exec->bo[i]->base;
- ret = dma_resv_reserve_shared(bo->resv, 1);
+ ret = dma_resv_reserve_fences(bo->resv, 1);
if (ret) {
vc4_unlock_bo_reservations(dev, exec, acquire_ctx);
return ret;
--- a/drivers/gpu/drm/vgem/vgem_fence.c
+++ b/drivers/gpu/drm/vgem/vgem_fence.c
@@ -162,7 +162,7 @@ int vgem_fence_attach_ioctl(struct drm_d
dma_resv_lock(resv, NULL);
if (arg->flags & VGEM_FENCE_WRITE)
dma_resv_add_excl_fence(resv, fence);
- else if ((ret = dma_resv_reserve_shared(resv, 1)) == 0)
+ else if ((ret = dma_resv_reserve_fences(resv, 1)) == 0)
dma_resv_add_shared_fence(resv, fence);
dma_resv_unlock(resv);
--- a/include/linux/dma-resv.h
+++ b/include/linux/dma-resv.h
@@ -273,7 +273,7 @@ dma_resv_get_excl_rcu(struct dma_resv *o
void dma_resv_init(struct dma_resv *obj);
void dma_resv_fini(struct dma_resv *obj);
-int dma_resv_reserve_shared(struct dma_resv *obj, unsigned int num_fences);
+int dma_resv_reserve_fences(struct dma_resv *obj, unsigned int num_fences);
void dma_resv_add_shared_fence(struct dma_resv *obj, struct dma_fence *fence);
void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 151/235] drm/virtio: use uninterruptible resv lock for plane updates
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (149 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 150/235] dma-buf/drivers: make reserving a shared slot mandatory v4 Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 152/235] drm/displayid: fix Tiled Display Topology ID size Greg Kroah-Hartman
` (86 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, syzbot+72bd3dd3a5d5f39a0271,
Deepanshu Kartikey, Dmitry Osipenko, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Deepanshu Kartikey <kartikey406@gmail.com>
[ Upstream commit a48bbcc7ac739e93562d6148c6fa504c2e9f22f8 ]
virtio_gpu_cursor_plane_update() and virtio_gpu_resource_flush() lock
the framebuffer BO's dma_resv via virtio_gpu_array_lock_resv() and
ignore its return value. The function can fail with -EINTR from
dma_resv_lock_interruptible() (signal during lock wait) or with
-ENOMEM from dma_resv_reserve_fences() (fence slot allocation),
leaving the resv lock not held. The queue path then walks the object
array and calls dma_resv_add_fence(), which requires the lock held;
with lockdep enabled this trips dma_resv_assert_held():
WARNING: drivers/dma-buf/dma-resv.c:296 at dma_resv_add_fence+0x71e/0x840
Call Trace:
virtio_gpu_array_add_fence
virtio_gpu_queue_ctrl_sgs
virtio_gpu_queue_fenced_ctrl_buffer
virtio_gpu_cursor_plane_update
drm_atomic_helper_commit_planes
drm_atomic_helper_commit_tail
commit_tail
drm_atomic_helper_commit
drm_atomic_commit
drm_atomic_helper_update_plane
__setplane_atomic
drm_mode_cursor_universal
drm_mode_cursor_common
drm_mode_cursor_ioctl
drm_ioctl
__x64_sys_ioctl
Beyond the WARN, mutating the dma_resv fence list without the lock
races with concurrent readers/writers and can corrupt the list.
Both call sites run inside the .atomic_update plane callback, which
DRM atomic helpers do not allow to fail (by the time it runs, the
commit has been signed off to userspace and there is no clean
rollback path). Moving the lock acquisition to .prepare_fb was
rejected because the broader lock scope deadlocks against other BO
locking paths in the same atomic commit.
Introduce virtio_gpu_lock_one_resv_uninterruptible() that uses
dma_resv_lock() instead of dma_resv_lock_interruptible(). This
eliminates the -EINTR failure mode -- the realistic syzbot trigger
-- without extending the lock hold across the commit. The helper
locks a single BO and rejects nents > 1 with -EINVAL; both fix
sites lock exactly one BO.
Use it from virtio_gpu_cursor_plane_update() and
virtio_gpu_resource_flush(); check the return value to handle the
remaining -ENOMEM case from dma_resv_reserve_fences() by freeing
the objs and skipping the plane update for that frame. The
framebuffer BOs touched here are not shared with other contexts
and lock contention is expected to be brief, so the loss of
signal-interruptibility is acceptable.
Other callers of virtio_gpu_array_lock_resv() (the ioctl paths)
continue to use the interruptible variant.
The bug was reported by syzbot, triggered via fault injection
(fail_nth) on the DRM_IOCTL_MODE_CURSOR path, which forces the
-ENOMEM branch in dma_resv_reserve_fences().
Reported-by: syzbot+72bd3dd3a5d5f39a0271@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=72bd3dd3a5d5f39a0271
Fixes: 5cfd31c5b3a3 ("drm/virtio: fix virtio_gpu_cursor_plane_update().")
Cc: stable@vger.kernel.org
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Link: https://patch.msgid.link/20260519082247.34470-1-kartikey406@gmail.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/virtio/virtgpu_drv.h | 1 +
drivers/gpu/drm/virtio/virtgpu_gem.c | 17 +++++++++++++++++
drivers/gpu/drm/virtio/virtgpu_plane.c | 5 ++++-
3 files changed, 22 insertions(+), 1 deletion(-)
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -259,6 +259,7 @@ virtio_gpu_array_from_handles(struct drm
void virtio_gpu_array_add_obj(struct virtio_gpu_object_array *objs,
struct drm_gem_object *obj);
int virtio_gpu_array_lock_resv(struct virtio_gpu_object_array *objs);
+int virtio_gpu_lock_one_resv_uninterruptible(struct virtio_gpu_object_array *objs);
void virtio_gpu_array_unlock_resv(struct virtio_gpu_object_array *objs);
void virtio_gpu_array_add_fence(struct virtio_gpu_object_array *objs,
struct dma_fence *fence);
--- a/drivers/gpu/drm/virtio/virtgpu_gem.c
+++ b/drivers/gpu/drm/virtio/virtgpu_gem.c
@@ -217,6 +217,23 @@ int virtio_gpu_array_lock_resv(struct vi
return ret;
}
+int virtio_gpu_lock_one_resv_uninterruptible(struct virtio_gpu_object_array *objs)
+{
+ int ret;
+
+ if (objs->nents != 1)
+ return -EINVAL;
+
+ dma_resv_lock(objs->objs[0]->resv, NULL);
+
+ ret = dma_resv_reserve_fences(objs->objs[0]->resv, 1);
+ if (ret) {
+ virtio_gpu_array_unlock_resv(objs);
+ return ret;
+ }
+ return 0;
+}
+
void virtio_gpu_array_unlock_resv(struct virtio_gpu_object_array *objs)
{
if (objs->nents == 1) {
--- a/drivers/gpu/drm/virtio/virtgpu_plane.c
+++ b/drivers/gpu/drm/virtio/virtgpu_plane.c
@@ -260,7 +260,10 @@ static void virtio_gpu_cursor_plane_upda
if (!objs)
return;
virtio_gpu_array_add_obj(objs, vgfb->base.obj[0]);
- virtio_gpu_array_lock_resv(objs);
+ if (virtio_gpu_lock_one_resv_uninterruptible(objs)) {
+ virtio_gpu_array_put_free(objs);
+ return;
+ }
virtio_gpu_cmd_transfer_to_host_2d
(vgdev, 0,
plane->state->crtc_w,
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 152/235] drm/displayid: fix Tiled Display Topology ID size
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (150 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 151/235] drm/virtio: use uninterruptible resv lock for plane updates Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 153/235] drm/tegra: fbdev: Remove offset into framebuffer memory Greg Kroah-Hartman
` (85 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Dave Airlie, Jani Nikula,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jani Nikula <jani.nikula@intel.com>
[ Upstream commit 90c0486a82e27393f9eaf3bb350f51a0bd38cb6b ]
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: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/drm_connector.c | 12 ++++++------
include/drm/drm_connector.h | 6 +++---
include/drm/drm_displayid.h | 2 +-
3 files changed, 10 insertions(+), 10 deletions(-)
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -2586,7 +2586,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.
*
@@ -2594,14 +2594,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);
@@ -2616,7 +2616,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.
@@ -2625,7 +2625,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;
@@ -2635,7 +2635,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/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1689,13 +1689,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);
--- a/include/drm/drm_displayid.h
+++ b/include/drm/drm_displayid.h
@@ -71,7 +71,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 {
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 153/235] drm/tegra: fbdev: Remove offset into framebuffer memory
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (151 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 152/235] drm/displayid: fix Tiled Display Topology ID size Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 154/235] drm/virtio: Return proper error codes instead of -1 Greg Kroah-Hartman
` (84 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Thomas Zimmermann, dri-devel,
linux-tegra, Thierry Reding, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Zimmermann <tzimmermann@suse.de>
[ Upstream commit a18b6e30ecd69096beda4a0c96d2570900c3879a ]
The screen_buffer field in struct fb_info contains the kernel address
of the first byte of framebuffer memory. Do not add the display offset.
This offset only describes scrolling during scanout.
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Fixes: de2ba664c30f ("gpu: host1x: drm: Add memory manager and fb")
Cc: dri-devel@lists.freedesktop.org
Cc: linux-tegra@vger.kernel.org
Cc: <stable@vger.kernel.org> # v3.10+
Signed-off-by: Thierry Reding <treding@nvidia.com>
Link: https://patch.msgid.link/20260421073646.144712-3-tzimmermann@suse.de
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/tegra/fb.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
--- a/drivers/gpu/drm/tegra/fb.c
+++ b/drivers/gpu/drm/tegra/fb.c
@@ -211,7 +211,6 @@ static int tegra_fbdev_probe(struct drm_
struct drm_mode_fb_cmd2 cmd = { 0 };
unsigned int bytes_per_pixel;
struct drm_framebuffer *fb;
- unsigned long offset;
struct fb_info *info;
struct tegra_bo *bo;
size_t size;
@@ -257,9 +256,6 @@ static int tegra_fbdev_probe(struct drm_
drm_fb_helper_fill_info(info, helper, sizes);
- offset = info->var.xoffset * bytes_per_pixel +
- info->var.yoffset * fb->pitches[0];
-
if (bo->pages) {
bo->vaddr = vmap(bo->pages, bo->num_pages, VM_MAP,
pgprot_writecombine(PAGE_KERNEL));
@@ -271,9 +267,9 @@ static int tegra_fbdev_probe(struct drm_
}
drm->mode_config.fb_base = (resource_size_t)bo->iova;
- info->screen_base = (void __iomem *)bo->vaddr + offset;
+ info->screen_base = (void __iomem *)bo->vaddr;
info->screen_size = size;
- info->fix.smem_start = (unsigned long)(bo->iova + offset);
+ info->fix.smem_start = (unsigned long)(bo->iova);
info->fix.smem_len = size;
return 0;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 154/235] drm/virtio: Return proper error codes instead of -1
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (152 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 153/235] drm/tegra: fbdev: Remove offset into framebuffer memory Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 155/235] drm/virtio: bound EDID block reads to the response buffer Greg Kroah-Hartman
` (83 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Dmitry Osipenko, Gerd Hoffmann,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Osipenko <dmitry.osipenko@collabora.com>
[ Upstream commit 4c703f5d6f776eaa6a98611c9b5dfe800fbeb0c8 ]
Don't return -1 in error cases, return proper error code. The returned
error codes propagate to error messages and to userspace and it's always
good to have a meaningful error number for debugging purposes.
Signed-off-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20220630200726.1884320-10-dmitry.osipenko@collabora.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Stable-dep-of: 4e1a53892ba7 ("drm/virtio: bound EDID block reads to the response buffer")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/virtio/virtgpu_vq.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -329,7 +329,7 @@ static int virtio_gpu_queue_ctrl_sgs(str
if (fence && vbuf->objs)
virtio_gpu_array_unlock_resv(vbuf->objs);
free_vbuf(vgdev, vbuf);
- return -1;
+ return -ENODEV;
}
if (vgdev->has_indirect)
@@ -393,7 +393,7 @@ static int virtio_gpu_queue_fenced_ctrl_
if (!sgt) {
if (fence && vbuf->objs)
virtio_gpu_array_unlock_resv(vbuf->objs);
- return -1;
+ return -ENOMEM;
}
elemcnt += sg_ents;
@@ -725,7 +725,7 @@ static int virtio_get_edid_block(void *d
size_t start = block * EDID_LENGTH;
if (start + len > le32_to_cpu(resp->size))
- return -1;
+ return -EINVAL;
memcpy(buf, resp->edid + start, len);
return 0;
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 155/235] drm/virtio: bound EDID block reads to the response buffer
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (153 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 154/235] drm/virtio: Return proper error codes instead of -1 Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 156/235] media: aspeed: fix missing of_reserved_mem_device_release() on probe failure Greg Kroah-Hartman
` (82 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Bryam Vargas, Dmitry Osipenko,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <hexlabsecurity@proton.me>
[ Upstream commit 4e1a53892ba7f8a3e1da6bfc53c83ae7c812dccd ]
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: Sasha Levin <sashal@kernel.org>
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
@@ -724,7 +724,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] 239+ messages in thread
* [PATCH 5.10 156/235] media: aspeed: fix missing of_reserved_mem_device_release() on probe failure
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (154 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 155/235] drm/virtio: bound EDID block reads to the response buffer Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 157/235] drm/i915/hdcp: require monotonically increasing seq_num_v Greg Kroah-Hartman
` (81 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Carlier, Hans Verkuil,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Carlier <devnexen@gmail.com>
[ Upstream commit 253c8ef7d57da0c74db251f385324faaa5ae2257 ]
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: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/platform/aspeed-video.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/media/platform/aspeed-video.c
+++ b/drivers/media/platform/aspeed-video.c
@@ -1724,6 +1724,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] 239+ messages in thread
* [PATCH 5.10 157/235] drm/i915/hdcp: require monotonically increasing seq_num_v
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (155 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 156/235] media: aspeed: fix missing of_reserved_mem_device_release() on probe failure Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 158/235] media: marvell-cam: fix missing pci_disable_device() on remove Greg Kroah-Hartman
` (80 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Martin Hodo, Suraj Kandpal,
Jani Nikula, Joonas Lahtinen, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jani Nikula <jani.nikula@intel.com>
[ Upstream commit db9e64c983dcb07ff256bd455f258c44aa530ff8 ]
The HDCP 2.2 specification requires the seq_num_v to be monotonically
increasing, and repeated seq_num_v needs to be treated as an integrity
failure. Make it so.
For the first message, seq_num_v must be zero, and is already
checked. We can only check for less-than-or-equal for the subsequent
messages, where hdcp2_encrypted is true.
Discovered using AI-assisted static analysis confirmed by Intel Product
Security.
Reported-by: Martin Hodo <martin.hodo@intel.com>
Fixes: d849178e2c9e ("drm/i915: Implement HDCP2.2 repeater authentication")
Cc: stable@vger.kernel.org # v5.2+
Cc: Suraj Kandpal <suraj.kandpal@intel.com>
Reviewed-by: Suraj Kandpal <suraj.kandpal@intel.com>
Link: https://patch.msgid.link/20260625104407.1025614-1-jani.nikula@intel.com
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
(cherry picked from commit 58a224375c81179b52558c53d8857b93196d2687)
Signed-off-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/i915/display/intel_hdcp.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
--- a/drivers/gpu/drm/i915/display/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_hdcp.c
@@ -1534,9 +1534,10 @@ int hdcp2_authenticate_repeater_topology
return -EINVAL;
}
- if (seq_num_v < hdcp->seq_num_v) {
- /* Roll over of the seq_num_v from repeater. Reauthenticate. */
- drm_dbg_kms(&dev_priv->drm, "Seq_num_v roll over.\n");
+ if (hdcp->hdcp2_encrypted && seq_num_v <= hdcp->seq_num_v) {
+ /* Reauthenticate on Seq_num_v repeat or rollover */
+ drm_dbg_kms(&dev_priv->drm, "Seq_num_v %s\n",
+ seq_num_v == hdcp->seq_num_v ? "repeat" : "rollover");
return -EINVAL;
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 158/235] media: marvell-cam: fix missing pci_disable_device() on remove
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (156 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 157/235] drm/i915/hdcp: require monotonically increasing seq_num_v Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 159/235] media: i2c: imx219: Drop IMX219_VTS_* macros Greg Kroah-Hartman
` (79 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Guangshuo Li, Hans Verkuil,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <lgs201920130244@gmail.com>
[ Upstream commit 033ff0420e4c9c240ae5523fff39770298efa964 ]
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: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/platform/marvell-ccic/cafe-driver.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/media/platform/marvell-ccic/cafe-driver.c
+++ b/drivers/media/platform/marvell-ccic/cafe-driver.c
@@ -600,6 +600,7 @@ static void cafe_pci_remove(struct pci_d
return;
}
cafe_shutdown(cam);
+ pci_disable_device(pdev);
kfree(cam);
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 159/235] media: i2c: imx219: Drop IMX219_VTS_* macros
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (157 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 158/235] media: marvell-cam: fix missing pci_disable_device() on remove Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 160/235] media: i2c: imx219: Correct the minimum vblanking value Greg Kroah-Hartman
` (78 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Laurent Pinchart, Dave Stevenson,
Jacopo Mondi, Sakari Ailus, Hans Verkuil, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
[ Upstream commit 5ebbdd7aab3321e60a8be23aac1fee4f16644021 ]
The IMX219_VTS_* macros define default VTS values for the modes
supported by the driver. They are used in a single place, and hinder
readability compared to using the value directly as a decimal number.
Drop them.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Stable-dep-of: 2c4f1ba73543 ("media: imx219: Fix maximum frame length in lines")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/i2c/imx219.c | 24 +++++++-----------------
1 file changed, 7 insertions(+), 17 deletions(-)
--- a/drivers/media/i2c/imx219.c
+++ b/drivers/media/i2c/imx219.c
@@ -49,20 +49,10 @@
/* V_TIMING internal */
#define IMX219_REG_VTS 0x0160
-#define IMX219_VTS_15FPS 0x0dc6
-#define IMX219_VTS_30FPS_1080P 0x06e3
-#define IMX219_VTS_30FPS_BINNED 0x06e3
-#define IMX219_VTS_30FPS_640x480 0x06e3
-#define IMX219_VTS_MAX 0xffff
+#define IMX219_FLL_MAX 0xffff
#define IMX219_VBLANK_MIN 4
-/*Frame Length Line*/
-#define IMX219_FLL_MIN 0x08a6
-#define IMX219_FLL_MAX 0xffff
-#define IMX219_FLL_STEP 1
-#define IMX219_FLL_DEFAULT 0x0c98
-
/* HBLANK control - read only */
#define IMX219_PPL_DEFAULT 3448
@@ -382,7 +372,7 @@ static const struct imx219_mode supporte
.width = 3280,
.height = 2464
},
- .vts_def = IMX219_VTS_15FPS,
+ .vts_def = 3526,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_3280x2464_regs),
.regs = mode_3280x2464_regs,
@@ -399,7 +389,7 @@ static const struct imx219_mode supporte
.width = 1920,
.height = 1080
},
- .vts_def = IMX219_VTS_30FPS_1080P,
+ .vts_def = 1763,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_1920_1080_regs),
.regs = mode_1920_1080_regs,
@@ -416,7 +406,7 @@ static const struct imx219_mode supporte
.width = 3280,
.height = 2464
},
- .vts_def = IMX219_VTS_30FPS_BINNED,
+ .vts_def = 1763,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_1640_1232_regs),
.regs = mode_1640_1232_regs,
@@ -433,7 +423,7 @@ static const struct imx219_mode supporte
.width = 1280,
.height = 960
},
- .vts_def = IMX219_VTS_30FPS_640x480,
+ .vts_def = 1763,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_640_480_regs),
.regs = mode_640_480_regs,
@@ -829,7 +819,7 @@ static int imx219_set_pad_format(struct
imx219->mode = mode;
/* Update limits and set FPS to default */
__v4l2_ctrl_modify_range(imx219->vblank, IMX219_VBLANK_MIN,
- IMX219_VTS_MAX - mode->height, 1,
+ IMX219_FLL_MAX - mode->height, 1,
mode->vts_def - mode->height);
__v4l2_ctrl_s_ctrl(imx219->vblank,
mode->vts_def - mode->height);
@@ -1246,7 +1236,7 @@ static int imx219_init_controls(struct i
/* Initial vblank/hblank/exposure parameters based on current mode */
imx219->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
V4L2_CID_VBLANK, IMX219_VBLANK_MIN,
- IMX219_VTS_MAX - height, 1,
+ IMX219_FLL_MAX - height, 1,
imx219->mode->vts_def - height);
hblank = IMX219_PPL_DEFAULT - imx219->mode->width;
imx219->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 160/235] media: i2c: imx219: Correct the minimum vblanking value
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (158 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 159/235] media: i2c: imx219: Drop IMX219_VTS_* macros Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 161/235] media: i2c: imx219: Rename VTS to FRM_LENGTH Greg Kroah-Hartman
` (77 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, David Plowman, Jacopo Mondi,
Dave Stevenson, Jai Luthra, Sakari Ailus, Hans Verkuil,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Plowman <david.plowman@raspberrypi.com>
[ Upstream commit e3b82d49bf676f3c873e642038765eac32ab6d39 ]
The datasheet for this sensor documents the minimum vblanking as being
32 lines. It does fix some problems with occasional black lines at the
bottom of images (tested on Raspberry Pi).
Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Stable-dep-of: 2c4f1ba73543 ("media: imx219: Fix maximum frame length in lines")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/i2c/imx219.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/media/i2c/imx219.c
+++ b/drivers/media/i2c/imx219.c
@@ -51,7 +51,7 @@
#define IMX219_REG_VTS 0x0160
#define IMX219_FLL_MAX 0xffff
-#define IMX219_VBLANK_MIN 4
+#define IMX219_VBLANK_MIN 32
/* HBLANK control - read only */
#define IMX219_PPL_DEFAULT 3448
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 161/235] media: i2c: imx219: Rename VTS to FRM_LENGTH
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (159 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 160/235] media: i2c: imx219: Correct the minimum vblanking value Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 162/235] media: imx219: Fix maximum frame length in lines Greg Kroah-Hartman
` (76 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Dave Stevenson, Jai Luthra,
Sakari Ailus, Hans Verkuil, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jai Luthra <jai.luthra@ideasonboard.com>
[ Upstream commit 04f78503f99ae7e9887c7fe5e4bc54a7cfb10fe0 ]
The IMX219 datasheet refers to the vertical length + blanking as
FRM_LENGTH instead of VTS.
Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl>
Stable-dep-of: 2c4f1ba73543 ("media: imx219: Fix maximum frame length in lines")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/i2c/imx219.c | 33 ++++++++++++++++-----------------
1 file changed, 16 insertions(+), 17 deletions(-)
--- a/drivers/media/i2c/imx219.c
+++ b/drivers/media/i2c/imx219.c
@@ -47,12 +47,6 @@
#define IMX219_DEFAULT_LINK_FREQ 456000000
-/* V_TIMING internal */
-#define IMX219_REG_VTS 0x0160
-#define IMX219_FLL_MAX 0xffff
-
-#define IMX219_VBLANK_MIN 32
-
/* HBLANK control - read only */
#define IMX219_PPL_DEFAULT 3448
@@ -77,6 +71,11 @@
#define IMX219_DGTL_GAIN_DEFAULT 0x0100
#define IMX219_DGTL_GAIN_STEP 1
+/* V_TIMING internal */
+#define IMX219_REG_FRM_LENGTH_A 0x0160
+#define IMX219_FLL_MAX 0xffff
+#define IMX219_VBLANK_MIN 32
+
#define IMX219_REG_ORIENTATION 0x0172
/* Binning Mode */
@@ -135,7 +134,7 @@ struct imx219_mode {
struct v4l2_rect crop;
/* V-timing */
- unsigned int vts_def;
+ unsigned int fll_def;
/* Default register values */
struct imx219_reg_list reg_list;
@@ -372,7 +371,7 @@ static const struct imx219_mode supporte
.width = 3280,
.height = 2464
},
- .vts_def = 3526,
+ .fll_def = 3526,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_3280x2464_regs),
.regs = mode_3280x2464_regs,
@@ -389,7 +388,7 @@ static const struct imx219_mode supporte
.width = 1920,
.height = 1080
},
- .vts_def = 1763,
+ .fll_def = 1763,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_1920_1080_regs),
.regs = mode_1920_1080_regs,
@@ -406,7 +405,7 @@ static const struct imx219_mode supporte
.width = 3280,
.height = 2464
},
- .vts_def = 1763,
+ .fll_def = 1763,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_1640_1232_regs),
.regs = mode_1640_1232_regs,
@@ -423,7 +422,7 @@ static const struct imx219_mode supporte
.width = 1280,
.height = 960
},
- .vts_def = 1763,
+ .fll_def = 1763,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_640_480_regs),
.regs = mode_640_480_regs,
@@ -660,7 +659,7 @@ static int imx219_set_ctrl(struct v4l2_c
imx219->vflip->val << 1);
break;
case V4L2_CID_VBLANK:
- ret = imx219_write_reg(imx219, IMX219_REG_VTS,
+ ret = imx219_write_reg(imx219, IMX219_REG_FRM_LENGTH_A,
IMX219_REG_VALUE_16BIT,
imx219->mode->height + ctrl->val);
break;
@@ -820,11 +819,11 @@ static int imx219_set_pad_format(struct
/* Update limits and set FPS to default */
__v4l2_ctrl_modify_range(imx219->vblank, IMX219_VBLANK_MIN,
IMX219_FLL_MAX - mode->height, 1,
- mode->vts_def - mode->height);
+ mode->fll_def - mode->height);
__v4l2_ctrl_s_ctrl(imx219->vblank,
- mode->vts_def - mode->height);
+ mode->fll_def - mode->height);
/* Update max exposure while meeting expected vblanking */
- exposure_max = mode->vts_def - 4;
+ exposure_max = mode->fll_def - 4;
exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ?
exposure_max : IMX219_EXPOSURE_DEFAULT;
__v4l2_ctrl_modify_range(imx219->exposure,
@@ -1237,14 +1236,14 @@ static int imx219_init_controls(struct i
imx219->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
V4L2_CID_VBLANK, IMX219_VBLANK_MIN,
IMX219_FLL_MAX - height, 1,
- imx219->mode->vts_def - height);
+ imx219->mode->fll_def - height);
hblank = IMX219_PPL_DEFAULT - imx219->mode->width;
imx219->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
V4L2_CID_HBLANK, hblank, hblank,
1, hblank);
if (imx219->hblank)
imx219->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
- exposure_max = imx219->mode->vts_def - 4;
+ exposure_max = imx219->mode->fll_def - 4;
exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ?
exposure_max : IMX219_EXPOSURE_DEFAULT;
imx219->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 162/235] media: imx219: Fix maximum frame length in lines
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (160 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 161/235] media: i2c: imx219: Rename VTS to FRM_LENGTH Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 163/235] wifi: ath6kl: fix use-after-free in aggr_reset_state() Greg Kroah-Hartman
` (75 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sakari Ailus, Dave Stevenson,
Laurent Pinchart, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sakari Ailus <sakari.ailus@linux.intel.com>
[ Upstream commit 2c4f1ba7354312ad2d6e34e70a518a51a9344715 ]
The driver used the maximum frame length in lines value of 0xffff, but the
maximum appears to be 0xfffe instead. Fix it.
Fixes: 1283b3b8f82b ("media: i2c: Add driver for Sony IMX219 sensor")
Cc: stable@vger.kernel.org
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/i2c/imx219.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/media/i2c/imx219.c
+++ b/drivers/media/i2c/imx219.c
@@ -73,7 +73,7 @@
/* V_TIMING internal */
#define IMX219_REG_FRM_LENGTH_A 0x0160
-#define IMX219_FLL_MAX 0xffff
+#define IMX219_FLL_MAX 0xfffe
#define IMX219_VBLANK_MIN 32
#define IMX219_REG_ORIENTATION 0x0172
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 163/235] wifi: ath6kl: fix use-after-free in aggr_reset_state()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (161 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 162/235] media: imx219: Fix maximum frame length in lines Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 164/235] media: v4l: async: Set owner for async sub-devices Greg Kroah-Hartman
` (74 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Daniel Hodges,
Vasanthakumar Thiagarajan, Jeff Johnson, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Hodges <git@danielhodges.dev>
[ Upstream commit ba7debb4dd6427386862220e8335a53a4bfc235d ]
The aggr_reset_state() function uses timer_delete() (non-synchronous)
for the aggregation timer before proceeding to delete TID state and
before the structure is freed by callers like aggr_module_destroy().
If the timer callback (aggr_timeout) is executing when aggr_reset_state()
is called, the callback will continue to access aggr_conn fields like
rx_tid[] and stat[] which may be freed immediately after by
kfree(aggr_info->aggr_conn) in aggr_module_destroy().
Additionally, the timer callback can re-arm itself via mod_timer() while
aggr_reset_state() is running, creating a more complex race condition.
Use timer_delete_sync() instead to ensure any running timer callback
has completed before returning.
Fixes: bdcd81707973 ("Add ath6kl cleaned up driver")
Cc: stable@vger.kernel.org
Signed-off-by: Daniel Hodges <git@danielhodges.dev>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
Link: https://patch.msgid.link/20260206185207.30098-1-git@danielhodges.dev
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/wireless/ath/ath6kl/txrx.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/wireless/ath/ath6kl/txrx.c
+++ b/drivers/net/wireless/ath/ath6kl/txrx.c
@@ -1829,7 +1829,7 @@ void aggr_reset_state(struct aggr_info_c
return;
if (aggr_conn->timer_scheduled) {
- del_timer(&aggr_conn->timer);
+ timer_delete_sync(&aggr_conn->timer);
aggr_conn->timer_scheduled = false;
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 164/235] media: v4l: async: Set owner for async sub-devices
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (162 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 163/235] wifi: ath6kl: fix use-after-free in aggr_reset_state() Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 165/235] media: v4l2-fwnode: Fix subdev owner overwritten in v4l2_async_register_subdev_sensor() Greg Kroah-Hartman
` (73 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sakari Ailus, Mauro Carvalho Chehab,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sakari Ailus <sakari.ailus@linux.intel.com>
[ Upstream commit 8a718752f5c339137c5b05e54f116cd26d5a4143 ]
Set the owner field of the async sub-devices by making
v4l2_async_register_subdev() a macro and obtaining THIS_MODULE that way.
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
Stable-dep-of: 06cb687a5132 ("media: v4l2-fwnode: Fix subdev owner overwritten in v4l2_async_register_subdev_sensor()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/v4l2-core/v4l2-async.c | 8 ++++++--
include/media/v4l2-async.h | 4 +++-
2 files changed, 9 insertions(+), 3 deletions(-)
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -747,7 +747,7 @@ v4l2_async_notifier_add_devname_subdev(s
}
EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_devname_subdev);
-int v4l2_async_register_subdev(struct v4l2_subdev *sd)
+int __v4l2_async_register_subdev(struct v4l2_subdev *sd, struct module *module)
{
struct v4l2_async_notifier *subdev_notifier;
struct v4l2_async_notifier *notifier;
@@ -761,6 +761,8 @@ int v4l2_async_register_subdev(struct v4
if (!sd->fwnode && sd->dev)
sd->fwnode = dev_fwnode(sd->dev);
+ sd->owner = module;
+
mutex_lock(&list_lock);
INIT_LIST_HEAD(&sd->async_list);
@@ -811,9 +813,11 @@ err_unbind:
mutex_unlock(&list_lock);
+ sd->owner = NULL;
+
return ret;
}
-EXPORT_SYMBOL(v4l2_async_register_subdev);
+EXPORT_SYMBOL(__v4l2_async_register_subdev);
void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
{
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -298,7 +298,9 @@ void v4l2_async_notifier_cleanup(struct
*
* @sd: pointer to &struct v4l2_subdev
*/
-int v4l2_async_register_subdev(struct v4l2_subdev *sd);
+#define v4l2_async_register_subdev(sd) \
+ __v4l2_async_register_subdev(sd, THIS_MODULE)
+int __v4l2_async_register_subdev(struct v4l2_subdev *sd, struct module *module);
/**
* v4l2_async_register_subdev_sensor_common - registers a sensor sub-device to
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 165/235] media: v4l2-fwnode: Fix subdev owner overwritten in v4l2_async_register_subdev_sensor()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (163 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 164/235] media: v4l: async: Set owner for async sub-devices Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 166/235] wifi: brcmfmac: drain bus_reset work on device removal Greg Kroah-Hartman
` (72 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Frank Li, Mirela Rabulea,
Laurent Pinchart, Sakari Ailus, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mirela Rabulea <mirela.rabulea@nxp.com>
[ Upstream commit 06cb687a5132fcffe624c0070576ab852ac6b568 ]
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: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/media/v4l2-core/v4l2-fwnode.c | 7 ++++---
include/media/v4l2-async.h | 5 ++++-
2 files changed, 8 insertions(+), 4 deletions(-)
--- a/drivers/media/v4l2-core/v4l2-fwnode.c
+++ b/drivers/media/v4l2-core/v4l2-fwnode.c
@@ -1337,7 +1337,8 @@ int v4l2_async_notifier_parse_fwnode_sen
}
EXPORT_SYMBOL_GPL(v4l2_async_notifier_parse_fwnode_sensor_common);
-int v4l2_async_register_subdev_sensor_common(struct v4l2_subdev *sd)
+int __v4l2_async_register_subdev_sensor_common(struct v4l2_subdev *sd,
+ struct module *module)
{
struct v4l2_async_notifier *notifier;
int ret;
@@ -1360,7 +1361,7 @@ int v4l2_async_register_subdev_sensor_co
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;
@@ -1377,7 +1378,7 @@ out_cleanup:
return ret;
}
-EXPORT_SYMBOL_GPL(v4l2_async_register_subdev_sensor_common);
+EXPORT_SYMBOL_GPL(__v4l2_async_register_subdev_sensor_common);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>");
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -321,8 +321,11 @@ 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_common(sd) \
+ __v4l2_async_register_subdev_sensor_common(sd, THIS_MODULE)
int __must_check
-v4l2_async_register_subdev_sensor_common(struct v4l2_subdev *sd);
+__v4l2_async_register_subdev_sensor_common(struct v4l2_subdev *sd,
+ struct module *module);
/**
* v4l2_async_unregister_subdev - unregisters a sub-device to the asynchronous
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 166/235] wifi: brcmfmac: drain bus_reset work on device removal
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (164 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 165/235] media: v4l2-fwnode: Fix subdev owner overwritten in v4l2_async_register_subdev_sensor() Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 167/235] ALSA: seq: close a re-opened queue timer in the destructor Greg Kroah-Hartman
` (71 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Fan Wu, Arend van Spriel,
Johannes Berg, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fan Wu <fanwu01@zju.edu.cn>
[ Upstream commit 43b25879f004c98defa2776bedc6ca4763c51945 ]
brcmf_fw_crashed() and the debugfs "reset" entry both schedule
drvr->bus_reset, whose callback recovers drvr through container_of()
and dereferences it. The removal path frees drvr (brcmf_free ->
wiphy_free) without draining the work, so a bus_reset callback pending
or running during removal can outlive drvr.
Cancellation cannot live in brcmf_detach() or brcmf_free(): the work
callback reaches teardown through the bus .reset op (PCIe
brcmf_pcie_reset -> brcmf_detach; SDIO brcmf_sdio_bus_reset ->
brcmf_sdiod_remove -> brcmf_free), so cancelling there would wait for
the running work and deadlock.
Add a per-bus mutex (bus_reset_lock) and route all arming through
brcmf_bus_schedule_reset(), which under the lock skips when the bus is
marked removing. Each bus remove entry calls
brcmf_bus_cancel_reset_work(), which under the same lock sets removing
and cancels the work. Holding the mutex across cancel_work_sync() makes
the set-removing + drain step atomic. Every producer reaches the arming
path from process context -- the PCIe firmware-halt notification runs in
the threaded IRQ handler (brcmf_pcie_isr_thread) and the SDIO hostmail
path runs from the data workqueue -- so the mutex is taken only in
sleepable contexts. Where applicable the remove entry first stops the
firmware-crash producer: on PCIe mask the mailbox and synchronize_irq;
on SDIO unregister the bus interrupt and cancel the data worker, which
also reports firmware halts through brcmf_fw_crashed(). The mutex is
initialized at bus allocation. The SDIO suspend power-off path frees
drvr through the same brcmf_sdiod_remove() and takes the same lock;
resume re-allows the work only on a successful re-probe.
Also guard brcmf_fw_crashed() against a NULL bus_if/drvr: it can fire
before brcmf_attach() wires up drvr, and it dereferences drvr
(bphy_err/brcmf_dev_coredump) before reaching the arming gate.
The bus_reset work is shared across buses, so the drain is applied to
every remove path: PCIe (the .reset op introduced by the Fixes commit),
SDIO (arms the same work through brcmf_fw_crashed()), and USB (via the
debugfs "reset" entry). cancel_work_sync() drains a running or pending
bus_reset work item before removal frees drvr, and patch 1/2 makes the
scratch-buffer release safe when reset teardown has already released
those DMA buffers.
This patch fixes the lifetime of the bus_reset work item itself. It does
not attempt to address the separate, pre-existing lifetime of the
asynchronous firmware completion started by the PCIe reset path. That
callback needs its own lifetime/ownership protocol and is being tracked
separately.
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-3-fanwu01@zju.edu.cn
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/broadcom/brcm80211/brcmfmac/bcmsdh.c | 13 ++++
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 6 +
drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 45 +++++++++++++-
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 6 +
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 6 +
drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h | 1
drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 3
7 files changed, 77 insertions(+), 3 deletions(-)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -1042,6 +1042,7 @@ static int brcmf_ops_sdio_probe(struct s
bus_if = kzalloc(sizeof(struct brcmf_bus), GFP_KERNEL);
if (!bus_if)
return -ENOMEM;
+ mutex_init(&bus_if->bus_reset_lock);
sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL);
if (!sdiodev) {
kfree(bus_if);
@@ -1101,6 +1102,14 @@ static void brcmf_ops_sdio_remove(struct
if (func->num != 1)
return;
+ /* Drain bus_reset before the shared brcmf_sdiod_remove()
+ * teardown, which the SDIO reset callback also reaches. The
+ * data worker can arm bus_reset via brcmf_fw_crashed(); cancel
+ * it first.
+ */
+ brcmf_sdio_cancel_datawork(sdiodev->bus);
+ brcmf_bus_cancel_reset_work(bus_if);
+
/* only proceed with rest of cleanup if func 1 */
brcmf_sdiod_remove(sdiodev);
@@ -1162,6 +1171,8 @@ static int brcmf_ops_sdio_suspend(struct
} else {
/* power will be cut so remove device, probe again in resume */
brcmf_sdiod_intr_unregister(sdiodev);
+ brcmf_sdio_cancel_datawork(sdiodev->bus);
+ brcmf_bus_cancel_reset_work(bus_if);
ret = brcmf_sdiod_remove(sdiodev);
if (ret)
brcmf_err("Failed to remove device on suspend\n");
@@ -1187,6 +1198,8 @@ static int brcmf_ops_sdio_resume(struct
ret = brcmf_sdiod_probe(sdiodev);
if (ret)
brcmf_err("Failed to probe device on resume\n");
+ else
+ brcmf_bus_allow_reset_work(bus_if);
} else {
if (sdiodev->wowl_enabled &&
sdiodev->settings->bus.sdio.oob_irq_supported)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
@@ -6,6 +6,7 @@
#ifndef BRCMFMAC_BUS_H
#define BRCMFMAC_BUS_H
+#include <linux/mutex.h>
#include "debug.h"
/* IDs of the 6 default common rings of msgbuf protocol */
@@ -149,11 +150,16 @@ struct brcmf_bus {
u32 chiprev;
bool always_use_fws_queue;
bool wowl_supported;
+ bool removing; /* device removal in progress; quiesce async work */
+ struct mutex bus_reset_lock;
const struct brcmf_bus_ops *ops;
struct brcmf_bus_msgbuf *msgbuf;
};
+void brcmf_bus_cancel_reset_work(struct brcmf_bus *bus_if);
+void brcmf_bus_allow_reset_work(struct brcmf_bus *bus_if);
+
/*
* callback wrappers
*/
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -1166,6 +1166,35 @@ static int brcmf_revinfo_read(struct seq
return 0;
}
+/*
+ * Serialize arming from debugfs reset and brcmf_fw_crashed() against
+ * teardown. The remove path sets ->removing and drains the work while
+ * holding bus_reset_lock, so a racing armer is either drained or skips it.
+ */
+static void brcmf_bus_schedule_reset(struct brcmf_bus *bus_if)
+{
+ mutex_lock(&bus_if->bus_reset_lock);
+ if (bus_if->drvr && bus_if->drvr->bus_reset.func && !bus_if->removing)
+ schedule_work(&bus_if->drvr->bus_reset);
+ mutex_unlock(&bus_if->bus_reset_lock);
+}
+
+void brcmf_bus_cancel_reset_work(struct brcmf_bus *bus_if)
+{
+ mutex_lock(&bus_if->bus_reset_lock);
+ bus_if->removing = true;
+ if (bus_if->drvr)
+ cancel_work_sync(&bus_if->drvr->bus_reset);
+ mutex_unlock(&bus_if->bus_reset_lock);
+}
+
+void brcmf_bus_allow_reset_work(struct brcmf_bus *bus_if)
+{
+ mutex_lock(&bus_if->bus_reset_lock);
+ bus_if->removing = false;
+ mutex_unlock(&bus_if->bus_reset_lock);
+}
+
static void brcmf_core_bus_reset(struct work_struct *work)
{
struct brcmf_pub *drvr = container_of(work, struct brcmf_pub,
@@ -1186,7 +1215,7 @@ static ssize_t bus_reset_write(struct fi
if (value != 1)
return -EINVAL;
- schedule_work(&drvr->bus_reset);
+ brcmf_bus_schedule_reset(drvr->bus_if);
return count;
}
@@ -1404,13 +1433,23 @@ void brcmf_dev_coredump(struct device *d
void brcmf_fw_crashed(struct device *dev)
{
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
- struct brcmf_pub *drvr = bus_if->drvr;
+ struct brcmf_pub *drvr;
+
+ /* May fire before brcmf_attach() wires up drvr, or after removal
+ * has cleared it; guard the derefs below (and the arming gate in
+ * brcmf_bus_schedule_reset() already checks drvr/->removing).
+ */
+ if (!bus_if)
+ return;
+ drvr = bus_if->drvr;
+ if (!drvr)
+ return;
bphy_err(drvr, "Firmware has halted or crashed\n");
brcmf_dev_coredump(dev);
- schedule_work(&drvr->bus_reset);
+ brcmf_bus_schedule_reset(bus_if);
}
void brcmf_detach(struct device *dev)
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -1892,6 +1892,7 @@ brcmf_pcie_probe(struct pci_dev *pdev, c
ret = -ENOMEM;
goto fail;
}
+ mutex_init(&bus->bus_reset_lock);
bus->msgbuf = kzalloc(sizeof(*bus->msgbuf), GFP_KERNEL);
if (!bus->msgbuf) {
ret = -ENOMEM;
@@ -1963,6 +1964,11 @@ brcmf_pcie_remove(struct pci_dev *pdev)
if (devinfo->ci)
brcmf_pcie_intr_disable(devinfo);
+ if (devinfo->irq_allocated)
+ synchronize_irq(pdev->irq);
+
+ brcmf_bus_cancel_reset_work(bus);
+
brcmf_detach(&pdev->dev);
brcmf_free(&pdev->dev);
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -4530,6 +4530,12 @@ fail:
return NULL;
}
+void brcmf_sdio_cancel_datawork(struct brcmf_sdio *bus)
+{
+ if (bus)
+ cancel_work_sync(&bus->datawork);
+}
+
/* Detach and free everything */
void brcmf_sdio_remove(struct brcmf_sdio *bus)
{
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -373,6 +373,7 @@ int brcmf_sdiod_remove(struct brcmf_sdio
struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev);
void brcmf_sdio_remove(struct brcmf_sdio *bus);
void brcmf_sdio_isr(struct brcmf_sdio *bus, bool in_isr);
+void brcmf_sdio_cancel_datawork(struct brcmf_sdio *bus);
void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, bool active);
void brcmf_sdio_wowl_config(struct device *dev, bool enabled);
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
@@ -1273,6 +1273,7 @@ static int brcmf_usb_probe_cb(struct brc
ret = -ENOMEM;
goto fail;
}
+ mutex_init(&bus->bus_reset_lock);
bus->dev = dev;
bus_pub->bus = bus;
@@ -1338,6 +1339,8 @@ brcmf_usb_disconnect_cb(struct brcmf_usb
return;
brcmf_dbg(USB, "Enter, bus_pub %p\n", devinfo);
+ brcmf_bus_cancel_reset_work(devinfo->bus_pub.bus);
+
brcmf_detach(devinfo->dev);
brcmf_free(devinfo->dev);
kfree(devinfo->bus_pub.bus);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 167/235] ALSA: seq: close a re-opened queue timer in the destructor
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (165 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 166/235] wifi: brcmfmac: drain bus_reset work on device removal Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 168/235] serial: 8250_mid: Remove unneeded test for ->setup() presence Greg Kroah-Hartman
` (70 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Norbert Szetei, Takashi Iwai,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Norbert Szetei <norbert@doyensec.com>
[ Upstream commit 2c4dc0ed50b05cd847a4b34b8cebf0775f19aeb9 ]
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>
[ replaced scoped_guard(spinlock_irq, &t->lock) with explicit spin_lock_irq()/spin_unlock_irq() pair since gnu89-compiled 5.15 rejects the macro's for-loop declarations ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
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
@@ -58,12 +58,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;
}
+
+ spin_lock_irq(&t->lock);
+ ti = t->timeri;
+ t->timeri = NULL;
+ spin_unlock_irq(&t->lock);
+ if (ti) {
+ snd_timer_close(ti);
+ snd_timer_instance_free(ti);
+ }
+
+ *tmr = NULL;
t->running = 0;
/* reset time */
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 168/235] serial: 8250_mid: Remove unneeded test for ->setup() presence
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (166 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 167/235] ALSA: seq: close a re-opened queue timer in the destructor Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 169/235] serial: 8250_mid: Fix NULL function pointer dereference on DNV/ICX-D/SNR platforms Greg Kroah-Hartman
` (69 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Andy Shevchenko, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
[ Upstream commit 324facd1ccb353a213ea2c2785604f2507f79297 ]
All supported platforms by this driver require ->setup() and ->exit().
Remove unneeded test for ->setup() presence.
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://lore.kernel.org/r/20220215101111.47250-1-andriy.shevchenko@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Stable-dep-of: 7fb13fd7e9a5 ("serial: 8250_mid: Fix NULL function pointer dereference on DNV/ICX-D/SNR platforms")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/tty/serial/8250/8250_mid.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
--- a/drivers/tty/serial/8250/8250_mid.c
+++ b/drivers/tty/serial/8250/8250_mid.c
@@ -319,11 +319,9 @@ static int mid8250_probe(struct pci_dev
if (!uart.port.membase)
return -ENOMEM;
- if (mid->board->setup) {
- ret = mid->board->setup(mid, &uart.port);
- if (ret)
- return ret;
- }
+ ret = mid->board->setup(mid, &uart.port);
+ if (ret)
+ return ret;
ret = mid8250_dma_setup(mid, &uart);
if (ret)
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 169/235] serial: 8250_mid: Fix NULL function pointer dereference on DNV/ICX-D/SNR platforms
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (167 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 168/235] serial: 8250_mid: Remove unneeded test for ->setup() presence Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 170/235] mptcp: only set DATA_FIN when a mapping is present Greg Kroah-Hartman
` (68 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, stable, Andy Shevchenko,
Jiangshan Yi, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiangshan Yi <yijiangshan@kylinos.cn>
[ Upstream commit 7fb13fd7e9a59a37cd911efff83abe19e3ee029d ]
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: Sasha Levin <sashal@kernel.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
@@ -319,9 +319,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)
@@ -337,7 +339,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;
}
@@ -347,7 +350,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] 239+ messages in thread
* [PATCH 5.10 170/235] mptcp: only set DATA_FIN when a mapping is present
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (168 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 169/235] serial: 8250_mid: Fix NULL function pointer dereference on DNV/ICX-D/SNR platforms Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 171/235] sc16is7xx: Properly resume TX after stop Greg Kroah-Hartman
` (67 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Paolo Abeni, Michael Bommarito,
Matthieu Baerts (NGI0), Jakub Kicinski, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <michael.bommarito@gmail.com>
[ Upstream commit b2ff91b752b0d85e8815e7f44fd85205c4268094 ]
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: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/mptcp/options.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
--- a/net/mptcp/options.c
+++ b/net/mptcp/options.c
@@ -142,17 +142,11 @@ static void mptcp_parse_option(const str
*/
mp_opt->mpc_map = 0;
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) {
@@ -163,12 +157,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);
+
/* RFC 6824, Section 3.3:
* If a checksum is present, but its use had
* not been negotiated in the MP_CAPABLE handshake,
@@ -306,6 +306,7 @@ void mptcp_get_options(const struct sk_b
mp_opt->port = 0;
mp_opt->rm_addr = 0;
mp_opt->dss = 0;
+ mp_opt->data_fin = 0;
length = (th->doff * 4) - sizeof(struct tcphdr);
ptr = (const unsigned char *)(th + 1);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 171/235] sc16is7xx: Properly resume TX after stop
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (169 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 170/235] mptcp: only set DATA_FIN when a mapping is present Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 172/235] serial: sc16is7xx: Fill in rs485_supported Greg Kroah-Hartman
` (66 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Tomasz Moń, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tomasz Moń <tomasz.mon@camlingroup.com>
[ Upstream commit cc4c1d05eb10c3ad4c6315f1897bc56b1e7429aa ]
sc16is7xx_stop_tx() clears THRI bit and thus disables THRI interrupt.
This makes it possible for transmission to cease indefinitely when more
than 64 characters are being sent.
The sc16is7xx_handle_tx() call executed by sc16is7xx_tx_proc() can send
up to FIFO length (64) characters. If more characters are written to the
output buffer, then the THRI interrupt is needed.
Solve the issue by enabling THRI interrupt in sc16is7xx_tx_proc().
Signed-off-by: Tomasz Moń <tomasz.mon@camlingroup.com>
Link: https://lore.kernel.org/r/20220301060332.2561851-2-tomasz.mon@camlingroup.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Stable-dep-of: af071d9e07e5 ("serial: sc16is7xx: implement gpio get_direction() callback")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/tty/serial/sc16is7xx.c | 47 +++++++++++++++++++++++++++++++++++------
1 file changed, 41 insertions(+), 6 deletions(-)
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -307,7 +307,8 @@ struct sc16is7xx_devtype {
struct sc16is7xx_one_config {
unsigned int flags;
- u8 ier_clear;
+ u8 ier_mask;
+ u8 ier_val;
};
struct sc16is7xx_one {
@@ -341,6 +342,9 @@ static struct uart_driver sc16is7xx_uart
.nr = SC16IS7XX_MAX_DEVS,
};
+static void sc16is7xx_ier_set(struct uart_port *port, u8 bit);
+static void sc16is7xx_stop_tx(struct uart_port *port);
+
#define to_sc16is7xx_port(p,e) ((container_of((p), struct sc16is7xx_port, e)))
#define to_sc16is7xx_one(p,e) ((container_of((p), struct sc16is7xx_one, e)))
@@ -650,6 +654,7 @@ static void sc16is7xx_handle_tx(struct u
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
struct circ_buf *xmit = &port->state->xmit;
unsigned int txlen, to_send, i;
+ unsigned long flags;
if (unlikely(port->x_char)) {
sc16is7xx_port_write(port, SC16IS7XX_THR_REG, port->x_char);
@@ -658,8 +663,12 @@ static void sc16is7xx_handle_tx(struct u
return;
}
- if (uart_circ_empty(xmit) || uart_tx_stopped(port))
+ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+ spin_lock_irqsave(&port->lock, flags);
+ sc16is7xx_stop_tx(port);
+ spin_unlock_irqrestore(&port->lock, flags);
return;
+ }
/* Get length of data pending in circular buffer */
to_send = uart_circ_chars_pending(xmit);
@@ -686,8 +695,13 @@ static void sc16is7xx_handle_tx(struct u
sc16is7xx_fifo_write(port, to_send);
}
+ spin_lock_irqsave(&port->lock, flags);
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
+
+ if (uart_circ_empty(xmit))
+ sc16is7xx_stop_tx(port);
+ spin_unlock_irqrestore(&port->lock, flags);
}
static bool sc16is7xx_port_irq(struct sc16is7xx_port *s, int portno)
@@ -762,6 +776,7 @@ static void sc16is7xx_tx_proc(struct kth
{
struct uart_port *port = &(to_sc16is7xx_one(ws, tx_work)->port);
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
+ unsigned long flags;
if ((port->rs485.flags & SER_RS485_ENABLED) &&
(port->rs485.delay_rts_before_send > 0))
@@ -770,6 +785,10 @@ static void sc16is7xx_tx_proc(struct kth
mutex_lock(&s->efr_lock);
sc16is7xx_handle_tx(port);
mutex_unlock(&s->efr_lock);
+
+ spin_lock_irqsave(&port->lock, flags);
+ sc16is7xx_ier_set(port, SC16IS7XX_IER_THRI_BIT);
+ spin_unlock_irqrestore(&port->lock, flags);
}
static void sc16is7xx_reconf_rs485(struct uart_port *port)
@@ -819,7 +838,7 @@ static void sc16is7xx_reg_proc(struct kt
}
if (config.flags & SC16IS7XX_RECONF_IER)
sc16is7xx_port_update(&one->port, SC16IS7XX_IER_REG,
- config.ier_clear, 0);
+ config.ier_mask, config.ier_val);
if (config.flags & SC16IS7XX_RECONF_RS485)
sc16is7xx_reconf_rs485(&one->port);
@@ -830,8 +849,24 @@ static void sc16is7xx_ier_clear(struct u
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
+ lockdep_assert_held_once(&port->lock);
+
+ one->config.flags |= SC16IS7XX_RECONF_IER;
+ one->config.ier_mask |= bit;
+ one->config.ier_val &= ~bit;
+ kthread_queue_work(&s->kworker, &one->reg_work);
+}
+
+static void sc16is7xx_ier_set(struct uart_port *port, u8 bit)
+{
+ struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
+ struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
+
+ lockdep_assert_held_once(&port->lock);
+
one->config.flags |= SC16IS7XX_RECONF_IER;
- one->config.ier_clear |= bit;
+ one->config.ier_mask |= bit;
+ one->config.ier_val |= bit;
kthread_queue_work(&s->kworker, &one->reg_work);
}
@@ -1059,8 +1094,8 @@ static int sc16is7xx_startup(struct uart
SC16IS7XX_EFCR_TXDISABLE_BIT,
0);
- /* Enable RX, TX interrupts */
- val = SC16IS7XX_IER_RDI_BIT | SC16IS7XX_IER_THRI_BIT;
+ /* Enable RX interrupt */
+ val = SC16IS7XX_IER_RDI_BIT;
sc16is7xx_port_write(port, SC16IS7XX_IER_REG, val);
return 0;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 172/235] serial: sc16is7xx: Fill in rs485_supported
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (170 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 171/235] sc16is7xx: Properly resume TX after stop Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 173/235] serial: sc16is7xx: remove obsolete out_thread label Greg Kroah-Hartman
` (65 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Ilpo Järvinen, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
[ Upstream commit 267913ecf73745ca3e8fc8282671b0b4f24df5fe ]
Add information on supported serial_rs485 features.
This driver does not support delay_rts_after_send but the pre-existing
behavior is to return -EINVAL if delay_rts_after_send is non-zero. In
contrast, other drivers that do not support delay_rts_after_send either
zero delay_rts_after_send or do not care (leave the inaccurate value).
As changing this would cause userspace visible impact, the change is
not attempted here. But perhaps it should be still tried (maybe nobody
finds that kind of API oddity significant)?
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Link: https://lore.kernel.org/r/20220606100433.13793-21-ilpo.jarvinen@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Stable-dep-of: af071d9e07e5 ("serial: sc16is7xx: implement gpio get_direction() callback")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/tty/serial/sc16is7xx.c | 7 +++++++
1 file changed, 7 insertions(+)
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -1239,6 +1239,12 @@ static int sc16is7xx_gpio_direction_outp
}
#endif
+static const struct serial_rs485 sc16is7xx_rs485_supported = {
+ .flags = SER_RS485_ENABLED | SER_RS485_RTS_AFTER_SEND,
+ .delay_rts_before_send = 1,
+ .delay_rts_after_send = 1, /* Not supported but keep returning -EINVAL */
+};
+
static int sc16is7xx_probe(struct device *dev,
const struct sc16is7xx_devtype *devtype,
struct regmap *regmap, int irq)
@@ -1326,6 +1332,7 @@ static int sc16is7xx_probe(struct device
s->p[i].port.iotype = UPIO_PORT;
s->p[i].port.uartclk = freq;
s->p[i].port.rs485_config = sc16is7xx_config_rs485;
+ s->p[i].port.rs485_supported = &sc16is7xx_rs485_supported;
s->p[i].port.ops = &sc16is7xx_ops;
s->p[i].port.line = sc16is7xx_alloc_line();
if (s->p[i].port.line >= SC16IS7XX_MAX_DEVS) {
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 173/235] serial: sc16is7xx: remove obsolete out_thread label
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (171 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 172/235] serial: sc16is7xx: Fill in rs485_supported Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 174/235] serial: sc16is7xx: fix regression with GPIO configuration Greg Kroah-Hartman
` (64 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Hugo Villeneuve, Lech Perczak,
Andy Shevchenko, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
[ Upstream commit dabc54a45711fe77674a6c0348231e00e66bd567 ]
Commit c8f71b49ee4d ("serial: sc16is7xx: setup GPIO controller later
in probe") moved GPIO setup code later in probe function. Doing so
also required to move ports cleanup code (out_ports label) after the
GPIO cleanup code.
After these moves, the out_thread label becomes misplaced and makes
part of the cleanup code illogical.
This patch remove the now obsolete out_thread label and make GPIO
setup code jump to out_ports label if it fails.
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Reviewed-by: Lech Perczak <lech.perczak@camlingroup.com>
Tested-by: Lech Perczak <lech.perczak@camlingroup.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Link: https://lore.kernel.org/r/20230807214556.540627-3-hugo@hugovil.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Stable-dep-of: af071d9e07e5 ("serial: sc16is7xx: implement gpio get_direction() callback")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/tty/serial/sc16is7xx.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -1397,7 +1397,7 @@ static int sc16is7xx_probe(struct device
s->gpio.can_sleep = 1;
ret = gpiochip_add_data(&s->gpio, s);
if (ret)
- goto out_thread;
+ goto out_ports;
}
#endif
@@ -1423,8 +1423,6 @@ static int sc16is7xx_probe(struct device
#ifdef CONFIG_GPIOLIB
if (devtype->nr_gpio)
gpiochip_remove(&s->gpio);
-
-out_thread:
#endif
out_ports:
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 174/235] serial: sc16is7xx: fix regression with GPIO configuration
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (172 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 173/235] serial: sc16is7xx: remove obsolete out_thread label Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 175/235] serial: sc16is7xx: implement gpio get_direction() callback Greg Kroah-Hartman
` (63 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Hugo Villeneuve, Andy Shevchenko,
Lech Perczak, Rob Herring, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
[ Upstream commit 0499942928341d572a42199580433c2b0725211e ]
Commit 679875d1d880 ("sc16is7xx: Separate GPIOs from modem control lines")
and commit 21144bab4f11 ("sc16is7xx: Handle modem status lines")
changed the function of the GPIOs pins to act as modem control
lines without any possibility of selecting GPIO function.
As a consequence, applications that depends on GPIO lines configured
by default as GPIO pins no longer work as expected.
Also, the change to select modem control lines function was done only
for channel A of dual UART variants (752/762). This was not documented
in the log message.
Allow to specify GPIO or modem control line function in the device
tree, and for each of the ports (A or B).
Do so by using the new device-tree property named
"nxp,modem-control-line-ports" (property added in separate patch).
When registering GPIO chip controller, mask-out GPIO pins declared as
modem control lines according to this new DT property.
Fixes: 679875d1d880 ("sc16is7xx: Separate GPIOs from modem control lines")
Fixes: 21144bab4f11 ("sc16is7xx: Handle modem status lines")
Cc: stable@vger.kernel.org
Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Reviewed-by: Lech Perczak <lech.perczak@camlingroup.com>
Tested-by: Lech Perczak <lech.perczak@camlingroup.com>
Acked-by: Rob Herring <robh@kernel.org>
Link: https://lore.kernel.org/r/20230807214556.540627-5-hugo@hugovil.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Stable-dep-of: af071d9e07e5 ("serial: sc16is7xx: implement gpio get_direction() callback")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/tty/serial/sc16is7xx.c | 124 ++++++++++++++++++++++++++++++++++-------
1 file changed, 105 insertions(+), 19 deletions(-)
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -237,7 +237,8 @@
/* IOControl register bits (Only 750/760) */
#define SC16IS7XX_IOCONTROL_LATCH_BIT (1 << 0) /* Enable input latching */
-#define SC16IS7XX_IOCONTROL_MODEM_BIT (1 << 1) /* Enable GPIO[7:4] as modem pins */
+#define SC16IS7XX_IOCONTROL_MODEM_A_BIT (1 << 1) /* Enable GPIO[7:4] as modem A pins */
+#define SC16IS7XX_IOCONTROL_MODEM_B_BIT (1 << 2) /* Enable GPIO[3:0] as modem B pins */
#define SC16IS7XX_IOCONTROL_SRESET_BIT (1 << 3) /* Software Reset */
/* EFCR register bits */
@@ -294,6 +295,7 @@
/* Misc definitions */
#define SC16IS7XX_FIFO_SIZE (64)
#define SC16IS7XX_REG_SHIFT 2
+#define SC16IS7XX_GPIOS_PER_BANK 4
struct sc16is7xx_devtype {
char name[10];
@@ -326,7 +328,9 @@ struct sc16is7xx_port {
struct clk *clk;
#ifdef CONFIG_GPIOLIB
struct gpio_chip gpio;
+ unsigned long gpio_valid_mask;
#endif
+ u8 mctrl_mask;
unsigned char buf[SC16IS7XX_FIFO_SIZE];
struct kthread_worker kworker;
struct task_struct *kworker_task;
@@ -1237,8 +1241,98 @@ static int sc16is7xx_gpio_direction_outp
return 0;
}
+
+static int sc16is7xx_gpio_init_valid_mask(struct gpio_chip *chip,
+ unsigned long *valid_mask,
+ unsigned int ngpios)
+{
+ struct sc16is7xx_port *s = gpiochip_get_data(chip);
+
+ *valid_mask = s->gpio_valid_mask;
+
+ return 0;
+}
+
+static int sc16is7xx_setup_gpio_chip(struct sc16is7xx_port *s)
+{
+ struct device *dev = s->p[0].port.dev;
+
+ if (!s->devtype->nr_gpio)
+ return 0;
+
+ switch (s->mctrl_mask) {
+ case 0:
+ s->gpio_valid_mask = GENMASK(7, 0);
+ break;
+ case SC16IS7XX_IOCONTROL_MODEM_A_BIT:
+ s->gpio_valid_mask = GENMASK(3, 0);
+ break;
+ case SC16IS7XX_IOCONTROL_MODEM_B_BIT:
+ s->gpio_valid_mask = GENMASK(7, 4);
+ break;
+ default:
+ break;
+ }
+
+ if (s->gpio_valid_mask == 0)
+ return 0;
+
+ s->gpio.owner = THIS_MODULE;
+ s->gpio.parent = dev;
+ s->gpio.label = dev_name(dev);
+ s->gpio.init_valid_mask = sc16is7xx_gpio_init_valid_mask;
+ s->gpio.direction_input = sc16is7xx_gpio_direction_input;
+ s->gpio.get = sc16is7xx_gpio_get;
+ s->gpio.direction_output = sc16is7xx_gpio_direction_output;
+ s->gpio.set = sc16is7xx_gpio_set;
+ s->gpio.base = -1;
+ s->gpio.ngpio = s->devtype->nr_gpio;
+ s->gpio.can_sleep = 1;
+
+ return gpiochip_add_data(&s->gpio, s);
+}
#endif
+/*
+ * Configure ports designated to operate as modem control lines.
+ */
+static int sc16is7xx_setup_mctrl_ports(struct sc16is7xx_port *s)
+{
+ int i;
+ int ret;
+ int count;
+ u32 mctrl_port[2];
+ struct device *dev = s->p[0].port.dev;
+
+ count = device_property_count_u32(dev, "nxp,modem-control-line-ports");
+ if (count < 0 || count > ARRAY_SIZE(mctrl_port))
+ return 0;
+
+ ret = device_property_read_u32_array(dev, "nxp,modem-control-line-ports",
+ mctrl_port, count);
+ if (ret)
+ return ret;
+
+ s->mctrl_mask = 0;
+
+ for (i = 0; i < count; i++) {
+ /* Use GPIO lines as modem control lines */
+ if (mctrl_port[i] == 0)
+ s->mctrl_mask |= SC16IS7XX_IOCONTROL_MODEM_A_BIT;
+ else if (mctrl_port[i] == 1)
+ s->mctrl_mask |= SC16IS7XX_IOCONTROL_MODEM_B_BIT;
+ }
+
+ if (s->mctrl_mask)
+ regmap_update_bits(
+ s->regmap,
+ SC16IS7XX_IOCONTROL_REG << SC16IS7XX_REG_SHIFT,
+ SC16IS7XX_IOCONTROL_MODEM_A_BIT |
+ SC16IS7XX_IOCONTROL_MODEM_B_BIT, s->mctrl_mask);
+
+ return 0;
+}
+
static const struct serial_rs485 sc16is7xx_rs485_supported = {
.flags = SER_RS485_ENABLED | SER_RS485_RTS_AFTER_SEND,
.delay_rts_before_send = 1,
@@ -1346,6 +1440,7 @@ static int sc16is7xx_probe(struct device
sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_EFCR_REG,
SC16IS7XX_EFCR_RXDISABLE_BIT |
SC16IS7XX_EFCR_TXDISABLE_BIT);
+
/* Initialize kthread work structs */
kthread_init_work(&s->p[i].tx_work, sc16is7xx_tx_proc);
kthread_init_work(&s->p[i].reg_work, sc16is7xx_reg_proc);
@@ -1382,23 +1477,14 @@ static int sc16is7xx_probe(struct device
s->p[u].irda_mode = true;
}
+ ret = sc16is7xx_setup_mctrl_ports(s);
+ if (ret)
+ goto out_ports;
+
#ifdef CONFIG_GPIOLIB
- if (devtype->nr_gpio) {
- /* Setup GPIO cotroller */
- s->gpio.owner = THIS_MODULE;
- s->gpio.parent = dev;
- s->gpio.label = dev_name(dev);
- s->gpio.direction_input = sc16is7xx_gpio_direction_input;
- s->gpio.get = sc16is7xx_gpio_get;
- s->gpio.direction_output = sc16is7xx_gpio_direction_output;
- s->gpio.set = sc16is7xx_gpio_set;
- s->gpio.base = -1;
- s->gpio.ngpio = devtype->nr_gpio;
- s->gpio.can_sleep = 1;
- ret = gpiochip_add_data(&s->gpio, s);
- if (ret)
- goto out_ports;
- }
+ ret = sc16is7xx_setup_gpio_chip(s);
+ if (ret)
+ goto out_ports;
#endif
/*
@@ -1421,7 +1507,7 @@ static int sc16is7xx_probe(struct device
return 0;
#ifdef CONFIG_GPIOLIB
- if (devtype->nr_gpio)
+ if (s->gpio_valid_mask)
gpiochip_remove(&s->gpio);
#endif
@@ -1446,7 +1532,7 @@ static int sc16is7xx_remove(struct devic
int i;
#ifdef CONFIG_GPIOLIB
- if (s->devtype->nr_gpio)
+ if (s->gpio_valid_mask)
gpiochip_remove(&s->gpio);
#endif
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 175/235] serial: sc16is7xx: implement gpio get_direction() callback
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (173 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 174/235] serial: sc16is7xx: fix regression with GPIO configuration Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 176/235] mptcp: fix subflow accounting on close Greg Kroah-Hartman
` (62 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, stable, Hugo Villeneuve,
Bartosz Golaszewski, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
[ Upstream commit af071d9e07e57cfff239e8d09d2f3b05ebc9c667 ]
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: Sasha Levin <sashal@kernel.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
@@ -1204,6 +1204,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)
{
@@ -1281,6 +1292,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] 239+ messages in thread
* [PATCH 5.10 176/235] mptcp: fix subflow accounting on close
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (174 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 175/235] serial: sc16is7xx: implement gpio get_direction() callback Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 177/235] mptcp: decrement subflows counter on failed passive join Greg Kroah-Hartman
` (61 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Paolo Abeni, Mat Martineau,
Jakub Kicinski, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paolo Abeni <pabeni@redhat.com>
[ Upstream commit 95d686517884a403412b000361cee2b08b2ed1e6 ]
If the PM closes a fully established MPJ subflow or the subflow
creation errors out in it's early stage the subflows counter is
not bumped accordingly.
This change adds the missing accounting, additionally taking care
of updating accordingly the 'accept_subflow' flag.
Fixes: a88c9e496937 ("mptcp: do not block subflows creation on errors")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: f3ca0ee2cc30 ("mptcp: decrement subflows counter on failed passive join")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/mptcp/protocol.h | 14 ++++++++++++++
net/mptcp/subflow.c | 12 +++++++++---
2 files changed, 23 insertions(+), 3 deletions(-)
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -498,6 +498,20 @@ void mptcp_pm_nl_rm_subflow_received(str
int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct sock_common *skc);
bool mptcp_pm_nl_is_backup(struct mptcp_sock *msk, struct mptcp_addr_info *skc);
+/* called under PM lock */
+static inline void __mptcp_pm_close_subflow(struct mptcp_sock *msk)
+{
+ if (--msk->pm.subflows < msk->pm.subflows_max)
+ WRITE_ONCE(msk->pm.accept_subflow, true);
+}
+
+static inline void mptcp_pm_close_subflow(struct mptcp_sock *msk)
+{
+ spin_lock_bh(&msk->pm.lock);
+ __mptcp_pm_close_subflow(msk);
+ spin_unlock_bh(&msk->pm.lock);
+}
+
static inline struct mptcp_ext *mptcp_get_ext(struct sk_buff *skb)
{
return (struct mptcp_ext *)skb_ext_find(skb, SKB_EXT_MPTCP);
--- a/net/mptcp/subflow.c
+++ b/net/mptcp/subflow.c
@@ -1122,18 +1122,18 @@ int __mptcp_subflow_connect(struct sock
struct sockaddr_storage addr;
int remote_id = remote->id;
int local_id = loc->id;
+ int err = -ENOTCONN;
struct socket *sf;
struct sock *ssk;
u32 remote_token;
int addrlen;
- int err;
if (!mptcp_is_fully_established(sk))
- return -ENOTCONN;
+ goto err_out;
err = mptcp_subflow_create_socket(sk, &sf);
if (err)
- return err;
+ goto err_out;
ssk = sf->sk;
subflow = mptcp_subflow_ctx(ssk);
@@ -1187,6 +1187,12 @@ int __mptcp_subflow_connect(struct sock
failed:
sock_release(sf);
+
+err_out:
+ /* we account subflows before the creation, and this failures will not
+ * be caught by sk_state_change()
+ */
+ mptcp_pm_close_subflow(msk);
return err;
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 177/235] mptcp: decrement subflows counter on failed passive join
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (175 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 176/235] mptcp: fix subflow accounting on close Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 178/235] sctp: avoid auth_enable sysctl UAF during netns teardown Greg Kroah-Hartman
` (60 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Chenguang Zhao,
Matthieu Baerts (NGI0), Jakub Kicinski, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chenguang Zhao <zhaochenguang@kylinos.cn>
[ Upstream commit f3ca0ee2cc308e33896536789cbc5f3a12ca7b30 ]
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: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/mptcp/protocol.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -2663,8 +2663,10 @@ bool mptcp_finish_join(struct sock *sk)
if (ret && !WARN_ON_ONCE(!list_empty(&subflow->node)))
list_add_tail(&subflow->node, &msk->join_list);
spin_unlock_bh(&msk->join_list_lock);
- if (!ret)
+ if (!ret) {
+ mptcp_pm_close_subflow(msk);
return false;
+ }
/* attach to msk socket only after we are sure he will deal with us
* at close time
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 178/235] sctp: avoid auth_enable sysctl UAF during netns teardown
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (176 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 177/235] mptcp: decrement subflows counter on failed passive join Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 179/235] ceph: avoid fs reclaim while using current->journal_info Greg Kroah-Hartman
` (59 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 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,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhiling Zou <roxy520tt@gmail.com>
[ Upstream commit f8d5e7846025f4ab15a461235f8ebae9094a361a ]
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>
[ dropped the missing `l3mdev_accept` context block and kept 6.1's non-const `struct ctl_table *table` declaration ]
Signed-off-by: Sasha Levin <sashal@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
@@ -1286,10 +1286,6 @@ static int __net_init sctp_defaults_init
/* Initialize maximum autoclose timeout. */
net->sctp.max_autoclose = INT_MAX / HZ;
- status = sctp_sysctl_net_register(net);
- if (status)
- goto err_sysctl_register;
-
/* Allocate and initialise sctp mibs. */
status = init_sctp_mibs(net);
if (status)
@@ -1323,8 +1319,6 @@ err_init_proc:
cleanup_sctp_mibs(net);
#endif
err_init_mibs:
- sctp_sysctl_net_unregister(net);
-err_sysctl_register:
return status;
}
@@ -1339,7 +1333,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 = {
@@ -1353,16 +1346,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
@@ -515,11 +515,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;
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] 239+ messages in thread
* [PATCH 5.10 179/235] ceph: avoid fs reclaim while using current->journal_info
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (177 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 178/235] sctp: avoid auth_enable sysctl UAF during netns teardown Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 180/235] libceph: Amend checking to fix `make W=1` build breakage Greg Kroah-Hartman
` (58 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Max Kellermann, Viacheslav Dubeyko,
Xiubo Li, Ilya Dryomov, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Max Kellermann <max.kellermann@ionos.com>
[ Upstream commit 5b602344a49e039e792ce5a8923bcc61412ee134 ]
handle_reply() stores a `ceph_mds_request` pointer in
`current->journal_info` while filling the inode and dentry cache from
an MDS reply.
An allocation in this section can enter direct reclaim and prune
dentries from another filesystem. If this dirties an ext4 inode, ext4
starts a JBD2 transaction. JBD2 interprets the Ceph request in
`current->journal_info` as a journal handle and dereferences the
request's `r_tid` as `h_transaction`, causing a kernel crash, e.g.:
Unable to handle kernel paging request at virtual address 00000000077b4818
[...]
Internal error: Oops: 0000000096000004 [#1] SMP
Modules linked in:
CPU: 6 UID: 0 PID: 2699135 Comm: kworker/6:3 Tainted: G W 6.18.38-i3 #1113 NONE
[...]
Workqueue: ceph-msgr ceph_con_workfn
pstate: 80400009 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
pc : jbd2__journal_start+0x2c/0x208
lr : __ext4_journal_start_sb+0x100/0x178
[...]
Call trace:
jbd2__journal_start+0x2c/0x208 (P)
__ext4_journal_start_sb+0x100/0x178
ext4_dirty_inode+0x3c/0x90
__mark_inode_dirty+0x58/0x400
iput.part.0+0x2b0/0x370
iput+0x18/0x30
dentry_unlink_inode+0xc0/0x158
__dentry_kill+0x80/0x250
shrink_dentry_list+0x90/0x130
prune_dcache_sb+0x60/0x98
super_cache_scan+0xe8/0x190
do_shrink_slab+0x174/0x388
shrink_slab+0xd8/0x4c0
shrink_node+0x31c/0x908
do_try_to_free_pages+0xd0/0x508
try_to_free_pages+0x11c/0x238
__alloc_frozen_pages_noprof+0x4d0/0xdd0
__folio_alloc_noprof+0x18/0x70
__filemap_get_folio+0x248/0x440
ceph_readdir_prepopulate+0x570/0x9e8
mds_dispatch+0x1424/0x1ba0
ceph_con_process_message+0x74/0xa0
ceph_con_v1_try_read+0x3a0/0x1510
ceph_con_workfn+0x260/0x460
Enter a scoped NOFS allocation context and leave it after clearing
`journal_info`. This prevents filesystem reclaim from recursing into
another filesystem while the field contains Ceph-private data.
Cc: stable@vger.kernel.org
Fixes: 315f24088048 ("ceph: fix security xattr deadlock")
Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
Reviewed-by: Viacheslav Dubeyko <slava@dubeyko.com>
Reviewed-by: Xiubo Li <xiubo.li@clyso.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/ceph/mds_client.c | 11 +++++++++++
1 file changed, 11 insertions(+)
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -6,6 +6,7 @@
#include <linux/slab.h>
#include <linux/gfp.h>
#include <linux/sched.h>
+#include <linux/sched/mm.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/ratelimit.h>
@@ -3126,6 +3127,7 @@ static void handle_reply(struct ceph_mds
struct ceph_mds_reply_head *head = msg->front.iov_base;
struct ceph_mds_reply_info_parsed *rinfo; /* parsed reply info */
struct ceph_snap_realm *realm;
+ unsigned int nofs_flags;
u64 tid;
int err, result;
int mds = session->s_mds;
@@ -3258,6 +3260,14 @@ static void handle_reply(struct ceph_mds
/* insert trace into our cache */
mutex_lock(&req->r_fill_mutex);
+
+ /* disable fs reclaim while we are using current->journal_info
+ * for our own purposes, or else shrinkers of other
+ * filesystems might dereference this pointer as a different
+ * type
+ */
+ nofs_flags = memalloc_nofs_save();
+
current->journal_info = req;
err = ceph_fill_trace(mdsc->fsc->sb, req);
if (err == 0) {
@@ -3266,6 +3276,7 @@ static void handle_reply(struct ceph_mds
ceph_readdir_prepopulate(req, req->r_session);
}
current->journal_info = NULL;
+ memalloc_nofs_restore(nofs_flags);
mutex_unlock(&req->r_fill_mutex);
up_read(&mdsc->snap_rwsem);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 180/235] libceph: Amend checking to fix `make W=1` build breakage
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (178 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 179/235] ceph: avoid fs reclaim while using current->journal_info Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 181/235] libceph: bound pg_{temp,upmap,upmap_items} length to CEPH_PG_MAX_SIZE Greg Kroah-Hartman
` (57 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Andy Shevchenko, Viacheslav Dubeyko,
Ilya Dryomov, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
[ Upstream commit 04d8712b079327409b09dee628378f9583e2e035 ]
In a few cases the code compares 32-bit value to a SIZE_MAX derived
constant which is much higher than that value on 64-bit platforms,
Clang, in particular, is not happy about this
net/ceph/osdmap.c:1441:10: error: result of comparison of constant 4611686018427387891 with expression of type 'u32' (aka 'unsigned int') is always false [-Werror,-Wtautological-constant-out-of-range-compare]
1441 | if (len > (SIZE_MAX - sizeof(*pg)) / sizeof(u32))
| ~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
net/ceph/osdmap.c:1624:10: error: result of comparison of constant 2305843009213693945 with expression of type 'u32' (aka 'unsigned int') is always false [-Werror,-Wtautological-constant-out-of-range-compare]
1624 | if (len > (SIZE_MAX - sizeof(*pg)) / (2 * sizeof(u32)))
| ~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Fix this by casting to size_t. Note, that possible replacement of SIZE_MAX
by U32_MAX may lead to the behaviour changes on the corner cases.
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Stable-dep-of: 9f00f9cf2be2 ("libceph: bound pg_{temp,upmap,upmap_items} length to CEPH_PG_MAX_SIZE")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ceph/osdmap.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/net/ceph/osdmap.c
+++ b/net/ceph/osdmap.c
@@ -1424,7 +1424,7 @@ static struct ceph_pg_mapping *__decode_
ceph_decode_32_safe(p, end, len, e_inval);
if (len == 0 && incremental)
return NULL; /* new_pg_temp: [] to remove */
- if (len > (SIZE_MAX - sizeof(*pg)) / sizeof(u32))
+ if ((size_t)len > (SIZE_MAX - sizeof(*pg)) / sizeof(u32))
return ERR_PTR(-EINVAL);
ceph_decode_need(p, end, len * sizeof(u32), e_inval);
@@ -1607,7 +1607,7 @@ static struct ceph_pg_mapping *__decode_
u32 len, i;
ceph_decode_32_safe(p, end, len, e_inval);
- if (len > (SIZE_MAX - sizeof(*pg)) / (2 * sizeof(u32)))
+ if ((size_t)len > (SIZE_MAX - sizeof(*pg)) / (2 * sizeof(u32)))
return ERR_PTR(-EINVAL);
ceph_decode_need(p, end, 2 * len * sizeof(u32), e_inval);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 181/235] libceph: bound pg_{temp,upmap,upmap_items} length to CEPH_PG_MAX_SIZE
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (179 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 180/235] libceph: Amend checking to fix `make W=1` build breakage Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 182/235] libceph: fix two unsafe bare decodes in decode_lockers() Greg Kroah-Hartman
` (56 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Weiming Shi, Xiang Mei, Alex Markuze,
Ilya Dryomov, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei <xmei5@asu.edu>
[ Upstream commit 9f00f9cf2be293efe899db67dc5272e3a9c62717 ]
__decode_pg_temp() decodes an user-controlled length but only rejects
values large enough to overflow the allocation; it does not bound it to
CEPH_PG_MAX_SIZE. The helper backs both pg_temp and pg_upmap decoding, and
apply_upmap()/get_temp_osds() later copy the decoded list into the fixed-size
on-stack array struct ceph_osds.osds[CEPH_PG_MAX_SIZE]. A monitor that sends
an OSDMap with a pg_temp/pg_upmap entry longer than 32 thus causes a stack
out-of-bounds write.
An OSD set for a single PG can never exceed CEPH_PG_MAX_SIZE, so reject longer
entries at decode time. The bound is well below the old overflow threshold, so
it also covers the allocation-size overflow the previous check guarded against.
BUG: KASAN: stack-out-of-bounds in ceph_pg_to_up_acting_osds
Write of size 4 ... by task exploit
kasan_report (mm/kasan/report.c:595)
ceph_pg_to_up_acting_osds (net/ceph/osdmap.c:2617 net/ceph/osdmap.c:2833)
calc_target (net/ceph/osd_client.c:1638)
__submit_request (net/ceph/osd_client.c:2394)
ceph_osdc_start_request (net/ceph/osd_client.c:2490)
ceph_osdc_call (net/ceph/osd_client.c:5164)
rbd_dev_image_probe (drivers/block/rbd.c:6899)
do_rbd_add (drivers/block/rbd.c:7138)
...
kernel BUG at net/ceph/osdmap.c:2670!
[ idryomov: do the same in __decode_pg_upmap_items() ]
Cc: stable@vger.kernel.org
Fixes: a303bb0e5834 ("libceph: introduce and switch to decode_pg_mapping()")
Reported-by: Weiming Shi <bestswngs@gmail.com>
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Xiang Mei <xmei5@asu.edu>
Reviewed-by: Alex Markuze <amarkuze@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ceph/osdmap.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/net/ceph/osdmap.c
+++ b/net/ceph/osdmap.c
@@ -1424,7 +1424,7 @@ static struct ceph_pg_mapping *__decode_
ceph_decode_32_safe(p, end, len, e_inval);
if (len == 0 && incremental)
return NULL; /* new_pg_temp: [] to remove */
- if ((size_t)len > (SIZE_MAX - sizeof(*pg)) / sizeof(u32))
+ if (len > CEPH_PG_MAX_SIZE)
return ERR_PTR(-EINVAL);
ceph_decode_need(p, end, len * sizeof(u32), e_inval);
@@ -1607,7 +1607,7 @@ static struct ceph_pg_mapping *__decode_
u32 len, i;
ceph_decode_32_safe(p, end, len, e_inval);
- if ((size_t)len > (SIZE_MAX - sizeof(*pg)) / (2 * sizeof(u32)))
+ if (len > CEPH_PG_MAX_SIZE)
return ERR_PTR(-EINVAL);
ceph_decode_need(p, end, 2 * len * sizeof(u32), e_inval);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 182/235] libceph: fix two unsafe bare decodes in decode_lockers()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (180 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 181/235] libceph: bound pg_{temp,upmap,upmap_items} length to CEPH_PG_MAX_SIZE Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 183/235] libceph: add doutc and *_client debug macros support Greg Kroah-Hartman
` (55 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Pavitra Jha, Viacheslav Dubeyko,
Ilya Dryomov, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pavitra Jha <jhapavitra98@gmail.com>
[ Upstream commit a109a556115271ca7896dcda7b4b7e45e156c227 ]
decode_lockers() in cls_lock_client.c contains two bare decode operations
that allow a malicious or compromised OSD to trigger slab-out-of-bounds
reads:
1. ceph_decode_32(p) at the num_lockers field has no preceding bounds
check. ceph_start_decoding() accepts struct_len=0 as valid -- the
internal ceph_decode_need(p, end, 0, bad) always passes -- so when an
OSD sends struct_len=0, ceph_start_decoding() returns success with
p == end. The immediately following bare ceph_decode_32(p) then reads
4 bytes past the validated buffer boundary. The garbage value is
passed directly to kzalloc_objs() as the locker count.
The sibling function decode_watchers() in osd_client.c already uses
ceph_decode_32_safe() after its own ceph_start_decoding() call.
decode_lockers() was the only site using the bare variant.
2. ceph_decode_8(p) after the decode_locker() loop has no preceding
bounds check. If an OSD crafts num_lockers such that the loop
advances p exactly to end, the subsequent bare ceph_decode_8(p) reads
one byte past the validated buffer boundary. The result is passed
directly into *type, which is used as a lock type discriminator by
callers, giving an OSD-controlled one-byte OOB read with direct
influence over the lock type field.
Fix both by replacing bare operations with their safe variants:
ceph_decode_32(p) -> ceph_decode_32_safe(p, end, *num_lockers,
err_inval)
ceph_decode_8(p) -> ceph_decode_8_safe(p, end, *type,
err_free_lockers)
The goto targets differ intentionally:
err_inval: is a new label returning -EINVAL directly. It is used for
the pre-allocation failure path where *lockers is not yet allocated
and must not be passed to ceph_free_lockers().
err_free_lockers: is the existing label. It is used for the
post-allocation failure path where *lockers is allocated and must
be freed.
ret is set to -EINVAL before ceph_decode_8_safe() so that
err_free_lockers returns the correct error code on bounds violation.
Without this, err_free_lockers would return a stale ret value (0 from
the successful decode_locker() loop), silently swallowing the error.
-EINVAL is correct for both failure paths. The data received from the
OSD is structurally malformed. -ENOMEM would misrepresent the failure
class to callers and to stable@ backporters triaging error paths.
Attacker model: a malicious or compromised OSD in a multi-tenant Ceph
deployment can trigger this against any kernel client that issues the
lock.get_info class method (e.g. during RBD exclusive lock acquisition).
[ idryomov: trim changelog, formatting ]
Cc: stable@vger.kernel.org
Fixes: d4ed4a530562 ("libceph: support for lock.lock_info")
Signed-off-by: Pavitra Jha <jhapavitra98@gmail.com>
Reviewed-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/ceph/cls_lock_client.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
--- a/net/ceph/cls_lock_client.c
+++ b/net/ceph/cls_lock_client.c
@@ -298,7 +298,7 @@ static int decode_lockers(void **p, void
if (ret)
return ret;
- *num_lockers = ceph_decode_32(p);
+ ceph_decode_32_safe(p, end, *num_lockers, err_inval);
*lockers = kcalloc(*num_lockers, sizeof(**lockers), GFP_NOIO);
if (!*lockers)
return -ENOMEM;
@@ -309,7 +309,8 @@ static int decode_lockers(void **p, void
goto err_free_lockers;
}
- *type = ceph_decode_8(p);
+ ret = -EINVAL;
+ ceph_decode_8_safe(p, end, *type, err_free_lockers);
s = ceph_extract_encoded_string(p, end, NULL, GFP_NOIO);
if (IS_ERR(s)) {
ret = PTR_ERR(s);
@@ -319,6 +320,9 @@ static int decode_lockers(void **p, void
*tag = s;
return 0;
+err_inval:
+ return -EINVAL;
+
err_free_lockers:
ceph_free_lockers(*lockers, *num_lockers);
return ret;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 183/235] libceph: add doutc and *_client debug macros support
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (181 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 182/235] libceph: fix two unsafe bare decodes in decode_lockers() Greg Kroah-Hartman
@ 2026-08-20 14:56 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 184/235] ceph: rename _to_client() to _to_fs_client() Greg Kroah-Hartman
` (54 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:56 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Xiubo Li, Patrick Donnelly,
Milind Changire, Ilya Dryomov, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiubo Li <xiubli@redhat.com>
[ Upstream commit 5c5f0d2b5f92c47baf82b9b211e27edd7d195158 ]
This will help print the fsid and client's global_id in debug logs,
and also print the function names.
[ idryomov: %lld -> %llu, leading space for doutc(), don't include
__func__ in pr_*() variants ]
Link: https://tracker.ceph.com/issues/61590
Signed-off-by: Xiubo Li <xiubli@redhat.com>
Reviewed-by: Patrick Donnelly <pdonnell@redhat.com>
Reviewed-by: Milind Changire <mchangir@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Stable-dep-of: 50958bb928ba ("ceph: fix hanging __ceph_get_caps() with stale mds_wanted")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/ceph/ceph_debug.h | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
--- a/include/linux/ceph/ceph_debug.h
+++ b/include/linux/ceph/ceph_debug.h
@@ -19,12 +19,25 @@
pr_debug("%.*s %12.12s:%-4d : " fmt, \
8 - (int)sizeof(KBUILD_MODNAME), " ", \
kbasename(__FILE__), __LINE__, ##__VA_ARGS__)
+# define doutc(client, fmt, ...) \
+ pr_debug("%.*s %12.12s:%-4d : [%pU %llu] " fmt, \
+ 8 - (int)sizeof(KBUILD_MODNAME), " ", \
+ kbasename(__FILE__), __LINE__, \
+ &client->fsid, client->monc.auth->global_id, \
+ ##__VA_ARGS__)
# else
/* faux printk call just to see any compiler warnings. */
# define dout(fmt, ...) do { \
if (0) \
printk(KERN_DEBUG fmt, ##__VA_ARGS__); \
} while (0)
+# define doutc(client, fmt, ...) do { \
+ if (0) \
+ printk(KERN_DEBUG "[%pU %llu] " fmt, \
+ &client->fsid, \
+ client->monc.auth->global_id, \
+ ##__VA_ARGS__); \
+ } while (0)
# endif
#else
@@ -33,7 +46,32 @@
* or, just wrap pr_debug
*/
# define dout(fmt, ...) pr_debug(" " fmt, ##__VA_ARGS__)
+# define doutc(client, fmt, ...) \
+ pr_debug(" [%pU %llu] %s: " fmt, &client->fsid, \
+ client->monc.auth->global_id, __func__, ##__VA_ARGS__)
#endif
+#define pr_notice_client(client, fmt, ...) \
+ pr_notice("[%pU %llu]: " fmt, &client->fsid, \
+ client->monc.auth->global_id, ##__VA_ARGS__)
+#define pr_info_client(client, fmt, ...) \
+ pr_info("[%pU %llu]: " fmt, &client->fsid, \
+ client->monc.auth->global_id, ##__VA_ARGS__)
+#define pr_warn_client(client, fmt, ...) \
+ pr_warn("[%pU %llu]: " fmt, &client->fsid, \
+ client->monc.auth->global_id, ##__VA_ARGS__)
+#define pr_warn_once_client(client, fmt, ...) \
+ pr_warn_once("[%pU %llu]: " fmt, &client->fsid, \
+ client->monc.auth->global_id, ##__VA_ARGS__)
+#define pr_err_client(client, fmt, ...) \
+ pr_err("[%pU %llu]: " fmt, &client->fsid, \
+ client->monc.auth->global_id, ##__VA_ARGS__)
+#define pr_warn_ratelimited_client(client, fmt, ...) \
+ pr_warn_ratelimited("[%pU %llu]: " fmt, &client->fsid, \
+ client->monc.auth->global_id, ##__VA_ARGS__)
+#define pr_err_ratelimited_client(client, fmt, ...) \
+ pr_err_ratelimited("[%pU %llu]: " fmt, &client->fsid, \
+ client->monc.auth->global_id, ##__VA_ARGS__)
+
#endif
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 184/235] ceph: rename _to_client() to _to_fs_client()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (182 preceding siblings ...)
2026-08-20 14:56 ` [PATCH 5.10 183/235] libceph: add doutc and *_client debug macros support Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 185/235] ceph: fix hanging __ceph_get_caps() with stale mds_wanted Greg Kroah-Hartman
` (53 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Xiubo Li, Patrick Donnelly,
Milind Changire, Ilya Dryomov, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiubo Li <xiubli@redhat.com>
[ Upstream commit 5995d90d2d19f337df6a50bcf4699ef053214dac ]
We need to covert the inode to ceph_client in the following commit,
and will add one new helper for that, here we rename the old helper
to _fs_client().
Link: https://tracker.ceph.com/issues/61590
Signed-off-by: Xiubo Li <xiubli@redhat.com>
Reviewed-by: Patrick Donnelly <pdonnell@redhat.com>
Reviewed-by: Milind Changire <mchangir@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Stable-dep-of: 50958bb928ba ("ceph: fix hanging __ceph_get_caps() with stale mds_wanted")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/ceph/addr.c | 24 ++++++++++++------------
fs/ceph/cache.c | 2 +-
fs/ceph/caps.c | 36 ++++++++++++++++++------------------
fs/ceph/dir.c | 20 ++++++++++----------
fs/ceph/export.c | 10 +++++-----
fs/ceph/file.c | 24 ++++++++++++------------
fs/ceph/inode.c | 20 ++++++++++----------
fs/ceph/ioctl.c | 8 ++++----
fs/ceph/super.c | 22 +++++++++++-----------
fs/ceph/super.h | 8 ++++----
fs/ceph/xattr.c | 8 ++++----
11 files changed, 91 insertions(+), 91 deletions(-)
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -178,7 +178,7 @@ static int ceph_do_readpage(struct file
{
struct inode *inode = file_inode(filp);
struct ceph_inode_info *ci = ceph_inode(inode);
- struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
struct ceph_osd_client *osdc = &fsc->client->osdc;
struct ceph_osd_request *req;
struct ceph_vino vino = ceph_vino(inode);
@@ -266,7 +266,7 @@ static int ceph_readpage(struct file *fi
static void finish_read(struct ceph_osd_request *req)
{
struct inode *inode = req->r_inode;
- struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
struct ceph_osd_data *osd_data;
int rc = req->r_result <= 0 ? req->r_result : 0;
int bytes = req->r_result >= 0 ? req->r_result : 0;
@@ -275,7 +275,7 @@ static void finish_read(struct ceph_osd_
dout("finish_read %p req %p rc %d bytes %d\n", inode, req, rc, bytes);
if (rc == -EBLOCKLISTED)
- ceph_inode_to_client(inode)->blocklisted = true;
+ ceph_inode_to_fs_client(inode)->blocklisted = true;
/* unlock all pages, zeroing any data we didn't read */
osd_data = osd_req_op_extent_osd_data(req, 0);
@@ -319,7 +319,7 @@ static int start_read(struct inode *inod
struct list_head *page_list, int max)
{
struct ceph_osd_client *osdc =
- &ceph_inode_to_client(inode)->client->osdc;
+ &ceph_inode_to_fs_client(inode)->client->osdc;
struct ceph_inode_info *ci = ceph_inode(inode);
struct page *page = lru_to_page(page_list);
struct ceph_vino vino;
@@ -453,7 +453,7 @@ static int ceph_readpages(struct file *f
struct list_head *page_list, unsigned nr_pages)
{
struct inode *inode = file_inode(file);
- struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
struct ceph_file_info *fi = file->private_data;
struct ceph_rw_context *rw_ctx;
int rc = 0;
@@ -591,7 +591,7 @@ static int writepage_nounlock(struct pag
{
struct inode *inode = page->mapping->host;
struct ceph_inode_info *ci = ceph_inode(inode);
- struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
struct ceph_snap_context *snapc, *oldest;
loff_t page_off = page_offset(page);
int err;
@@ -733,7 +733,7 @@ static void writepages_finish(struct cep
int rc = req->r_result;
struct ceph_snap_context *snapc = req->r_snapc;
struct address_space *mapping = inode->i_mapping;
- struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
bool remove_page;
dout("writepages_finish %p rc %d\n", inode, rc);
@@ -815,7 +815,7 @@ static int ceph_writepages_start(struct
{
struct inode *inode = mapping->host;
struct ceph_inode_info *ci = ceph_inode(inode);
- struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
struct ceph_vino vino = ceph_vino(inode);
pgoff_t index, start_index, end = -1;
struct ceph_snap_context *snapc = NULL, *last_snapc = NULL, *pgsnapc;
@@ -1252,7 +1252,7 @@ static struct ceph_snap_context *
ceph_find_incompatible(struct page *page)
{
struct inode *inode = page->mapping->host;
- struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
if (READ_ONCE(fsc->mount_state) == CEPH_MOUNT_SHUTDOWN) {
@@ -1739,7 +1739,7 @@ int ceph_uninline_data(struct file *filp
{
struct inode *inode = file_inode(filp);
struct ceph_inode_info *ci = ceph_inode(inode);
- struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
struct ceph_osd_request *req;
struct page *page = NULL;
u64 len, inline_version;
@@ -1896,7 +1896,7 @@ enum {
static int __ceph_pool_perm_get(struct ceph_inode_info *ci,
s64 pool, struct ceph_string *pool_ns)
{
- struct ceph_fs_client *fsc = ceph_inode_to_client(&ci->vfs_inode);
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(&ci->vfs_inode);
struct ceph_mds_client *mdsc = fsc->mdsc;
struct ceph_osd_request *rd_req = NULL, *wr_req = NULL;
struct rb_node **p, *parent;
@@ -2085,7 +2085,7 @@ int ceph_pool_perm_check(struct inode *i
return 0;
}
- if (ceph_test_mount_opt(ceph_inode_to_client(inode),
+ if (ceph_test_mount_opt(ceph_inode_to_fs_client(inode),
NOPOOLPERM))
return 0;
--- a/fs/ceph/cache.c
+++ b/fs/ceph/cache.c
@@ -138,7 +138,7 @@ static const struct fscache_cookie_def c
void ceph_fscache_register_inode_cookie(struct inode *inode)
{
struct ceph_inode_info *ci = ceph_inode(inode);
- struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
struct ceph_aux_inode aux;
/* No caching for filesystem */
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -633,7 +633,7 @@ void ceph_add_cap(struct inode *inode,
unsigned seq, unsigned mseq, u64 realmino, int flags,
struct ceph_cap **new_cap)
{
- struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
+ struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc;
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_cap *cap;
int mds = session->s_mds;
@@ -940,7 +940,7 @@ int __ceph_caps_issued_mask(struct ceph_
int __ceph_caps_issued_mask_metric(struct ceph_inode_info *ci, int mask,
int touch)
{
- struct ceph_fs_client *fsc = ceph_sb_to_client(ci->vfs_inode.i_sb);
+ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(ci->vfs_inode.i_sb);
int r;
r = __ceph_caps_issued_mask(ci, mask, touch);
@@ -1014,7 +1014,7 @@ int __ceph_caps_file_wanted(struct ceph_
const int WR_SHIFT = ffs(CEPH_FILE_MODE_WR);
const int LAZY_SHIFT = ffs(CEPH_FILE_MODE_LAZY);
struct ceph_mount_options *opt =
- ceph_inode_to_client(&ci->vfs_inode)->mount_options;
+ ceph_inode_to_fs_client(&ci->vfs_inode)->mount_options;
unsigned long used_cutoff = jiffies - opt->caps_wanted_delay_max * HZ;
unsigned long idle_cutoff = jiffies - opt->caps_wanted_delay_min * HZ;
@@ -1126,7 +1126,7 @@ static void drop_inode_snap_realm(struct
if (realm->ino == ci->i_vino.ino)
realm->inode = NULL;
spin_unlock(&realm->inodes_with_caps_lock);
- ceph_put_snap_realm(ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc,
+ ceph_put_snap_realm(ceph_sb_to_fs_client(ci->vfs_inode.i_sb)->mdsc,
realm);
}
@@ -1151,7 +1151,7 @@ void __ceph_remove_cap(struct ceph_cap *
dout("__ceph_remove_cap %p from %p\n", cap, &ci->vfs_inode);
- mdsc = ceph_inode_to_client(&ci->vfs_inode)->mdsc;
+ mdsc = ceph_inode_to_fs_client(&ci->vfs_inode)->mdsc;
/* remove from inode's cap rbtree, and clear auth cap */
rb_erase(&cap->ci_node, &ci->i_caps);
@@ -1635,7 +1635,7 @@ void ceph_flush_snaps(struct ceph_inode_
struct ceph_mds_session **psession)
{
struct inode *inode = &ci->vfs_inode;
- struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
+ struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc;
struct ceph_mds_session *session = NULL;
bool need_put = false;
int mds;
@@ -1707,7 +1707,7 @@ int __ceph_mark_dirty_caps(struct ceph_i
struct ceph_cap_flush **pcf)
{
struct ceph_mds_client *mdsc =
- ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc;
+ ceph_sb_to_fs_client(ci->vfs_inode.i_sb)->mdsc;
struct inode *inode = &ci->vfs_inode;
int was = ci->i_dirty_caps;
int dirty = 0;
@@ -1830,7 +1830,7 @@ static u64 __mark_caps_flushing(struct i
struct ceph_mds_session *session, bool wake,
u64 *oldest_flush_tid)
{
- struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
+ struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_cap_flush *cf = NULL;
int flushing;
@@ -2211,7 +2211,7 @@ ack:
*/
static int try_flush_caps(struct inode *inode, u64 *ptid)
{
- struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
+ struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_mds_session *session = NULL;
int flushing = 0;
@@ -2301,7 +2301,7 @@ static int caps_are_flushed(struct inode
*/
static int unsafe_request_wait(struct inode *inode)
{
- struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
+ struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_mds_request *req1 = NULL, *req2 = NULL;
int ret, err = 0;
@@ -2480,7 +2480,7 @@ int ceph_write_inode(struct inode *inode
caps_are_flushed(inode, flush_tid));
} else {
struct ceph_mds_client *mdsc =
- ceph_sb_to_client(inode->i_sb)->mdsc;
+ ceph_sb_to_fs_client(inode->i_sb)->mdsc;
spin_lock(&ci->i_ceph_lock);
if (__ceph_caps_dirty(ci))
@@ -2729,7 +2729,7 @@ static int try_get_cap_refs(struct inode
loff_t endoff, int flags, int *got)
{
struct ceph_inode_info *ci = ceph_inode(inode);
- struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
+ struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc;
int ret = 0;
int have, implemented;
bool snap_rwsem_locked = false;
@@ -2949,7 +2949,7 @@ int ceph_get_caps(struct file *filp, int
struct ceph_file_info *fi = filp->private_data;
struct inode *inode = file_inode(filp);
struct ceph_inode_info *ci = ceph_inode(inode);
- struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
int ret, _got, flags;
ret = ceph_pool_perm_check(inode, need);
@@ -3651,7 +3651,7 @@ static void handle_cap_flush_ack(struct
__releases(ci->i_ceph_lock)
{
struct ceph_inode_info *ci = ceph_inode(inode);
- struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
+ struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
struct ceph_cap_flush *cf, *tmp_cf;
LIST_HEAD(to_remove);
unsigned seq = le32_to_cpu(m->seq);
@@ -3757,7 +3757,7 @@ void __ceph_remove_capsnap(struct inode
bool *wake_ci, bool *wake_mdsc)
{
struct ceph_inode_info *ci = ceph_inode(inode);
- struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
+ struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
bool ret;
lockdep_assert_held(&ci->i_ceph_lock);
@@ -3801,7 +3801,7 @@ static void handle_cap_flushsnap_ack(str
struct ceph_mds_session *session)
{
struct ceph_inode_info *ci = ceph_inode(inode);
- struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
+ struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
u64 follows = le64_to_cpu(m->snap_follows);
struct ceph_cap_snap *capsnap;
bool flushed = false;
@@ -3885,7 +3885,7 @@ static void handle_cap_export(struct ino
struct ceph_mds_cap_peer *ph,
struct ceph_mds_session *session)
{
- struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
+ struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc;
struct ceph_mds_session *tsession = NULL;
struct ceph_cap *cap, *tcap, *new_cap = NULL;
struct ceph_inode_info *ci = ceph_inode(inode);
@@ -4504,7 +4504,7 @@ int ceph_drop_caps_for_unlink(struct ino
if (__ceph_caps_dirty(ci)) {
struct ceph_mds_client *mdsc =
- ceph_inode_to_client(inode)->mdsc;
+ ceph_inode_to_fs_client(inode)->mdsc;
__cap_delay_requeue_front(mdsc, ci);
}
}
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -307,7 +307,7 @@ static int ceph_readdir(struct file *fil
struct ceph_dir_file_info *dfi = file->private_data;
struct inode *inode = file_inode(file);
struct ceph_inode_info *ci = ceph_inode(inode);
- struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
struct ceph_mds_client *mdsc = fsc->mdsc;
int i;
int err;
@@ -677,7 +677,7 @@ out:
int ceph_handle_snapdir(struct ceph_mds_request *req,
struct dentry *dentry, int err)
{
- struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb);
+ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dentry->d_sb);
struct inode *parent = d_inode(dentry->d_parent); /* we hold i_mutex */
/* .snap dir? */
@@ -746,7 +746,7 @@ static bool is_root_ceph_dentry(struct i
static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
unsigned int flags)
{
- struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
+ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dir->i_sb);
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb);
struct ceph_mds_request *req;
int op;
@@ -1128,7 +1128,7 @@ static int get_caps_for_async_unlink(str
*/
static int ceph_unlink(struct inode *dir, struct dentry *dentry)
{
- struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
+ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dir->i_sb);
struct ceph_mds_client *mdsc = fsc->mdsc;
struct inode *inode = d_inode(dentry);
struct ceph_inode_info *ci = ceph_inode(inode);
@@ -1288,7 +1288,7 @@ void __ceph_dentry_lease_touch(struct ce
return;
}
- mdsc = ceph_sb_to_client(dn->d_sb)->mdsc;
+ mdsc = ceph_sb_to_fs_client(dn->d_sb)->mdsc;
spin_lock(&mdsc->dentry_list_lock);
list_move_tail(&di->lease_list, &mdsc->dentry_leases);
spin_unlock(&mdsc->dentry_list_lock);
@@ -1335,7 +1335,7 @@ void __ceph_dentry_dir_lease_touch(struc
return;
}
- mdsc = ceph_sb_to_client(dn->d_sb)->mdsc;
+ mdsc = ceph_sb_to_fs_client(dn->d_sb)->mdsc;
spin_lock(&mdsc->dentry_list_lock);
__dentry_dir_lease_touch(mdsc, di),
spin_unlock(&mdsc->dentry_list_lock);
@@ -1349,7 +1349,7 @@ static void __dentry_lease_unlist(struct
if (list_empty(&di->lease_list))
return;
- mdsc = ceph_sb_to_client(di->dentry->d_sb)->mdsc;
+ mdsc = ceph_sb_to_fs_client(di->dentry->d_sb)->mdsc;
spin_lock(&mdsc->dentry_list_lock);
list_del_init(&di->lease_list);
spin_unlock(&mdsc->dentry_list_lock);
@@ -1704,7 +1704,7 @@ static int ceph_d_revalidate(struct dent
dout("d_revalidate %p '%pd' inode %p offset 0x%llx\n", dentry,
dentry, inode, ceph_dentry(dentry)->offset);
- mdsc = ceph_sb_to_client(dir->i_sb)->mdsc;
+ mdsc = ceph_sb_to_fs_client(dir->i_sb)->mdsc;
/* always trust cached snapped dentries, snapdir dentry */
if (ceph_snap(dir) != CEPH_NOSNAP) {
@@ -1810,7 +1810,7 @@ static int ceph_d_delete(const struct de
static void ceph_d_release(struct dentry *dentry)
{
struct ceph_dentry_info *di = ceph_dentry(dentry);
- struct ceph_fs_client *fsc = ceph_sb_to_client(dentry->d_sb);
+ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dentry->d_sb);
dout("d_release %p\n", dentry);
@@ -1879,7 +1879,7 @@ static ssize_t ceph_read_dir(struct file
int left;
const int bufsize = 1024;
- if (!ceph_test_mount_opt(ceph_sb_to_client(inode->i_sb), DIRSTAT))
+ if (!ceph_test_mount_opt(ceph_sb_to_fs_client(inode->i_sb), DIRSTAT))
return -EISDIR;
if (!dfi->dir_info) {
--- a/fs/ceph/export.c
+++ b/fs/ceph/export.c
@@ -122,7 +122,7 @@ static int ceph_encode_fh(struct inode *
static struct inode *__lookup_inode(struct super_block *sb, u64 ino)
{
- struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc;
+ struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(sb)->mdsc;
struct inode *inode;
struct ceph_vino vino;
int err;
@@ -198,7 +198,7 @@ static struct dentry *__snapfh_to_dentry
struct ceph_nfs_snapfh *sfh,
bool want_parent)
{
- struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc;
+ struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(sb)->mdsc;
struct ceph_mds_request *req;
struct inode *inode;
struct ceph_vino vino;
@@ -304,7 +304,7 @@ static struct dentry *ceph_fh_to_dentry(
static struct dentry *__get_parent(struct super_block *sb,
struct dentry *child, u64 ino)
{
- struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc;
+ struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(sb)->mdsc;
struct ceph_mds_request *req;
struct inode *inode;
int mask;
@@ -426,7 +426,7 @@ static int __get_snap_name(struct dentry
{
struct inode *inode = d_inode(child);
struct inode *dir = d_inode(parent);
- struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
struct ceph_mds_request *req = NULL;
char *last_name = NULL;
unsigned next_offset = 2;
@@ -529,7 +529,7 @@ static int ceph_get_name(struct dentry *
if (ceph_snap(inode) != CEPH_NOSNAP)
return __get_snap_name(parent, name, child);
- mdsc = ceph_inode_to_client(inode)->mdsc;
+ mdsc = ceph_inode_to_fs_client(inode)->mdsc;
req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LOOKUPNAME,
USE_ANY_MDS);
if (IS_ERR(req))
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -233,7 +233,7 @@ static int ceph_init_file_info(struct in
spin_lock_init(&fi->rw_contexts_lock);
INIT_LIST_HEAD(&fi->rw_contexts);
- fi->filp_gen = READ_ONCE(ceph_inode_to_client(inode)->filp_gen);
+ fi->filp_gen = READ_ONCE(ceph_inode_to_fs_client(inode)->filp_gen);
return 0;
}
@@ -338,7 +338,7 @@ out:
int ceph_open(struct inode *inode, struct file *file)
{
struct ceph_inode_info *ci = ceph_inode(inode);
- struct ceph_fs_client *fsc = ceph_sb_to_client(inode->i_sb);
+ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(inode->i_sb);
struct ceph_mds_client *mdsc = fsc->mdsc;
struct ceph_mds_request *req;
struct ceph_file_info *fi = file->private_data;
@@ -687,7 +687,7 @@ static int ceph_finish_async_create(stru
int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
struct file *file, unsigned flags, umode_t mode)
{
- struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
+ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dir->i_sb);
struct ceph_mds_client *mdsc = fsc->mdsc;
struct ceph_mds_request *req;
struct dentry *dn;
@@ -869,7 +869,7 @@ static ssize_t ceph_sync_read(struct kio
struct file *file = iocb->ki_filp;
struct inode *inode = file_inode(file);
struct ceph_inode_info *ci = ceph_inode(inode);
- struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
struct ceph_osd_client *osdc = &fsc->client->osdc;
ssize_t ret;
u64 off = iocb->ki_pos;
@@ -1089,7 +1089,7 @@ static void ceph_aio_complete_req(struct
if (aio_work) {
INIT_WORK(&aio_work->work, ceph_aio_retry_work);
aio_work->req = req;
- queue_work(ceph_inode_to_client(inode)->inode_wq,
+ queue_work(ceph_inode_to_fs_client(inode)->inode_wq,
&aio_work->work);
return;
}
@@ -1208,7 +1208,7 @@ ceph_direct_read_write(struct kiocb *ioc
struct file *file = iocb->ki_filp;
struct inode *inode = file_inode(file);
struct ceph_inode_info *ci = ceph_inode(inode);
- struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
struct ceph_client_metric *metric = &fsc->mdsc->metric;
struct ceph_vino vino;
struct ceph_osd_request *req;
@@ -1418,7 +1418,7 @@ ceph_sync_write(struct kiocb *iocb, stru
struct file *file = iocb->ki_filp;
struct inode *inode = file_inode(file);
struct ceph_inode_info *ci = ceph_inode(inode);
- struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
struct ceph_vino vino;
struct ceph_osd_request *req;
struct page **pages;
@@ -1703,7 +1703,7 @@ static ssize_t ceph_write_iter(struct ki
struct ceph_file_info *fi = file->private_data;
struct inode *inode = file_inode(file);
struct ceph_inode_info *ci = ceph_inode(inode);
- struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
struct ceph_osd_client *osdc = &fsc->client->osdc;
struct ceph_cap_flush *prealloc_cf;
ssize_t count, written = 0;
@@ -1897,7 +1897,7 @@ out_unlocked:
static loff_t ceph_llseek(struct file *file, loff_t offset, int whence)
{
struct inode *inode = file->f_mapping->host;
- struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
loff_t i_size;
loff_t ret;
@@ -1990,7 +1990,7 @@ static int ceph_zero_partial_object(stru
loff_t offset, loff_t *length)
{
struct ceph_inode_info *ci = ceph_inode(inode);
- struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
struct ceph_osd_request *req;
struct ceph_snap_context *snapc;
int ret = 0;
@@ -2324,7 +2324,7 @@ static ssize_t __ceph_copy_file_range(st
struct ceph_inode_info *src_ci = ceph_inode(src_inode);
struct ceph_inode_info *dst_ci = ceph_inode(dst_inode);
struct ceph_cap_flush *prealloc_cf;
- struct ceph_fs_client *src_fsc = ceph_inode_to_client(src_inode);
+ struct ceph_fs_client *src_fsc = ceph_inode_to_fs_client(src_inode);
loff_t size;
ssize_t ret = -EIO, bytes;
u64 src_objnum, dst_objnum, src_objoff, dst_objoff;
@@ -2332,7 +2332,7 @@ static ssize_t __ceph_copy_file_range(st
int src_got = 0, dst_got = 0, err, dirty;
if (src_inode->i_sb != dst_inode->i_sb) {
- struct ceph_fs_client *dst_fsc = ceph_inode_to_client(dst_inode);
+ struct ceph_fs_client *dst_fsc = ceph_inode_to_fs_client(dst_inode);
if (ceph_fsid_compare(&src_fsc->client->fsid,
&dst_fsc->client->fsid)) {
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -1240,7 +1240,7 @@ int ceph_fill_trace(struct super_block *
struct ceph_mds_reply_info_parsed *rinfo = &req->r_reply_info;
struct inode *in = NULL;
struct ceph_vino tvino, dvino;
- struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
+ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb);
int err = 0;
dout("fill_trace %p is_dentry %d is_target %d\n", req,
@@ -1815,7 +1815,7 @@ void ceph_async_iput(struct inode *inode
for (;;) {
if (atomic_add_unless(&inode->i_count, -1, 1))
break;
- if (queue_work(ceph_inode_to_client(inode)->inode_wq,
+ if (queue_work(ceph_inode_to_fs_client(inode)->inode_wq,
&ceph_inode(inode)->i_work))
break;
/* queue work failed, i_count must be at least 2 */
@@ -1832,7 +1832,7 @@ void ceph_queue_writeback(struct inode *
set_bit(CEPH_I_WORK_WRITEBACK, &ci->i_work_mask);
ihold(inode);
- if (queue_work(ceph_inode_to_client(inode)->inode_wq,
+ if (queue_work(ceph_inode_to_fs_client(inode)->inode_wq,
&ci->i_work)) {
dout("ceph_queue_writeback %p\n", inode);
} else {
@@ -1851,7 +1851,7 @@ void ceph_queue_invalidate(struct inode
set_bit(CEPH_I_WORK_INVALIDATE_PAGES, &ci->i_work_mask);
ihold(inode);
- if (queue_work(ceph_inode_to_client(inode)->inode_wq,
+ if (queue_work(ceph_inode_to_fs_client(inode)->inode_wq,
&ceph_inode(inode)->i_work)) {
dout("ceph_queue_invalidate %p\n", inode);
} else {
@@ -1871,7 +1871,7 @@ void ceph_queue_vmtruncate(struct inode
set_bit(CEPH_I_WORK_VMTRUNCATE, &ci->i_work_mask);
ihold(inode);
- if (queue_work(ceph_inode_to_client(inode)->inode_wq,
+ if (queue_work(ceph_inode_to_fs_client(inode)->inode_wq,
&ci->i_work)) {
dout("ceph_queue_vmtruncate %p\n", inode);
} else {
@@ -1884,7 +1884,7 @@ void ceph_queue_vmtruncate(struct inode
static void ceph_do_invalidate_pages(struct inode *inode)
{
struct ceph_inode_info *ci = ceph_inode(inode);
- struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
u32 orig_gen;
int check = 0;
@@ -2033,7 +2033,7 @@ int __ceph_setattr(struct inode *inode,
struct ceph_inode_info *ci = ceph_inode(inode);
unsigned int ia_valid = attr->ia_valid;
struct ceph_mds_request *req;
- struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
+ struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
struct ceph_cap_flush *prealloc_cf;
int issued;
int release = 0, dirtied = 0;
@@ -2248,7 +2248,7 @@ int __ceph_setattr(struct inode *inode,
int ceph_setattr(struct dentry *dentry, struct iattr *attr)
{
struct inode *inode = d_inode(dentry);
- struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
int err;
if (ceph_snap(inode) != CEPH_NOSNAP)
@@ -2281,7 +2281,7 @@ int ceph_setattr(struct dentry *dentry,
int __ceph_do_getattr(struct inode *inode, struct page *locked_page,
int mask, bool force)
{
- struct ceph_fs_client *fsc = ceph_sb_to_client(inode->i_sb);
+ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(inode->i_sb);
struct ceph_mds_client *mdsc = fsc->mdsc;
struct ceph_mds_request *req;
int mode;
@@ -2401,7 +2401,7 @@ int ceph_getattr(const struct path *path
stat->dev = ci->i_snapid_map ? ci->i_snapid_map->dev : 0;
if (S_ISDIR(inode->i_mode)) {
- if (ceph_test_mount_opt(ceph_sb_to_client(inode->i_sb),
+ if (ceph_test_mount_opt(ceph_sb_to_fs_client(inode->i_sb),
RBYTES))
stat->size = ci->i_rbytes;
else
--- a/fs/ceph/ioctl.c
+++ b/fs/ceph/ioctl.c
@@ -64,7 +64,7 @@ static long __validate_layout(struct cep
static long ceph_ioctl_set_layout(struct file *file, void __user *arg)
{
struct inode *inode = file_inode(file);
- struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
+ struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
struct ceph_mds_request *req;
struct ceph_ioctl_layout l;
struct ceph_inode_info *ci = ceph_inode(file_inode(file));
@@ -139,7 +139,7 @@ static long ceph_ioctl_set_layout_policy
struct ceph_mds_request *req;
struct ceph_ioctl_layout l;
int err;
- struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
+ struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
/* copy and validate */
if (copy_from_user(&l, arg, sizeof(l)))
@@ -182,7 +182,7 @@ static long ceph_ioctl_get_dataloc(struc
struct inode *inode = file_inode(file);
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_osd_client *osdc =
- &ceph_sb_to_client(inode->i_sb)->client->osdc;
+ &ceph_sb_to_fs_client(inode->i_sb)->client->osdc;
struct ceph_object_locator oloc;
CEPH_DEFINE_OID_ONSTACK(oid);
u32 xlen;
@@ -243,7 +243,7 @@ static long ceph_ioctl_lazyio(struct fil
struct ceph_file_info *fi = file->private_data;
struct inode *inode = file_inode(file);
struct ceph_inode_info *ci = ceph_inode(inode);
- struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
+ struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc;
if ((fi->fmode & CEPH_FILE_MODE_LAZY) == 0) {
spin_lock(&ci->i_ceph_lock);
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -41,7 +41,7 @@ static LIST_HEAD(ceph_fsc_list);
*/
static void ceph_put_super(struct super_block *s)
{
- struct ceph_fs_client *fsc = ceph_sb_to_client(s);
+ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(s);
dout("put_super\n");
ceph_mdsc_close_sessions(fsc->mdsc);
@@ -49,7 +49,7 @@ static void ceph_put_super(struct super_
static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
{
- struct ceph_fs_client *fsc = ceph_inode_to_client(d_inode(dentry));
+ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(d_inode(dentry));
struct ceph_mon_client *monc = &fsc->client->monc;
struct ceph_statfs st;
int i, err;
@@ -112,7 +112,7 @@ static int ceph_statfs(struct dentry *de
static int ceph_sync_fs(struct super_block *sb, int wait)
{
- struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
+ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb);
if (!wait) {
dout("sync_fs (non-blocking)\n");
@@ -529,7 +529,7 @@ static int compare_mount_options(struct
*/
static int ceph_show_options(struct seq_file *m, struct dentry *root)
{
- struct ceph_fs_client *fsc = ceph_sb_to_client(root->d_sb);
+ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(root->d_sb);
struct ceph_mount_options *fsopt = fsc->mount_options;
size_t pos;
int ret;
@@ -841,7 +841,7 @@ static void destroy_caches(void)
*/
static void ceph_umount_begin(struct super_block *sb)
{
- struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
+ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb);
dout("ceph_umount_begin - starting forced umount\n");
if (!fsc)
@@ -1001,7 +1001,7 @@ static int ceph_compare_super(struct sup
struct ceph_fs_client *new = fc->s_fs_info;
struct ceph_mount_options *fsopt = new->mount_options;
struct ceph_options *opt = new->client->options;
- struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
+ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb);
dout("ceph_compare_super %p\n", sb);
@@ -1094,9 +1094,9 @@ static int ceph_get_tree(struct fs_conte
goto out;
}
- if (ceph_sb_to_client(sb) != fsc) {
+ if (ceph_sb_to_fs_client(sb) != fsc) {
destroy_fs_client(fsc);
- fsc = ceph_sb_to_client(sb);
+ fsc = ceph_sb_to_fs_client(sb);
dout("get_sb got existing client %p\n", fsc);
} else {
dout("get_sb using new client %p\n", fsc);
@@ -1147,7 +1147,7 @@ static int ceph_reconfigure_fc(struct fs
{
struct ceph_parse_opts_ctx *pctx = fc->fs_private;
struct ceph_mount_options *fsopt = pctx->opts;
- struct ceph_fs_client *fsc = ceph_sb_to_client(fc->root->d_sb);
+ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(fc->root->d_sb);
if (fsopt->flags & CEPH_MOUNT_OPT_ASYNC_DIROPS)
ceph_set_mount_opt(fsc, ASYNC_DIROPS);
@@ -1218,7 +1218,7 @@ nomem:
static void ceph_kill_sb(struct super_block *s)
{
- struct ceph_fs_client *fsc = ceph_sb_to_client(s);
+ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(s);
dout("kill_sb %p\n", s);
@@ -1256,7 +1256,7 @@ MODULE_ALIAS_FS("ceph");
int ceph_force_reconnect(struct super_block *sb)
{
- struct ceph_fs_client *fsc = ceph_sb_to_client(sb);
+ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb);
int err = 0;
ceph_umount_begin(sb);
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -440,13 +440,13 @@ ceph_inode(const struct inode *inode)
}
static inline struct ceph_fs_client *
-ceph_inode_to_client(const struct inode *inode)
+ceph_inode_to_fs_client(const struct inode *inode)
{
return (struct ceph_fs_client *)inode->i_sb->s_fs_info;
}
static inline struct ceph_fs_client *
-ceph_sb_to_client(const struct super_block *sb)
+ceph_sb_to_fs_client(const struct super_block *sb)
{
return (struct ceph_fs_client *)sb->s_fs_info;
}
@@ -454,7 +454,7 @@ ceph_sb_to_client(const struct super_blo
static inline struct ceph_mds_client *
ceph_sb_to_mdsc(const struct super_block *sb)
{
- return (struct ceph_mds_client *)ceph_sb_to_client(sb)->mdsc;
+ return (struct ceph_mds_client *)ceph_sb_to_fs_client(sb)->mdsc;
}
static inline struct ceph_vino
@@ -510,7 +510,7 @@ static inline u64 ceph_snap(struct inode
*/
static inline u64 ceph_present_ino(struct super_block *sb, u64 ino)
{
- if (unlikely(ceph_test_mount_opt(ceph_sb_to_client(sb), INO32)))
+ if (unlikely(ceph_test_mount_opt(ceph_sb_to_fs_client(sb), INO32)))
return ceph_ino_to_ino32(ino);
return ino;
}
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -56,7 +56,7 @@ static bool ceph_vxattrcb_layout_exists(
static ssize_t ceph_vxattrcb_layout(struct ceph_inode_info *ci, char *val,
size_t size)
{
- struct ceph_fs_client *fsc = ceph_sb_to_client(ci->vfs_inode.i_sb);
+ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(ci->vfs_inode.i_sb);
struct ceph_osd_client *osdc = &fsc->client->osdc;
struct ceph_string *pool_ns;
s64 pool = ci->i_layout.pool_id;
@@ -160,7 +160,7 @@ static ssize_t ceph_vxattrcb_layout_pool
char *val, size_t size)
{
ssize_t ret;
- struct ceph_fs_client *fsc = ceph_sb_to_client(ci->vfs_inode.i_sb);
+ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(ci->vfs_inode.i_sb);
struct ceph_osd_client *osdc = &fsc->client->osdc;
s64 pool = ci->i_layout.pool_id;
const char *pool_name;
@@ -954,7 +954,7 @@ out:
static int ceph_sync_setxattr(struct inode *inode, const char *name,
const char *value, size_t size, int flags)
{
- struct ceph_fs_client *fsc = ceph_sb_to_client(inode->i_sb);
+ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(inode->i_sb);
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_mds_request *req;
struct ceph_mds_client *mdsc = fsc->mdsc;
@@ -1021,7 +1021,7 @@ int __ceph_setxattr(struct inode *inode,
{
struct ceph_vxattr *vxattr;
struct ceph_inode_info *ci = ceph_inode(inode);
- struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc;
+ struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;
struct ceph_cap_flush *prealloc_cf = NULL;
struct ceph_buffer *old_blob = NULL;
int issued;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 185/235] ceph: fix hanging __ceph_get_caps() with stale mds_wanted
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (183 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 184/235] ceph: rename _to_client() to _to_fs_client() Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 186/235] net/sched: serialize qdisc_rtab_list against concurrent get/put Greg Kroah-Hartman
` (52 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Max Kellermann, Alex Markuze,
Ilya Dryomov, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Max Kellermann <max.kellermann@ionos.com>
[ Upstream commit 50958bb928bad3bdba9e5d1b7ff4bbadcf6951e6 ]
A reader can hang forever in __ceph_get_caps() when the client no
longer holds `FILE_RD`, but local cap state still says that the
capability is already wanted (via `mds_wanted`).
One way to trigger this is through MDS cap revocation. If another
client performs a conflicting operation, the MDS can revoke `FILE_RD`
from the reader; the next read then has to reacquire `FILE_RD`. If
the cap update that should request `FILE_RD` never reaches the MDS
after `cap->mds_wanted` was raised, the reader is left holding only
non-file caps while local `mds_wanted` still includes the file read
caps.
In that state, try_get_cap_refs() sees `need <= mds_wanted` and
returns 0, so __ceph_get_caps() just waits on `i_cap_wq`. If the cap
update that was supposed to request `FILE_RD never reaches the MDS
after `cap->mds_wanted was` raised, no further request is sent and the
waiter can sleep indefinitely until unrelated cap traffic happens to
wake it up.
The ordering issue is that `cap->mds_wanted` is updated in
__prep_cap() before the `CEPH_MSG_CLIENT_CAPS message` is actually
queued for send. That makes one field serve two different meanings at
once: what this client wants, and what the client believes the MDS
already knows it wants.
A proper fix would be to split those states and track whether a cap
update is actually in flight or has been observed by the MDS.
However, simply moving the `cap->mds_wanted assignment` later would
not be sufficient: queueing the message in the messenger does not
guarantee that the MDS processed that specific wanted set, and
reconnect or message loss can still invalidate that assumption.
Fixing that properly would require a larger rework of the cap state
machine.
To allow simpler backports to stable kernels, this patch implements a
simpler workaround:
- stop waiting forever in __ceph_get_caps(); after a bounded wait,
fall back to the renew path
- make ceph_renew_caps() issue a synchronous `OPEN` request whenever
the inode still does not actually hold the wanted caps, instead of
only calling ceph_check_caps()
The extra issued-vs-wanted check in ceph_renew_caps() is necessary
because the previous test only checked whether the inode still had any
real caps at all. That is not enough after revocation: the client can
still hold something like `pLs` and yet be missing `FILE_RD`
completely. In that case, falling back to ceph_check_caps() is not
sufficient, because it still trusts `cap->mds_wanted` and may resend
nothing. By requiring `(issued & wanted) == wanted` before taking the
asynchronous path, the code only uses ceph_check_caps() when the
`wanted caps` are already actually issued. Otherwise, it sends the
synchronous `OPEN` renew.
This preserves the existing asynchronous fast path when the wanted
caps are already issued, avoids changing cap-state semantics, and
fixes the hang by guaranteeing that a stalled waiter eventually
retries through a path that does not rely on the stale `mds_wanted`
state.
[ idryomov: move CEPH_GET_CAPS_WAIT_TIMEOUT from libceph.h to
mds_client.h, formatting ]
Cc: stable@vger.kernel.org
Fixes: 0a454bdd501a ("ceph: reorganize __send_cap for less spinlock abuse")
Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
Reviewed-by: Alex Markuze <amarkuze@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/ceph/caps.c | 17 +++++++++++++++--
fs/ceph/file.c | 9 +++++----
fs/ceph/mds_client.h | 2 ++
3 files changed, 22 insertions(+), 6 deletions(-)
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -2995,7 +2995,19 @@ int ceph_get_caps(struct file *filp, int
ret = -ERESTARTSYS;
break;
}
- wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
+
+ /*
+ * If a cap update is lost after
+ * mds_wanted was raised, waiting
+ * forever will never make progress.
+ * Retry the renew path periodically
+ * so we can resend synchronously.
+ */
+ if (!wait_woken(&wait, TASK_INTERRUPTIBLE,
+ CEPH_GET_CAPS_WAIT_TIMEOUT)) {
+ ret = -ESTALE;
+ break;
+ }
}
remove_wait_queue(&ci->i_cap_wq, &wait);
@@ -3027,7 +3039,8 @@ int ceph_get_caps(struct file *filp, int
continue;
}
if (ret == -ESTALE) {
- /* session was killed, try renew caps */
+ /* session was killed or a waited cap
+ * request needs a retry */
ret = ceph_renew_caps(inode, flags);
if (ret == 0)
continue;
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -277,21 +277,22 @@ static int ceph_init_file(struct inode *
}
/*
- * try renew caps after session gets killed.
+ * Retry cap acquisition after a stale session or a lost cap update.
*/
int ceph_renew_caps(struct inode *inode, int fmode)
{
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb);
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_mds_request *req;
- int err, flags, wanted;
+ int err, flags, wanted, issued;
spin_lock(&ci->i_ceph_lock);
__ceph_touch_fmode(ci, mdsc, fmode);
wanted = __ceph_caps_file_wanted(ci);
+ issued = __ceph_caps_issued(ci, NULL);
if (__ceph_is_any_real_caps(ci) &&
- (!(wanted & CEPH_CAP_ANY_WR) || ci->i_auth_cap)) {
- int issued = __ceph_caps_issued(ci, NULL);
+ (!(wanted & CEPH_CAP_ANY_WR) || ci->i_auth_cap) &&
+ (issued & wanted) == wanted) {
spin_unlock(&ci->i_ceph_lock);
dout("renew caps %p want %s issued %s updating mds_wanted\n",
inode, ceph_cap_string(wanted), ceph_cap_string(issued));
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -61,6 +61,8 @@ enum ceph_feature_type {
struct ceph_fs_client;
struct ceph_cap;
+#define CEPH_GET_CAPS_WAIT_TIMEOUT (5 * HZ)
+
/*
* parsed info about a single inode. pointers are into the encoded
* on-wire structures within the mds reply message payload.
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 186/235] net/sched: serialize qdisc_rtab_list against concurrent get/put
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (184 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 185/235] ceph: fix hanging __ceph_get_caps() with stale mds_wanted Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 187/235] net: gro: fix double aggregation of flush-marked skbs Greg Kroah-Hartman
` (51 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Eric Dumazet, Aldo Ariel Panzardo,
Jamal Hadi Salim, Jakub Kicinski, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aldo Ariel Panzardo <qwe.aldo@gmail.com>
[ Upstream commit f43ee0c0730d6191629b5ee1ceae27b1ebfdc047 ]
qdisc_get_rtab() and qdisc_put_rtab() mutate the process-global singly
linked list qdisc_rtab_list and a plain non-atomic 'int refcnt' with no
lock. This was only safe because every caller historically held the RTNL
mutex, which serialized all rate-table lookups, inserts and frees.
That invariant no longer holds. cls_flower sets
TCF_PROTO_OPS_DOIT_UNLOCKED, so tc_new_tfilter() keeps rtnl_held == false
for it and sets TCA_ACT_FLAGS_NO_RTNL. That flag propagates through
tcf_exts_validate_ex() -> tcf_action_init() -> tcf_action_init_1() ->
tcf_police_init(), which calls qdisc_get_rtab()/qdisc_put_rtab() with the
RTNL mutex NOT held. Two RTM_NEWTFILTER requests on different CPUs, each
adding a flower filter with a police action carrying the same rate, then
race on qdisc_rtab_list and on the non-atomic refcnt, leading to a
use-after-free / double-free of the kmalloc-2k struct qdisc_rate_table.
qdisc_rtab_list is a single global (not per-netns), so the corrupted
object is shared system-wide.
BUG: KASAN: slab-use-after-free in qdisc_put_rtab+0x12f/0x160
qdisc_put_rtab+0x12f/0x160
tcf_police_init+0xda9/0x1590
tcf_action_init_1+0x460/0x6b0
tcf_action_init+0x439/0xa40
tcf_exts_validate_ex+0x42d/0x550
fl_change+0xddd/0x7da0
tc_new_tfilter+0xaa7/0x2420
rtnetlink_rcv_msg+0x95e/0xe90
which belongs to the cache kmalloc-2k of size 2048
Protect qdisc_rtab_list and the refcount with a dedicated spinlock. The
(sleeping, GFP_KERNEL) allocation in qdisc_get_rtab() is performed before
taking the lock; if a concurrent inserter added an identical table in the
meantime the freshly allocated one is freed under the lock, so no
duplicate is leaked. qdisc_put_rtab() now decrements the refcount and
unlinks under the same lock.
Fixes: 470502de5bdb ("net: sched: unlock rules update API")
Suggested-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Aldo Ariel Panzardo <qwe.aldo@gmail.com>
Cc: stable@vger.kernel.org
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20260715114114.446841-1-qwe.aldo@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/sched/sch_api.c | 24 +++++++++++++++++++-----
1 file changed, 19 insertions(+), 5 deletions(-)
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -410,12 +410,13 @@ static __u8 __detect_linklayer(struct tc
}
static struct qdisc_rate_table *qdisc_rtab_list;
+static DEFINE_SPINLOCK(qdisc_rtab_lock);
struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r,
struct nlattr *tab,
struct netlink_ext_ack *extack)
{
- struct qdisc_rate_table *rtab;
+ struct qdisc_rate_table *rtab, *new_rtab;
if (tab == NULL || r->rate == 0 ||
r->cell_log == 0 || r->cell_log >= 32 ||
@@ -424,15 +425,20 @@ struct qdisc_rate_table *qdisc_get_rtab(
return NULL;
}
+ new_rtab = kmalloc(sizeof(*new_rtab), GFP_KERNEL);
+
+ spin_lock(&qdisc_rtab_lock);
for (rtab = qdisc_rtab_list; rtab; rtab = rtab->next) {
if (!memcmp(&rtab->rate, r, sizeof(struct tc_ratespec)) &&
!memcmp(&rtab->data, nla_data(tab), 1024)) {
rtab->refcnt++;
+ spin_unlock(&qdisc_rtab_lock);
+ kfree(new_rtab);
return rtab;
}
}
- rtab = kmalloc(sizeof(*rtab), GFP_KERNEL);
+ rtab = new_rtab;
if (rtab) {
rtab->rate = *r;
rtab->refcnt = 1;
@@ -444,6 +450,7 @@ struct qdisc_rate_table *qdisc_get_rtab(
} else {
NL_SET_ERR_MSG(extack, "Failed to allocate new qdisc rate table");
}
+ spin_unlock(&qdisc_rtab_lock);
return rtab;
}
EXPORT_SYMBOL(qdisc_get_rtab);
@@ -452,18 +459,25 @@ void qdisc_put_rtab(struct qdisc_rate_ta
{
struct qdisc_rate_table *rtab, **rtabp;
- if (!tab || --tab->refcnt)
+ if (!tab)
+ return;
+
+ spin_lock(&qdisc_rtab_lock);
+ if (--tab->refcnt) {
+ spin_unlock(&qdisc_rtab_lock);
return;
+ }
for (rtabp = &qdisc_rtab_list;
(rtab = *rtabp) != NULL;
rtabp = &rtab->next) {
if (rtab == tab) {
*rtabp = rtab->next;
- kfree(rtab);
- return;
+ break;
}
}
+ spin_unlock(&qdisc_rtab_lock);
+ kfree(tab);
}
EXPORT_SYMBOL(qdisc_put_rtab);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 187/235] net: gro: fix double aggregation of flush-marked skbs
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (185 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 186/235] net/sched: serialize qdisc_rtab_list against concurrent get/put Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 188/235] super: fix emergency thaw deadlock on frozen block devices Greg Kroah-Hartman
` (50 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Shiming Cheng, Willem de Bruijn,
Jakub Kicinski, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shiming Cheng <shiming.cheng@mediatek.com>
[ Upstream commit e751256486d0ded20f5a9f9863467f1dce65142f ]
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: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/core/skbuff.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3830,7 +3830,9 @@ EXPORT_SYMBOL_GPL(skb_segment_list);
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 (NAPI_GRO_CB(p)->last == p)
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 188/235] super: fix emergency thaw deadlock on frozen block devices
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (186 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 187/235] net: gro: fix double aggregation of flush-marked skbs Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 189/235] ftrace: Add global mutex to serialize trace_parser access Greg Kroah-Hartman
` (49 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Christian Brauner (Amutable),
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Brauner <brauner@kernel.org>
[ Upstream commit 749d7aa0377aae32af8c0a4ad43371e7bf830ab5 ]
do_thaw_all_callback() calls bdev_thaw() while holding sb->s_umount
exclusively. If the block device was frozen via bdev_freeze() dropping
the last block layer freeze reference calls fs_bdev_thaw() which
reacquires s_umount:
do_thaw_all_callback(sb)
super_lock_excl(sb) # holds sb->s_umount
bdev_thaw(sb->s_bdev)
mutex_lock(&bdev->bd_fsfreeze_mutex)
# bd_fsfreeze_count drops 1 -> 0
bd_holder_ops->thaw == fs_bdev_thaw
get_bdev_super(bdev)
bdev_super_lock(bdev, true)
super_lock(sb, true)
down_write(&sb->s_umount) # same task: deadlock
The emergency thaw worker deadlocks against itself holding both
s_umount and bd_fsfreeze_mutex. That fscks any subsequent unmount,
freeze, or thaw of that filesystem and block device.
[ 81.878470] sysrq: Show Blocked State
[ 81.880140] task:kworker/0:1 state:D stack:0 pid:11 tgid:11 ppid:2 task_flags:0x4208060 flags:0x00080000
[ 81.884876] Workqueue: events do_thaw_all
[ 81.886656] Call Trace:
[ 81.887759] <TASK>
[ 81.888763] __schedule+0x579/0x1420
[ 81.890372] schedule+0x3a/0x100
[ 81.891794] schedule_preempt_disabled+0x15/0x30
[ 81.893848] rwsem_down_write_slowpath+0x1ea/0x900
[ 81.895191] ? __pfx_do_thaw_all_callback+0x10/0x10
[ 81.896528] down_write+0xbd/0xc0
[ 81.897505] super_lock+0x91/0x180
[ 81.898457] ? __mutex_lock+0xa99/0x1140
[ 81.900748] ? __mutex_unlock_slowpath+0x1f/0x400
[ 81.902069] bdev_super_lock+0x5b/0x150
[ 81.903132] get_bdev_super+0x10/0x60
[ 81.904042] fs_bdev_thaw+0x23/0xf0
[ 81.904755] bdev_thaw+0x82/0x100
[ 81.905484] do_thaw_all_callback+0x2c/0x50
[ 81.906298] __iterate_supers+0x5d/0x130
[ 81.907067] do_thaw_all+0x20/0x40
[ 81.907739] process_one_work+0x206/0x5e0
[ 81.908545] worker_thread+0x1e2/0x3c0
[ 81.909339] ? __pfx_worker_thread+0x10/0x10
[ 81.910171] kthread+0xf4/0x130
[ 81.910799] ? __pfx_kthread+0x10/0x10
[ 81.911528] ret_from_fork+0x2e2/0x3b0
[ 81.912259] ? __pfx_kthread+0x10/0x10
[ 81.913010] ret_from_fork_asm+0x1a/0x30
[ 81.913806] </TASK>
bdev_super_lock() even documents the violated requirement with
lockdep_assert_not_held(&sb->s_umount).
Acquiring bd_fsfreeze_mutex under s_umount also inverts the
bd_fsfreeze_mutex vs. s_umount ordering established by
bdev_{freeze,thaw}() and can thus ABBA against a concurrent block-layer
freeze even when the recursive path isn't hit.
Fix this by not holding s_umount around the bdev_thaw() loop at all. Pin
the superblock with an active reference instead as
filesystems_freeze_callback() does. The active reference keeps the
superblock from being shut down and so ->s_bdev stays valid without
holding s_umount. The block-layer-held freeze is dropped by
fs_bdev_thaw() with FREEZE_MAY_NEST | FREEZE_HOLDER_USERSPACE exactly as
a regular unfreeze would and thaw_super_locked() handles
filesystem-level freezes as before.
The emergency thaw path has deadlocked like this in one form or
another for a long long time but the current exclusively-held
shape dates back to commit [1] where thaw_bdev() already ended in
thaw_super() with s_umount held by do_thaw_all_callback().
Fixes: 08fdc8a0138a ("buffer.c: call thaw_super during emergency thaw") [1]
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260723-work-super-emergency_thaw-v1-1-7c315c600245@kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/super.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
--- a/fs/super.c
+++ b/fs/super.c
@@ -1048,13 +1048,24 @@ void emergency_remount(void)
static void do_thaw_all_callback(struct super_block *sb)
{
+ bool active = false;
+
+ down_write(&sb->s_umount);
+ if (sb->s_root && sb->s_flags & SB_BORN)
+ active = atomic_inc_not_zero(&sb->s_active);
+ up_write(&sb->s_umount);
+ if (!active)
+ return;
+
+ /* thaw_bdev() acquires s_umount so it must not be held here */
+ emergency_thaw_bdev(sb);
+
down_write(&sb->s_umount);
- if (sb->s_root && sb->s_flags & SB_BORN) {
- emergency_thaw_bdev(sb);
+ if (sb->s_root && sb->s_flags & SB_BORN)
thaw_super_locked(sb);
- } else {
+ else
up_write(&sb->s_umount);
- }
+ deactivate_super(sb);
}
static void do_thaw_all(struct work_struct *work)
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 189/235] ftrace: Add global mutex to serialize trace_parser access
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (187 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 188/235] super: fix emergency thaw deadlock on frozen block devices Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 190/235] skbuff: introduce skb_pull_data Greg Kroah-Hartman
` (48 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Tengda Wu, Steven Rostedt,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tengda Wu <wutengda@huaweicloud.com>
[ Upstream commit 7720b63bcef3f54c7fe288774b720a227d54a306 ]
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: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
kernel/trace/ftrace.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -1043,6 +1043,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 undwinder to know about dynamic ftrace trampolines.
*/
struct ftrace_ops *ftrace_ops_trampoline(unsigned long addr)
@@ -4934,6 +4940,8 @@ ftrace_regex_write(struct file *file, co
/* iter->hash is a local copy, so we don't need regex_lock */
parser = &iter->parser;
+
+ mutex_lock(&parser_lock);
read = trace_get_user(parser, ubuf, cnt, ppos);
if (read >= 0 && trace_parser_loaded(parser) &&
@@ -4947,6 +4955,7 @@ ftrace_regex_write(struct file *file, co
ret = read;
out:
+ mutex_unlock(&parser_lock);
return ret;
}
@@ -5682,12 +5691,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);
@@ -6005,10 +6016,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);
@@ -6127,6 +6140,7 @@ ftrace_graph_write(struct file *file, co
parser = &fgd->parser;
+ mutex_lock(&parser_lock);
read = trace_get_user(parser, ubuf, cnt, ppos);
if (read >= 0 && trace_parser_loaded(parser) &&
@@ -6139,6 +6153,7 @@ ftrace_graph_write(struct file *file, co
if (!ret)
ret = read;
+ mutex_unlock(&parser_lock);
return ret;
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 190/235] skbuff: introduce skb_pull_data
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (188 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 189/235] ftrace: Add global mutex to serialize trace_parser access Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 191/235] Bluetooth: HIDP: reject frames without a transaction header Greg Kroah-Hartman
` (47 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jakub Kicinski,
Luiz Augusto von Dentz, Dan Carpenter, Marcel Holtmann,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
[ Upstream commit 13244cccc2b61ec715f0ac583d3037497004d4a5 ]
Like skb_pull but returns the original data pointer before pulling the
data after performing a check against sbk->len.
This allows to change code that does "struct foo *p = (void *)skb->data;"
which is hard to audit and error prone, to:
p = skb_pull_data(skb, sizeof(*p));
if (!p)
return;
Which is both safer and cleaner.
Acked-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Stable-dep-of: 47778d2c2087 ("Bluetooth: HIDP: reject frames without a transaction header")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/skbuff.h | 2 ++
net/core/skbuff.c | 24 ++++++++++++++++++++++++
2 files changed, 26 insertions(+)
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -2317,6 +2317,8 @@ static inline void *skb_pull_inline(stru
return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len);
}
+void *skb_pull_data(struct sk_buff *skb, size_t len);
+
void *__pskb_pull_tail(struct sk_buff *skb, int delta);
static inline void *__pskb_pull(struct sk_buff *skb, unsigned int len)
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -1977,6 +1977,30 @@ void *skb_pull(struct sk_buff *skb, unsi
EXPORT_SYMBOL(skb_pull);
/**
+ * skb_pull_data - remove data from the start of a buffer returning its
+ * original position.
+ * @skb: buffer to use
+ * @len: amount of data to remove
+ *
+ * This function removes data from the start of a buffer, returning
+ * the memory to the headroom. A pointer to the original data in the buffer
+ * is returned after checking if there is enough data to pull. Once the
+ * data has been pulled future pushes will overwrite the old data.
+ */
+void *skb_pull_data(struct sk_buff *skb, size_t len)
+{
+ void *data = skb->data;
+
+ if (skb->len < len)
+ return NULL;
+
+ skb_pull(skb, len);
+
+ return data;
+}
+EXPORT_SYMBOL(skb_pull_data);
+
+/**
* skb_trim - remove end from a buffer
* @skb: buffer to alter
* @len: new length
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 191/235] Bluetooth: HIDP: reject frames without a transaction header
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (189 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 190/235] skbuff: introduce skb_pull_data Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 192/235] mm/vmstat: fold stranded per-cpu node stats when a node comes online Greg Kroah-Hartman
` (46 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sangho Lee, Luiz Augusto von Dentz,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sangho Lee <kudo3228@gmail.com>
[ Upstream commit 47778d2c2087b5d192398f6fddf692d16a5431cf ]
hidp_recv_ctrl_frame() and hidp_recv_intr_frame() read skb->data[0]
before checking that the L2CAP SDU contains a transaction header. A
connected HIDP peer can send an empty basic-mode SDU and make both paths
use an uninitialized byte from skb tailroom.
KMSAN reports the use in hidp_session_run(), with the uninitialized value
originating in __alloc_skb() through vhci_write(). The control path
produces two reports and the interrupt path produces one.
The byte can also be controlled by a malformed lower-layer packet. If an
HCI ACL packet contains an L2CAP PDU with a declared zero-length payload
followed by an extra 0x15 byte, l2cap_recv_acldata() reduces skb->len to
the declared PDU length before dispatch. The current HIDP path nevertheless
consumes the extra byte as HIDP_TRANS_HID_CONTROL |
HIDP_CTRL_VIRTUAL_CABLE_UNPLUG and terminates the HIDP session. With this
change, the same packet is discarded and a subsequent feature report
request succeeds.
Pull the transaction header with skb_pull_data() and discard frames that
do not contain it.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Sangho Lee <kudo3228@gmail.com>
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>
---
net/bluetooth/hidp/core.c | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -551,16 +551,18 @@ static int hidp_process_data(struct hidp
static void hidp_recv_ctrl_frame(struct hidp_session *session,
struct sk_buff *skb)
{
- unsigned char hdr, type, param;
+ unsigned char type, param;
+ u8 *hdr;
int free_skb = 1;
BT_DBG("session %p skb %p len %d", session, skb, skb->len);
- hdr = skb->data[0];
- skb_pull(skb, 1);
+ hdr = skb_pull_data(skb, 1);
+ if (!hdr)
+ goto free;
- type = hdr & HIDP_HEADER_TRANS_MASK;
- param = hdr & HIDP_HEADER_PARAM_MASK;
+ type = *hdr & HIDP_HEADER_TRANS_MASK;
+ param = *hdr & HIDP_HEADER_PARAM_MASK;
switch (type) {
case HIDP_TRANS_HANDSHAKE:
@@ -581,6 +583,7 @@ static void hidp_recv_ctrl_frame(struct
break;
}
+free:
if (free_skb)
kfree_skb(skb);
}
@@ -588,14 +591,15 @@ static void hidp_recv_ctrl_frame(struct
static void hidp_recv_intr_frame(struct hidp_session *session,
struct sk_buff *skb)
{
- unsigned char hdr;
+ u8 *hdr;
BT_DBG("session %p skb %p len %d", session, skb, skb->len);
- hdr = skb->data[0];
- skb_pull(skb, 1);
+ hdr = skb_pull_data(skb, 1);
+ if (!hdr)
+ goto free;
- if (hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
+ if (*hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
hidp_set_timer(session);
if (session->input)
@@ -607,9 +611,10 @@ static void hidp_recv_intr_frame(struct
BT_DBG("report len %d", skb->len);
}
} else {
- BT_DBG("Unsupported protocol header 0x%02x", hdr);
+ BT_DBG("Unsupported protocol header 0x%02x", *hdr);
}
+free:
kfree_skb(skb);
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 192/235] mm/vmstat: fold stranded per-cpu node stats when a node comes online
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (190 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 191/235] Bluetooth: HIDP: reject frames without a transaction header Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 193/235] net: pktgen: fix code style (WARNING: Block comments) Greg Kroah-Hartman
` (45 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Gregory Price, Johannes Weiner,
Mel Gorman, Mike Rapoport, Vlastimil Babka, Andrew Morton,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gregory Price <gourry@gourry.net>
[ Upstream commit ea3034b2b00fa50c8d2518d0804c9d427bbafa86 ]
A per-node vmstat counter is pgdat->vm_stat[] plus per-cpu deltas. A
balanced counter can sit split as global=+N / per-cpu=-N.
The folds reconciling the split only walk online nodes, so when
try_offline_node() marks a node offline the per-cpu deltas are stranded.
A subsequent online resets the per-cpu area but not pgdat->vm_stat[],
orphaning the +N permanently. All NR_VM_NODE_STAT_ITEMS are affected.
The existing code zeroes the per-cpu counters and causes a permanent skew.
Fold the stranded deltas instead, before the node rejoins the online set.
The node is not online yet and the hotplug lock is held, so the remote
access to per-cpu values is safe.
Discovered when node compaction hung for a nearly empty node, as the math
to determine throttling broke. Reproduced by repeated memory
hotplug/unplug cycles on a node under pressure: NR_ISOLATED_ANON ratchets
up and never returns to zero.
Link: https://lore.kernel.org/20260627202243.758289-1-gourry@gourry.net
Fixes: 75ef71840539 ("mm, vmstat: add infrastructure for per-node vmstats")
Signed-off-by: Gregory Price <gourry@gourry.net>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Mel Gorman <mgorman@techsingularity.net>
Cc: Mike Rapoport <rppt@kernel.org>
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/memory_hotplug.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -894,7 +894,7 @@ static pg_data_t __ref *hotadd_new_pgdat
alloc_percpu(struct per_cpu_nodestat);
arch_refresh_nodedata(nid, pgdat);
} else {
- int cpu;
+ int cpu, i;
/*
* Reset the nr_zones, order and highest_zoneidx before reuse.
* Note that kswapd will init kswapd_highest_zoneidx properly
@@ -903,10 +903,17 @@ static pg_data_t __ref *hotadd_new_pgdat
pgdat->nr_zones = 0;
pgdat->kswapd_order = 0;
pgdat->kswapd_highest_zoneidx = 0;
- for_each_online_cpu(cpu) {
- struct per_cpu_nodestat *p;
+ /*
+ * Hot-unplug can leave per-cpu vmstat deltas unfolded (folders skip
+ * offline nodes) - reconcile this at online. Foreign access to counters
+ * is safe: the node is not online yet and we hold the hotplug lock.
+ */
+ for_each_possible_cpu(cpu) {
+ struct per_cpu_nodestat *p = per_cpu_ptr(pgdat->per_cpu_nodestats, cpu);
- p = per_cpu_ptr(pgdat->per_cpu_nodestats, cpu);
+ for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++)
+ if (p->vm_node_stat_diff[i])
+ node_page_state_add(p->vm_node_stat_diff[i], pgdat, i);
memset(p, 0, sizeof(*p));
}
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 193/235] net: pktgen: fix code style (WARNING: Block comments)
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (191 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 192/235] mm/vmstat: fold stranded per-cpu node stats when a node comes online Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 194/235] net: pktgen: fix proc entry use-after-free Greg Kroah-Hartman
` (44 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Peter Seiderer,
Toke Høiland-Jørgensen, Jakub Kicinski, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Seiderer <ps.report@gmx.net>
[ Upstream commit 870b856cb478bc02fffe4d89897e62c692efb09a ]
Fix checkpatch code style warnings:
WARNING: Block comments use a trailing */ on a separate line
+ * removal by worker thread */
WARNING: Block comments use * on subsequent lines
+ __u8 tos; /* six MSB of (former) IPv4 TOS
+ are for dscp codepoint */
WARNING: Block comments use a trailing */ on a separate line
+ are for dscp codepoint */
WARNING: Block comments use * on subsequent lines
+ __u8 traffic_class; /* ditto for the (former) Traffic Class in IPv6
+ (see RFC 3260, sec. 4) */
WARNING: Block comments use a trailing */ on a separate line
+ (see RFC 3260, sec. 4) */
WARNING: Block comments use * on subsequent lines
+ /* = {
+ 0x00, 0x80, 0xC8, 0x79, 0xB3, 0xCB,
WARNING: Block comments use * on subsequent lines
+ /* Field for thread to receive "posted" events terminate,
+ stop ifs etc. */
WARNING: Block comments use a trailing */ on a separate line
+ stop ifs etc. */
WARNING: Block comments should align the * on each line
+ * we go look for it ...
+*/
WARNING: Block comments use a trailing */ on a separate line
+ * we resolve the dst issue */
WARNING: Block comments use a trailing */ on a separate line
+ * with proc_create_data() */
Signed-off-by: Peter Seiderer <ps.report@gmx.net>
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: 817ff6efdb7f ("net: pktgen: fix proc entry use-after-free")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/core/pktgen.c | 39 +++++++++++++++++++++++----------------
1 file changed, 23 insertions(+), 16 deletions(-)
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -275,7 +275,8 @@ struct pktgen_dev {
int pkt_overhead; /* overhead for MPLS, VLANs, IPSEC etc */
int nfrags;
int removal_mark; /* non-zero => the device is marked for
- * removal by worker thread */
+ * removal by worker thread
+ */
struct page *page;
u64 delay; /* nano-seconds */
@@ -338,10 +339,12 @@ struct pktgen_dev {
__u16 udp_dst_max; /* exclusive, dest UDP port */
/* DSCP + ECN */
- __u8 tos; /* six MSB of (former) IPv4 TOS
- are for dscp codepoint */
- __u8 traffic_class; /* ditto for the (former) Traffic Class in IPv6
- (see RFC 3260, sec. 4) */
+ __u8 tos; /* six MSB of (former) IPv4 TOS
+ * are for dscp codepoint
+ */
+ __u8 traffic_class; /* ditto for the (former) Traffic Class in IPv6
+ * (see RFC 3260, sec. 4)
+ */
/* MPLS */
unsigned int nr_labels; /* Depth of stack, 0 = no MPLS */
@@ -375,12 +378,12 @@ struct pktgen_dev {
__u8 hh[14];
/* = {
- 0x00, 0x80, 0xC8, 0x79, 0xB3, 0xCB,
-
- We fill in SRC address later
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x08, 0x00
- };
+ * 0x00, 0x80, 0xC8, 0x79, 0xB3, 0xCB,
+ *
+ * We fill in SRC address later
+ * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ * 0x08, 0x00
+ * };
*/
__u16 pad; /* pad out the hh struct to an even 16 bytes */
@@ -443,7 +446,8 @@ struct pktgen_thread {
char result[512];
/* Field for thread to receive "posted" events terminate,
- stop ifs etc. */
+ * stop ifs etc.
+ */
u32 control;
int cpu;
@@ -2235,7 +2239,7 @@ static inline int f_pick(struct pktgen_d
#ifdef CONFIG_XFRM
/* If there was already an IPSEC SA, we keep it as is, else
* we go look for it ...
-*/
+ */
#define DUMMY_MARK 0
static void get_ipsec_sa(struct pktgen_dev *pkt_dev, int flow)
{
@@ -2506,7 +2510,8 @@ static int pktgen_output_ipsec(struct sk
if (!x)
return 0;
/* XXX: we dont support tunnel mode for now until
- * we resolve the dst issue */
+ * we resolve the dst issue
+ */
if ((x->props.mode != XFRM_MODE_TRANSPORT) && (pkt_dev->spi == 0))
return 0;
@@ -3569,7 +3574,8 @@ static int add_dev_to_thread(struct pktg
* userspace on another CPU than the kthread. The if_lock()
* is used here to sync with concurrent instances of
* _rem_dev_from_if_list() invoked via kthread, which is also
- * updating the if_list */
+ * updating the if_list
+ */
if_lock(t);
if (pkt_dev->pg_thread) {
@@ -3766,7 +3772,8 @@ static int pktgen_remove_device(struct p
/* Remove proc before if_list entry, because add_device uses
* list to determine if interface already exist, avoid race
- * with proc_create_data() */
+ * with proc_create_data()
+ */
proc_remove(pkt_dev->entry);
/* And update the thread if_list */
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 194/235] net: pktgen: fix proc entry use-after-free
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (192 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 193/235] net: pktgen: fix code style (WARNING: Block comments) Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 195/235] scsi: sd: sd_zbc: Improve source code documentation Greg Kroah-Hartman
` (43 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Chengfeng Ye, Simon Horman,
Jakub Kicinski, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chengfeng Ye <nicoyip.dev@gmail.com>
[ Upstream commit 817ff6efdb7f484ea547218e11e17d8e43daa3b4 ]
pktgen_change_name() replaces pkt_dev->entry while holding t->if_lock.
pktgen_remove_device() removes the same entry before
_rem_dev_from_if_list() takes that lock.
This allows the following interleaving:
CPU 0 (NETDEV_CHANGENAME) CPU 1 (kpktgend)
if_lock(t)
proc_remove(pkt_dev->entry)
proc_remove(pkt_dev->entry)
pkt_dev->entry = proc_create_data(...)
if_unlock(t)
The kthread can pass the stale proc_dir_entry to proc_remove() after the
rename path has freed it. A reproducer with a widened race window reports:
BUG: KASAN: slab-use-after-free in proc_remove+0x78/0x80
Read of size 8 at addr ffff8881478fea70 by task kpktgend_0/67
Call Trace:
proc_remove+0x78/0x80
pktgen_remove_device.isra.0+0x11c/0x4c0
pktgen_thread_worker+0x1214/0x6bc0
kthread+0x2c6/0x3b0
Allocated by task 95:
__proc_create+0x204/0x790
proc_create_data+0x72/0xe0
pktgen_thread_write+0xd61/0x1510
Freed by task 28:
kmem_cache_free+0xcb/0x3d0
proc_free_inode+0x5b/0x80
rcu_core+0x50a/0x1850
The buggy address belongs to the object at ffff8881478fea00
which belongs to the cache proc_dir_entry of size 192
Move proc_remove() into the if_lock-protected list removal helper. Keep it
before list_del_rcu() to preserve the ordering required by add_device().
The rename path must then finish replacing the entry before removal, or
it observes that the device is no longer on the list.
Fixes: 39df232f1a9b ("[PKTGEN]: fix device name handling")
Cc: stable@vger.kernel.org
Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260719145740.2888967-1-nicoyip.dev@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/core/pktgen.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -3745,6 +3745,7 @@ static void _rem_dev_from_if_list(struct
struct pktgen_dev *p;
if_lock(t);
+ proc_remove(pkt_dev->entry);
list_for_each_safe(q, n, &t->if_list) {
p = list_entry(q, struct pktgen_dev, list);
if (p == pkt_dev)
@@ -3774,9 +3775,6 @@ static int pktgen_remove_device(struct p
* list to determine if interface already exist, avoid race
* with proc_create_data()
*/
- proc_remove(pkt_dev->entry);
-
- /* And update the thread if_list */
_rem_dev_from_if_list(t, pkt_dev);
#ifdef CONFIG_XFRM
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 195/235] scsi: sd: sd_zbc: Improve source code documentation
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (193 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 194/235] net: pktgen: fix proc entry use-after-free Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 196/235] scsi: sd: sd_zbc: Use logical blocks as unit when querying zones Greg Kroah-Hartman
` (42 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Damien Le Moal, Himanshu Madhani,
Douglas Gilbert, Bart Van Assche, Martin K. Petersen, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bart Van Assche <bvanassche@acm.org>
[ Upstream commit aa96bfb4caff59c93f0637092efe3a714cab0fe6 ]
Add several kernel-doc headers. Declare input arrays const. Specify the
array size in function declarations.
Link: https://lore.kernel.org/r/20220421183023.3462291-2-bvanassche@acm.org
Reviewed-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Acked-by: Douglas Gilbert <dgilbert@interlog.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Stable-dep-of: 93dde0bf2f39 ("scsi: scsi_debug: Fix REPORT ZONES alloc_len underflow OOB write")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/scsi/sd.h | 5 +---
drivers/scsi/sd_zbc.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 54 insertions(+), 6 deletions(-)
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -217,7 +217,7 @@ static inline int sd_is_zoned(struct scs
#ifdef CONFIG_BLK_DEV_ZONED
void sd_zbc_release_disk(struct scsi_disk *sdkp);
-int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buffer);
+int sd_zbc_read_zones(struct scsi_disk *sdkp, u8 buf[SD_BUF_SIZE]);
int sd_zbc_revalidate_zones(struct scsi_disk *sdkp);
blk_status_t sd_zbc_setup_zone_mgmt_cmnd(struct scsi_cmnd *cmd,
unsigned char op, bool all);
@@ -233,8 +233,7 @@ blk_status_t sd_zbc_prepare_zone_append(
static inline void sd_zbc_release_disk(struct scsi_disk *sdkp) {}
-static inline int sd_zbc_read_zones(struct scsi_disk *sdkp,
- unsigned char *buf)
+static inline int sd_zbc_read_zones(struct scsi_disk *sdkp, u8 buf[SD_BUF_SIZE])
{
return 0;
}
--- a/drivers/scsi/sd_zbc.c
+++ b/drivers/scsi/sd_zbc.c
@@ -20,6 +20,12 @@
#include "sd.h"
+/**
+ * sd_zbc_get_zone_wp_offset - Get zone write pointer offset.
+ * @zone: Zone for which to return the write pointer offset.
+ *
+ * Return: offset of the write pointer from the start of the zone.
+ */
static unsigned int sd_zbc_get_zone_wp_offset(struct blk_zone *zone)
{
if (zone->type == ZBC_ZONE_TYPE_CONV)
@@ -44,7 +50,21 @@ static unsigned int sd_zbc_get_zone_wp_o
}
}
-static int sd_zbc_parse_report(struct scsi_disk *sdkp, u8 *buf,
+/**
+ * sd_zbc_parse_report - Parse a SCSI zone descriptor
+ * @sdkp: SCSI disk pointer.
+ * @buf: SCSI zone descriptor.
+ * @idx: Index of the zone relative to the first zone reported by the current
+ * sd_zbc_report_zones() call.
+ * @cb: Callback function pointer.
+ * @data: Second argument passed to @cb.
+ *
+ * Return: Value returned by @cb.
+ *
+ * Convert a SCSI zone descriptor into struct blk_zone format. Additionally,
+ * call @cb(blk_zone, @data).
+ */
+static int sd_zbc_parse_report(struct scsi_disk *sdkp, const u8 buf[64],
unsigned int idx, report_zones_cb cb, void *data)
{
struct scsi_device *sdp = sdkp->device;
@@ -189,6 +209,17 @@ static inline sector_t sd_zbc_zone_secto
return logical_to_sectors(sdkp->device, sdkp->zone_blocks);
}
+/**
+ * sd_zbc_report_zones - SCSI .report_zones() callback.
+ * @disk: Disk to report zones for.
+ * @sector: Start sector.
+ * @nr_zones: Maximum number of zones to report.
+ * @cb: Callback function called to report zone information.
+ * @data: Second argument passed to @cb.
+ *
+ * Called by the block layer to iterate over zone information. See also the
+ * disk->fops->report_zones() calls in block/blk-zoned.c.
+ */
int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
unsigned int nr_zones, report_zones_cb cb, void *data)
{
@@ -276,6 +307,10 @@ static int sd_zbc_update_wp_offset_cb(st
return 0;
}
+/*
+ * An attempt to append a zone triggered an invalid write pointer error.
+ * Reread the write pointer of the zone(s) in which the append failed.
+ */
static void sd_zbc_update_wp_offset_workfn(struct work_struct *work)
{
struct scsi_disk *sdkp;
@@ -584,7 +619,7 @@ static int sd_zbc_check_zoned_characteri
* sd_zbc_check_capacity - Check the device capacity
* @sdkp: Target disk
* @buf: command buffer
- * @zblocks: zone size in number of blocks
+ * @zblocks: zone size in logical blocks
*
* Get the device zone size and check that the device capacity as reported
* by READ CAPACITY matches the max_lba value (plus one) of the report zones
@@ -679,6 +714,11 @@ static void sd_zbc_revalidate_zones_cb(s
swap(sdkp->zones_wp_offset, sdkp->rev_wp_offset);
}
+/*
+ * Call blk_revalidate_disk_zones() if any of the zoned disk properties have
+ * changed that make it necessary to call that function. Called by
+ * sd_revalidate_disk() after the gendisk capacity has been set.
+ */
int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
{
struct gendisk *disk = sdkp->disk;
@@ -757,7 +797,16 @@ unlock:
return ret;
}
-int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buf)
+/**
+ * sd_zbc_read_zones - Read zone information and update the request queue
+ * @sdkp: SCSI disk pointer.
+ * @buf: 512 byte buffer used for storing SCSI command output.
+ *
+ * Read zone information and update the request queue zone characteristics and
+ * also the zoned device information in *sdkp. Called by sd_revalidate_disk()
+ * before the gendisk capacity has been set.
+ */
+int sd_zbc_read_zones(struct scsi_disk *sdkp, u8 buf[SD_BUF_SIZE])
{
struct gendisk *disk = sdkp->disk;
struct request_queue *q = disk->queue;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 196/235] scsi: sd: sd_zbc: Use logical blocks as unit when querying zones
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (194 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 195/235] scsi: sd: sd_zbc: Improve source code documentation Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 197/235] scsi: sd: sd_zbc: Return early in sd_zbc_check_zoned_characteristics() Greg Kroah-Hartman
` (41 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Himanshu Madhani, Douglas Gilbert,
Damien Le Moal, Bart Van Assche, Martin K. Petersen, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Damien Le Moal <damien.lemoal@opensource.wdc.com>
[ Upstream commit 43af5da09efb8abe450ec859d3063adeb7d1eb54 ]
When querying zones, track the position in logical blocks instead of in
sectors. This change slightly simplifies sd_zbc_report_zones().
Link: https://lore.kernel.org/r/20220421183023.3462291-4-bvanassche@acm.org
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Acked-by: Douglas Gilbert <dgilbert@interlog.com>
Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
[ bvanassche: extracted this change from a larger patch ]
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Stable-dep-of: 93dde0bf2f39 ("scsi: scsi_debug: Fix REPORT ZONES alloc_len underflow OOB write")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/scsi/sd_zbc.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
--- a/drivers/scsi/sd_zbc.c
+++ b/drivers/scsi/sd_zbc.c
@@ -224,7 +224,7 @@ int sd_zbc_report_zones(struct gendisk *
unsigned int nr_zones, report_zones_cb cb, void *data)
{
struct scsi_disk *sdkp = scsi_disk(disk);
- sector_t capacity = logical_to_sectors(sdkp->device, sdkp->capacity);
+ sector_t lba = sectors_to_logical(sdkp->device, sector);
unsigned int nr, i;
unsigned char *buf;
size_t offset, buflen = 0;
@@ -235,7 +235,7 @@ int sd_zbc_report_zones(struct gendisk *
/* Not a zoned device */
return -EOPNOTSUPP;
- if (!capacity)
+ if (!sdkp->capacity)
/* Device gone or invalid */
return -ENODEV;
@@ -243,9 +243,8 @@ int sd_zbc_report_zones(struct gendisk *
if (!buf)
return -ENOMEM;
- while (zone_idx < nr_zones && sector < capacity) {
- ret = sd_zbc_do_report_zones(sdkp, buf, buflen,
- sectors_to_logical(sdkp->device, sector), true);
+ while (zone_idx < nr_zones && lba < sdkp->capacity) {
+ ret = sd_zbc_do_report_zones(sdkp, buf, buflen, lba, true);
if (ret)
goto out;
@@ -263,7 +262,7 @@ int sd_zbc_report_zones(struct gendisk *
zone_idx++;
}
- sector += sd_zbc_zone_sectors(sdkp) * i;
+ lba += sdkp->zone_blocks * i;
}
ret = zone_idx;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 197/235] scsi: sd: sd_zbc: Return early in sd_zbc_check_zoned_characteristics()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (195 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 196/235] scsi: sd: sd_zbc: Use logical blocks as unit when querying zones Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 198/235] scsi: scsi_debug: Rename zone type constants Greg Kroah-Hartman
` (40 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Himanshu Madhani, Douglas Gilbert,
Damien Le Moal, Bart Van Assche, Martin K. Petersen, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Damien Le Moal <damien.lemoal@opensource.wdc.com>
[ Upstream commit 60caf3758103b8edc90724ba781ff119f739162a ]
Return early in sd_zbc_check_zoned_characteristics() for host-aware
disks. This patch does not change any functionality but makes a later patch
easier to read.
Link: https://lore.kernel.org/r/20220421183023.3462291-6-bvanassche@acm.org
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Acked-by: Douglas Gilbert <dgilbert@interlog.com>
Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
[ bvanassche: extracted this change from a larger patch ]
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Stable-dep-of: 93dde0bf2f39 ("scsi: scsi_debug: Fix REPORT ZONES alloc_len underflow OOB write")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/scsi/sd_zbc.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
--- a/drivers/scsi/sd_zbc.c
+++ b/drivers/scsi/sd_zbc.c
@@ -591,14 +591,15 @@ static int sd_zbc_check_zoned_characteri
sdkp->zones_optimal_open = get_unaligned_be32(&buf[8]);
sdkp->zones_optimal_nonseq = get_unaligned_be32(&buf[12]);
sdkp->zones_max_open = 0;
- } else {
- /* Host-managed */
- sdkp->urswrz = buf[4] & 1;
- sdkp->zones_optimal_open = 0;
- sdkp->zones_optimal_nonseq = 0;
- sdkp->zones_max_open = get_unaligned_be32(&buf[16]);
+ return 0;
}
+ /* Host-managed */
+ sdkp->urswrz = buf[4] & 1;
+ sdkp->zones_optimal_open = 0;
+ sdkp->zones_optimal_nonseq = 0;
+ sdkp->zones_max_open = get_unaligned_be32(&buf[16]);
+
/*
* Check for unconstrained reads: host-managed devices with
* constrained reads (drives failing read after write pointer)
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 198/235] scsi: scsi_debug: Rename zone type constants
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (196 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 197/235] scsi: sd: sd_zbc: Return early in sd_zbc_check_zoned_characteristics() Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 199/235] scsi: scsi_debug: Fix REPORT ZONES alloc_len underflow OOB write Greg Kroah-Hartman
` (39 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Douglas Gilbert, Damien Le Moal,
Bart Van Assche, Martin K. Petersen, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Damien Le Moal <damien.lemoal@opensource.wdc.com>
[ Upstream commit 35dbe2b9a7b0c92777c855c6a2cca8390f4c166b ]
Rename the scsi_debug zone type constants to prevent a conflict with the
ZBC_ZONE_TYPE_GAP constant from include/scsi/scsi_proto.h.
Link: https://lore.kernel.org/r/20220421183023.3462291-9-bvanassche@acm.org
Cc: Douglas Gilbert <dgilbert@interlog.com>
Acked-by: Douglas Gilbert <dgilbert@interlog.com>
Signed-off-by: Damien Le Moal <damien.lemoal@opensource.wdc.com>
[ bvanassche: Extracted these changes from a larger patch ]
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Stable-dep-of: 93dde0bf2f39 ("scsi: scsi_debug: Fix REPORT ZONES alloc_len underflow OOB write")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/scsi/scsi_debug.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -250,9 +250,9 @@ static const char *sdebug_version_date =
/* Zone types (zbcr05 table 25) */
enum sdebug_z_type {
- ZBC_ZONE_TYPE_CNV = 0x1,
- ZBC_ZONE_TYPE_SWR = 0x2,
- ZBC_ZONE_TYPE_SWP = 0x3,
+ ZBC_ZTYPE_CNV = 0x1,
+ ZBC_ZTYPE_SWR = 0x2,
+ ZBC_ZTYPE_SWP = 0x3,
};
/* enumeration names taken from table 26, zbcr05 */
@@ -2681,7 +2681,7 @@ static struct sdeb_zone_state *zbc_zone(
static inline bool zbc_zone_is_conv(struct sdeb_zone_state *zsp)
{
- return zsp->z_type == ZBC_ZONE_TYPE_CNV;
+ return zsp->z_type == ZBC_ZTYPE_CNV;
}
static void zbc_close_zone(struct sdebug_dev_info *devip,
@@ -2780,7 +2780,7 @@ static void zbc_inc_wp(struct sdebug_dev
if (zbc_zone_is_conv(zsp))
return;
- if (zsp->z_type == ZBC_ZONE_TYPE_SWR) {
+ if (zsp->z_type == ZBC_ZTYPE_SWR) {
zsp->z_wp += num;
if (zsp->z_wp >= zend)
zbc_set_zone_full(devip, zsp);
@@ -2847,7 +2847,7 @@ static int check_zbc_access_params(struc
return 0;
}
- if (zsp->z_type == ZBC_ZONE_TYPE_SWR) {
+ if (zsp->z_type == ZBC_ZTYPE_SWR) {
/* Writes cannot cross sequential zone boundaries */
if (zsp_end != zsp) {
mk_sense_buffer(scp, ILLEGAL_REQUEST,
@@ -4913,14 +4913,14 @@ static int sdebug_device_create_zones(st
zsp->z_start = zstart;
if (i < devip->nr_conv_zones) {
- zsp->z_type = ZBC_ZONE_TYPE_CNV;
+ zsp->z_type = ZBC_ZTYPE_CNV;
zsp->z_cond = ZBC_NOT_WRITE_POINTER;
zsp->z_wp = (sector_t)-1;
} else {
if (devip->zmodel == BLK_ZONED_HM)
- zsp->z_type = ZBC_ZONE_TYPE_SWR;
+ zsp->z_type = ZBC_ZTYPE_SWR;
else
- zsp->z_type = ZBC_ZONE_TYPE_SWP;
+ zsp->z_type = ZBC_ZTYPE_SWP;
zsp->z_cond = ZC1_EMPTY;
zsp->z_wp = zsp->z_start;
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 199/235] scsi: scsi_debug: Fix REPORT ZONES alloc_len underflow OOB write
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (197 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 198/235] scsi: scsi_debug: Rename zone type constants Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 200/235] ice: fix VF interrupts cleanup Greg Kroah-Hartman
` (38 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Damien Le Moal, Ibrahim Hashimov,
Bart Van Assche, Martin K. Petersen
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ibrahim Hashimov <security@auditcode.ai>
resp_report_zones() sizes the reply buffer from the CDB allocation
length. The v3 fix rounds alloc_len up with ALIGN() before deriving the
descriptor count:
rep_max_zones = (ALIGN((u64)alloc_len, RZONES_DESC_HD) -
RZONES_DESC_HD) >> ilog2(RZONES_DESC_HD);
arr_len = (u64)RZONES_DESC_HD * (rep_max_zones + 1);
For alloc_len in 0xFFFFFFC1..0xFFFFFFFF, ALIGN() rounds up to
0x100000000, so arr_len is 4 GB. On 32-bit, kzalloc()'s size_t is 32-bit
and truncates 0x100000000 to 0; kzalloc(0) returns ZERO_SIZE_PTR, which
passes the !arr check, and desc = arr + 64 is then dereferenced in the
loop -> out-of-bounds write / panic.
Clamp rep_max_zones to devip->nr_zones. The loop already stops at
sdebug_capacity (after nr_zones zones), so a report can never hold more
than nr_zones descriptors; the clamp does not change the report, it only
bounds arr_len to (nr_zones + 1) * RZONES_DESC_HD, a real device
property that can never reach 0x100000000.
Fixes: 7db0e0c8190a ("scsi: scsi_debug: Fix buffer size of REPORT ZONES command")
Suggested-by: Damien Le Moal <dlemoal@kernel.org>
Cc: stable@vger.kernel.org
Signed-off-by: Ibrahim Hashimov <security@auditcode.ai>
Assisted-by: AuditCode-AI:2026.07
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Link: https://patch.msgid.link/20260712183739.83915-1-security@auditcode.ai
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
[ Adjusted for 5.10: resp_report_zones() here predates commit 4a5fc1c6d752
("scsi: scsi_debug: Add gap zone support"), so it still computes
max_zones = devip->nr_zones - (zs_lba >> devip->zsize_shift);
and bounds the descriptor loop with it. Keep that existing, tighter
clamp instead of introducing a second one against devip->nr_zones:
max_zones is by construction <= devip->nr_zones and is the actual
number of descriptors the loop can emit, so it satisfies the upstream
requirement that arr_len be bounded by a real device property while
leaving the reported zone list unchanged.
Without the fix 5.10 has the same class of bug from the other end of
the range: for alloc_len in 1..63 the unsigned (alloc_len - 64)
underflows, kzalloc(alloc_len) returns a sub-64-byte buffer, and both
the report header at arr + 0 and desc = arr + 64 are written out of
bounds. Sizing the allocation from rep_max_zones rather than from
alloc_len fixes that too. ]
(cherry picked from commit 93dde0bf2f39a0f9f57fd610aa3201ce5b753433)
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/scsi/scsi_debug.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -4320,6 +4320,7 @@ static int resp_report_zones(struct scsi
u32 alloc_len, rep_opts, rep_len;
bool partial;
u64 lba, zs_lba;
+ u64 arr_len;
u8 *arr = NULL, *desc;
u8 *cmd = scp->cmnd;
struct sdeb_zone_state *zsp;
@@ -4343,10 +4344,12 @@ static int resp_report_zones(struct scsi
}
max_zones = devip->nr_zones - (zs_lba >> devip->zsize_shift);
- rep_max_zones = min((alloc_len - 64) >> ilog2(RZONES_DESC_HD),
- max_zones);
+ rep_max_zones = (ALIGN((u64)alloc_len, RZONES_DESC_HD) - RZONES_DESC_HD) >>
+ ilog2(RZONES_DESC_HD);
+ rep_max_zones = min_t(unsigned int, rep_max_zones, max_zones);
+ arr_len = (u64)RZONES_DESC_HD * (rep_max_zones + 1);
- arr = kzalloc(alloc_len, GFP_ATOMIC | __GFP_NOWARN);
+ arr = kzalloc(arr_len, GFP_ATOMIC | __GFP_NOWARN);
if (!arr) {
mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
INSUFF_RES_ASCQ);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 200/235] ice: fix VF interrupts cleanup
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (198 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 199/235] scsi: scsi_debug: Fix REPORT ZONES alloc_len underflow OOB write Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 201/235] ice: fix memory leak in ice_lbtest_prepare_rings() Greg Kroah-Hartman
` (37 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Vladimir Medvedkin,
Aleksandr Loktionov, Dawid Osuchowski, Simon Horman, Patryk Holda,
Tony Nguyen, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dawid Osuchowski <dawid.osuchowski@linux.intel.com>
[ Upstream commit fb096882095e5a8d6b5159e43793d4a38a0c5b1f ]
When a virtual function sends an IRQ map command, the PF will set up
interrupts according to that request. However, because these interrupts are
never reset, the next time Virtual Function initializes, the interrupts are
still enabled for a given VF, which leads to performance degradation in
certain cases due to interrupts being unexpectedly enabled and thus causing
interrupt floods.
Cc: stable@vger.kernel.org
Fixes: 1071a8358a28 ("ice: Implement virtchnl commands for AVF support")
Suggested-by: Vladimir Medvedkin <vladimir.medvedkin@intel.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: Dawid Osuchowski <dawid.osuchowski@linux.intel.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Tested-by: Patryk Holda <patryk.holda@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c | 48 +++++++++++++++++++++++
1 file changed, 48 insertions(+)
--- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c
@@ -1262,6 +1262,30 @@ static bool ice_is_vf_disabled(struct ic
}
/**
+ * ice_reset_interrupts - clear all queue interrupt configuration for a VSI
+ * @vsi: the VSI whose interrupt registers should be cleared
+ *
+ * Zero the QINT_RQCTL and QINT_TQCTL registers for all allocated queues
+ * in the VSI. This clears the entire register including MSIX_INDX, ITR_INDX,
+ * CAUSE_ENA and NEXTQ fields, unlike ice_vf_dis_rxq_interrupt() which only
+ * clears the CAUSE_ENA bit.
+ */
+static void ice_reset_interrupts(struct ice_vsi *vsi)
+{
+ struct ice_pf *pf = vsi->back;
+ struct ice_hw *hw = &pf->hw;
+ int i;
+
+ ice_for_each_alloc_rxq(vsi, i)
+ wr32(hw, QINT_RQCTL(vsi->rxq_map[i]), 0);
+
+ ice_for_each_alloc_txq(vsi, i)
+ wr32(hw, QINT_TQCTL(vsi->txq_map[i]), 0);
+
+ ice_flush(hw);
+}
+
+/**
* ice_reset_vf - Reset a particular VF
* @vf: pointer to the VF structure
* @is_vflr: true if VFLR was issued, false if not
@@ -1304,6 +1328,9 @@ bool ice_reset_vf(struct ice_vf *vf, boo
ice_dis_vf_qs(vf);
+ /* cleanup interrupt registers */
+ ice_reset_interrupts(vsi);
+
/* Call Disable LAN Tx queue AQ whether or not queues are
* enabled. This is needed for successful completion of VFR.
*/
@@ -2582,6 +2609,24 @@ static void ice_vf_ena_rxq_interrupt(str
}
/**
+ * ice_vf_dis_rxq_interrupt - disable Rx queue interrupt via QINT_RQCTL
+ * @vsi: VSI of the VF to configure
+ * @q_idx: VF queue index used to determine the queue in the PF's space
+ */
+static void ice_vf_dis_rxq_interrupt(struct ice_vsi *vsi, u32 q_idx)
+{
+ struct ice_hw *hw = &vsi->back->hw;
+ u32 pfq = vsi->rxq_map[q_idx];
+ u32 reg;
+
+ reg = rd32(hw, QINT_RQCTL(pfq));
+ reg &= ~QINT_RQCTL_CAUSE_ENA_M;
+ wr32(hw, QINT_RQCTL(pfq), reg);
+
+ ice_flush(hw);
+}
+
+/**
* ice_vc_ena_qs_msg
* @vf: pointer to the VF info
* @msg: pointer to the msg buffer
@@ -2753,6 +2798,8 @@ static int ice_vc_dis_qs_msg(struct ice_
goto error_param;
}
+ for_each_set_bit(vf_q_id, &q_map, ICE_MAX_RSS_QS_PER_VF)
+ ice_vf_dis_rxq_interrupt(vsi, vf_q_id);
bitmap_zero(vf->rxq_ena, ICE_MAX_RSS_QS_PER_VF);
} else if (q_map) {
for_each_set_bit(vf_q_id, &q_map, ICE_MAX_RSS_QS_PER_VF) {
@@ -2773,6 +2820,7 @@ static int ice_vc_dis_qs_msg(struct ice_
goto error_param;
}
+ ice_vf_dis_rxq_interrupt(vsi, vf_q_id);
/* Clear enabled queues flag */
clear_bit(vf_q_id, vf->rxq_ena);
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 201/235] ice: fix memory leak in ice_lbtest_prepare_rings()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (199 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 200/235] ice: fix VF interrupts cleanup Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 202/235] i2c: bcm-iproc: remove printout on handled timeouts Greg Kroah-Hartman
` (36 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Dawei Feng, Jacob Keller,
Tony Nguyen, Sasha Levin, Rinitha S
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dawei Feng <dawei.feng@seu.edu.cn>
[ Upstream commit 3a9de5590da4ffd9e9c541c4c4d492aa2b54cf6e ]
ice_lbtest_prepare_rings() frees Rx rings only when
ice_vsi_start_all_rx_rings() fails. If ice_vsi_setup_rx_rings() fails
after allocating some descriptors, or if ice_vsi_cfg_lan() fails after
the Rx rings were prepared, the function reaches the Tx cleanup path
without releasing the initialized Rx resources.
Fix this by adding separate unwind paths for Rx setup failure and LAN
configuration failure. The Rx setup failure path releases the partially
prepared Rx rings before freeing Tx rings, while later failures first
undo the LAN Tx configuration and then release the Rx rings in reverse
setup order.
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-rc7.
An x86_64 allyesconfig build showed no new warnings. As we do not have an
Intel E800 Series adapter available to run the ethtool offline loopback
selftest, no runtime testing was able to be performed.
Fixes: 0e674aeb0b77 ("ice: Add handler for ethtool selftest")
Cc: stable@vger.kernel.org
Signed-off-by: Dawei Feng <dawei.feng@seu.edu.cn>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Rinitha S <sx.rinitha@intel.com> (A Contingent worker at Intel)
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/intel/ice/ice_ethtool.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c
+++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c
@@ -478,18 +478,18 @@ static int ice_lbtest_prepare_rings(stru
status = ice_vsi_cfg(vsi);
if (status)
- goto err_setup_rx_ring;
+ goto err_cfg_lan;
status = ice_vsi_start_all_rx_rings(vsi);
if (status)
- goto err_start_rx_ring;
+ goto err_cfg_lan;
return status;
-err_start_rx_ring:
- ice_vsi_free_rx_rings(vsi);
-err_setup_rx_ring:
+err_cfg_lan:
ice_vsi_stop_lan_tx_rings(vsi, ICE_NO_RESET, 0);
+err_setup_rx_ring:
+ ice_vsi_free_rx_rings(vsi);
err_setup_tx_ring:
ice_vsi_free_tx_rings(vsi);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 202/235] i2c: bcm-iproc: remove printout on handled timeouts
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (200 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 201/235] ice: fix memory leak in ice_lbtest_prepare_rings() Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 203/235] i2c: iproc: reset bus after timeout if START_BUSY is stuck Greg Kroah-Hartman
` (35 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Wolfram Sang, Andi Shyti,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wolfram Sang <wsa+renesas@sang-engineering.com>
[ Upstream commit 796e2c260187e32530cf343546ba1cdf2e2f5491 ]
I2C and SMBus timeouts are not something the user needs to be informed
about on controller level. The client driver may know if that really is
a problem and give more detailed information to the user. The controller
should just pass this information upwards. Remove the printout.
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
Stable-dep-of: 98f2e9e6d6f9 ("i2c: iproc: reset bus after timeout if START_BUSY is stuck")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/i2c/busses/i2c-bcm-iproc.c | 2 --
1 file changed, 2 deletions(-)
--- a/drivers/i2c/busses/i2c-bcm-iproc.c
+++ b/drivers/i2c/busses/i2c-bcm-iproc.c
@@ -789,8 +789,6 @@ static int bcm_iproc_i2c_xfer_wait(struc
}
if (!time_left && !iproc_i2c->xfer_is_done) {
- dev_err(iproc_i2c->device, "transaction timed out\n");
-
/* flush both TX/RX FIFOs */
val = BIT(M_FIFO_RX_FLUSH_SHIFT) | BIT(M_FIFO_TX_FLUSH_SHIFT);
iproc_i2c_wr_reg(iproc_i2c, M_FIFO_CTRL_OFFSET, val);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 203/235] i2c: iproc: reset bus after timeout if START_BUSY is stuck
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (201 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 202/235] i2c: bcm-iproc: remove printout on handled timeouts Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 204/235] fsnotify: opt-in for permission events at file open time Greg Kroah-Hartman
` (34 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jonas Gorski, Ray Jui, Andi Shyti,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonas Gorski <jonas.gorski@bisdn.de>
[ Upstream commit 98f2e9e6d6f91a6abb43f166b244b428ba85fa2b ]
If a transaction times out, the START_BUSY signal can stay up, and
subsequent transactaction attempts will fail as the bus is still
considered busy.
I can easily trigger this by attempting to read from an address with no
device, e.g. when running i2cdetect. After the first read times out, all
subsequent read attempts return busy.
To get to a working state again, the controller needs to be reset to
clear the START_BUSY signal. So check for START_BUSY still asserted on a
timeout, and do reset in case it is,
This is also done by the original non-upstream iproc-smbus driver
implementation [1].
Works around situations like:
bcm-iproc-2c 1803b000.i2c: transaction timed out
bcm-iproc-2c 1803b000.i2c: bus is busy
bcm-iproc-2c 1803b000.i2c: bus is busy
bcm-iproc-2c 1803b000.i2c: bus is busy
bcm-iproc-2c 1803b000.i2c: bus is busy
bcm-iproc-2c 1803b000.i2c: bus is busy
...
where the bus never recovers after a timeout.
[1] https://github.com/opencomputeproject/onie/blob/master/patches/kernel/3.2.69/driver-iproc-smbus.patch
Fixes: e6e5dd3566e0 ("i2c: iproc: Add Broadcom iProc I2C Driver")
Signed-off-by: Jonas Gorski <jonas.gorski@bisdn.de>
Cc: <stable@vger.kernel.org> # v4.0+
Acked-by: Ray Jui <ray.jui@broadcom.com>
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
Link: https://lore.kernel.org/r/20260717085507.34209-1-jonas.gorski@bisdn.de
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/i2c/busses/i2c-bcm-iproc.c | 11 +++++++++++
1 file changed, 11 insertions(+)
--- a/drivers/i2c/busses/i2c-bcm-iproc.c
+++ b/drivers/i2c/busses/i2c-bcm-iproc.c
@@ -789,6 +789,17 @@ static int bcm_iproc_i2c_xfer_wait(struc
}
if (!time_left && !iproc_i2c->xfer_is_done) {
+ /*
+ * The controller may fail to clear START_BUSY after a timeout,
+ * reset the controller to recover in that case.
+ */
+ if (!!(iproc_i2c_rd_reg(iproc_i2c, M_CMD_OFFSET) &
+ BIT(M_CMD_START_BUSY_SHIFT))) {
+ bcm_iproc_i2c_enable_disable(iproc_i2c, false);
+ bcm_iproc_i2c_init(iproc_i2c);
+ bcm_iproc_i2c_enable_disable(iproc_i2c, true);
+ }
+
/* flush both TX/RX FIFOs */
val = BIT(M_FIFO_RX_FLUSH_SHIFT) | BIT(M_FIFO_TX_FLUSH_SHIFT);
iproc_i2c_wr_reg(iproc_i2c, M_FIFO_CTRL_OFFSET, val);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 204/235] fsnotify: opt-in for permission events at file open time
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (202 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 203/235] i2c: iproc: reset bus after timeout if START_BUSY is stuck Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 205/235] fs: dont block write during exec on pre-content watched files Greg Kroah-Hartman
` (33 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Linus Torvalds, Amir Goldstein,
Jan Kara, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amir Goldstein <amir73il@gmail.com>
[ Upstream commit a94204f4d48e28a711b7ed10399f749286c433e3 ]
Legacy inotify/fanotify listeners can add watches for events on inode,
parent or mount and expect to get events (e.g. FS_MODIFY) on files that
were already open at the time of setting up the watches.
fanotify permission events are typically used by Anti-malware sofware,
that is watching the entire mount and it is not common to have more that
one Anti-malware engine installed on a system.
To reduce the overhead of the fsnotify_file_perm() hooks on every file
access, relax the semantics of the legacy FAN_ACCESS_PERM event to generate
events only if there were *any* permission event listeners on the
filesystem at the time that the file was opened.
The new semantic is implemented by extending the FMODE_NONOTIFY bit into
two FMODE_NONOTIFY_* bits, that are used to store a mode for which of the
events types to report.
This is going to apply to the new fanotify pre-content events in order
to reduce the cost of the new pre-content event vfs hooks.
[Thanks to Bert Karwatzki <spasswolf@web.de> for reporting a bug in this
code with CONFIG_FANOTIFY_ACCESS_PERMISSIONS disabled]
Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Link: https://lore.kernel.org/linux-fsdevel/CAHk-=wj8L=mtcRTi=NECHMGfZQgXOp_uix1YVh04fEmrKaMnXA@mail.gmail.com/
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Link: https://patch.msgid.link/5ea5f8e283d1edb55aa79c35187bfe344056af14.1731684329.git.josef@toxicpanda.com
Stable-dep-of: db1856ea9196 ("binfmt_misc: restore write access when removing an entry")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/linux/fs.h | 6 ++++++
1 file changed, 6 insertions(+)
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -179,6 +179,12 @@ typedef int (dio_iodone_t)(struct kiocb
#define FMODE_BUF_RASYNC ((__force fmode_t)0x40000000)
/*
+ * fsnotify pre-content events do not exist in this kernel, so a file is never
+ * watched by a pre-content event listener.
+ */
+#define FMODE_FSNOTIFY_HSM(mode) 0
+
+/*
* Attribute flags. These should be or-ed together to figure out what
* has been changed!
*/
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 205/235] fs: dont block write during exec on pre-content watched files
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (203 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 204/235] fsnotify: opt-in for permission events at file open time Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 206/235] binfmt_misc: restore write access when removing an entry Greg Kroah-Hartman
` (32 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Amir Goldstein, Christian Brauner,
Jan Kara, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amir Goldstein <amir73il@gmail.com>
[ Upstream commit 0357ef03c94ef835bd44a0658b8edb672a9dbf51 ]
Commit 2a010c412853 ("fs: don't block i_writecount during exec") removed
the legacy behavior of getting ETXTBSY on attempt to open and executable
file for write while it is being executed.
This commit was reverted because an application that depends on this
legacy behavior was broken by the change.
We need to allow HSM writing into executable files while executed to
fill their content on-the-fly.
To that end, disable the ETXTBSY legacy behavior for files that are
watched by pre-content events.
This change is not expected to cause regressions with existing systems
which do not have any pre-content event listeners.
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Acked-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Jan Kara <jack@suse.cz>
Link: https://patch.msgid.link/20241128142532.465176-1-amir73il@gmail.com
Stable-dep-of: db1856ea9196 ("binfmt_misc: restore write access when removing an entry")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/binfmt_elf.c | 4 ++--
fs/binfmt_elf_fdpic.c | 4 ++--
fs/exec.c | 6 +++---
include/linux/fs.h | 22 ++++++++++++++++++++++
4 files changed, 29 insertions(+), 7 deletions(-)
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1243,7 +1243,7 @@ out_free_interp:
}
reloc_func_desc = interp_load_addr;
- allow_write_access(interpreter);
+ exe_file_allow_write_access(interpreter);
fput(interpreter);
kfree(interp_elf_ex);
@@ -1332,7 +1332,7 @@ out_free_dentry:
kfree(interp_elf_ex);
kfree(interp_elf_phdata);
out_free_file:
- allow_write_access(interpreter);
+ exe_file_allow_write_access(interpreter);
if (interpreter)
fput(interpreter);
out_free_ph:
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -398,7 +398,7 @@ static int load_elf_fdpic_binary(struct
goto error;
}
- allow_write_access(interpreter);
+ exe_file_allow_write_access(interpreter);
fput(interpreter);
interpreter = NULL;
}
@@ -471,7 +471,7 @@ static int load_elf_fdpic_binary(struct
error:
if (interpreter) {
- allow_write_access(interpreter);
+ exe_file_allow_write_access(interpreter);
fput(interpreter);
}
kfree(interpreter_name);
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -929,7 +929,7 @@ static struct file *do_open_execat(int f
path_noexec(&file->f_path))
goto exit;
- err = deny_write_access(file);
+ err = exe_file_deny_write_access(file);
if (err)
goto exit;
@@ -1485,7 +1485,7 @@ static void free_bprm(struct linux_binpr
abort_creds(bprm->cred);
}
if (bprm->file) {
- allow_write_access(bprm->file);
+ exe_file_allow_write_access(bprm->file);
fput(bprm->file);
}
if (bprm->executable)
@@ -1773,7 +1773,7 @@ static int exec_binprm(struct linux_binp
bprm->file = bprm->interpreter;
bprm->interpreter = NULL;
- allow_write_access(exec);
+ exe_file_allow_write_access(exec);
if (unlikely(bprm->have_execfd)) {
if (bprm->executable) {
fput(exec);
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2987,6 +2987,28 @@ static inline void allow_write_access(st
if (file)
atomic_inc(&file_inode(file)->i_writecount);
}
+
+/*
+ * Do not prevent write to executable file when watched by pre-content events.
+ *
+ * Note that FMODE_FSNOTIFY_HSM mode is set depending on pre-content watches at
+ * the time of file open and remains constant for entire lifetime of the file,
+ * so if pre-content watches are added post execution or removed before the end
+ * of the execution, it will not cause i_writecount reference leak.
+ */
+static inline int exe_file_deny_write_access(struct file *exe_file)
+{
+ if (unlikely(FMODE_FSNOTIFY_HSM(exe_file->f_mode)))
+ return 0;
+ return deny_write_access(exe_file);
+}
+static inline void exe_file_allow_write_access(struct file *exe_file)
+{
+ if (unlikely(!exe_file || FMODE_FSNOTIFY_HSM(exe_file->f_mode)))
+ return;
+ allow_write_access(exe_file);
+}
+
static inline bool inode_is_open_for_write(const struct inode *inode)
{
return atomic_read(&inode->i_writecount) > 0;
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 206/235] binfmt_misc: restore write access when removing an entry
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (204 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 205/235] fs: dont block write during exec on pre-content watched files Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 207/235] can: gs_usb: gs_usb_receive_bulk_callback(): resubmit URB on skb allocation failure Greg Kroah-Hartman
` (31 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Christian Brauner (Amutable),
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Brauner <brauner@kernel.org>
[ Upstream commit db1856ea9196cf6e015d12199a34c0b9313c7bfa ]
Registering an entry with the MISC_FMT_OPEN_FILE flag opens the
interpreter via open_exec() which denies write access to it for as
long as the entry exists. Removing the entry closes the interpreter
file via filp_close() but never restores write access, leaving the
inode's i_writecount permanently negative. Opening the interpreter
for writing keeps failing with ETXTBSY long after the entry is gone
until the inode is evicted from the inode cache.
Commit 90f601b497d7 ("binfmt_misc: restore write access before
closing files opened by open_exec()") fixed the same imbalance in the
error path of bm_register_write() but the actual removal path has
been leaking the write denial since the introduction of the flag.
Restore write access in put_binfmt_handler() before closing the
interpreter file.
Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-1-a162f7cb58d6@kernel.org
Fixes: 948b701a607f ("binfmt_misc: add persistent opened binary handler for containers")
Cc: stable@vger.kernel.org
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
fs/binfmt_misc.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -163,8 +163,10 @@ static Node *get_binfmt_handler(struct l
static void put_binfmt_handler(Node *e)
{
if (refcount_dec_and_test(&e->users)) {
- if (e->flags & MISC_FMT_OPEN_FILE)
+ if (e->flags & MISC_FMT_OPEN_FILE) {
+ exe_file_allow_write_access(e->interp_file);
filp_close(e->interp_file, NULL);
+ }
kfree(e);
}
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 207/235] can: gs_usb: gs_usb_receive_bulk_callback(): resubmit URB on skb allocation failure
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (205 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 206/235] binfmt_misc: restore write access when removing an entry Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 208/235] hwmon: (npcm750-pwm-fan): stop fan timer on device detach Greg Kroah-Hartman
` (30 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, stable, Marc Kleine-Budde,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marc Kleine-Budde <mkl@pengutronix.de>
[ Upstream commit 68c5724ecd159992f76edb7b57dc508a44c8b7da ]
If the allocation of the SKB in gs_usb_receive_bulk_callback() fails, the
driver returns from the callback without resubmitting the URB in order to
receive further USB in URBs.
This results in a silent performance degradation which, if it occurs
repeatedly, results in starvation of USB in traffic.
Instead of returning immediately, try to resend the URB. If this also
fails, this is logged as an info message.
Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices")
Fixes: 26949ac935e3 ("can: gs_usb: add CAN-FD support")
Link: https://patch.msgid.link/20260709-gs_usb-resubmit-urb-v1-1-4dd40030cc84@pengutronix.de
Cc: stable@kernel.org
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/can/usb/gs_usb.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -332,7 +332,7 @@ static void gs_usb_receive_bulk_callback
if (hf->echo_id == -1) { /* normal rx */
skb = alloc_can_skb(dev->netdev, &cf);
if (!skb)
- return;
+ goto resubmit_urb;
cf->can_id = le32_to_cpu(hf->can_id);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 208/235] hwmon: (npcm750-pwm-fan): stop fan timer on device detach
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (206 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 207/235] can: gs_usb: gs_usb_receive_bulk_callback(): resubmit URB on skb allocation failure Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 209/235] drm/amd/pm: fix torn gpu metrics reads Greg Kroah-Hartman
` (29 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Hongyan Xu, Guenter Roeck,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hongyan Xu <getshell@seu.edu.cn>
[ Upstream commit f27f6976ea269219c1259a7c2f8c6dfe782540a3 ]
When a fan tach channel is present, npcm7xx_pwm_fan_probe() starts
fan_timer. The timer callback polls tach state and rearms the timer, but
the driver has no remove callback or devm cleanup action to stop it. On
device detach, the devm-managed driver data and I/O mappings can be
released while the timer is still pending or running.
Register a devm cleanup action before starting the timer and shut the
timer down synchronously from that action.
This issue was found by a static analysis tool.
Fixes: f1fd4a4db777 ("hwmon: Add NPCM7xx PWM and Fan driver")
Cc: stable@vger.kernel.org
Signed-off-by: Hongyan Xu <getshell@seu.edu.cn>
Link: https://lore.kernel.org/r/20260729100116.790-1-getshell@seu.edu.cn
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
[ changed `timer_shutdown_sync()` to `timer_delete_sync()` since the former is absent in 5.10 ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/hwmon/npcm750-pwm-fan.c | 11 +++++++++++
1 file changed, 11 insertions(+)
--- a/drivers/hwmon/npcm750-pwm-fan.c
+++ b/drivers/hwmon/npcm750-pwm-fan.c
@@ -360,6 +360,11 @@ static void npcm7xx_fan_polling(struct t
add_timer(&data->fan_timer);
}
+static void npcm7xx_fan_cleanup(void *timer)
+{
+ timer_delete_sync(timer);
+}
+
static inline void npcm7xx_fan_compute(struct npcm7xx_pwm_fan_data *data,
u8 fan, u8 cmp, u8 fan_id, u8 flag_int,
u8 flag_mode, u8 flag_clear)
@@ -1003,6 +1008,12 @@ static int npcm7xx_pwm_fan_probe(struct
msecs_to_jiffies(NPCM7XX_FAN_POLL_TIMER_200MS);
timer_setup(&data->fan_timer,
npcm7xx_fan_polling, 0);
+ ret = devm_add_action_or_reset(dev,
+ npcm7xx_fan_cleanup,
+ &data->fan_timer);
+ if (ret)
+ return ret;
+
add_timer(&data->fan_timer);
break;
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 209/235] drm/amd/pm: fix torn gpu metrics reads
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (207 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 208/235] hwmon: (npcm750-pwm-fan): stop fan timer on device detach Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 210/235] ALSA: usx2y: Fix potential leaks of uninitialized memory Greg Kroah-Hartman
` (28 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Yang Wang, Kenneth Feng,
Alex Deucher, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yang Wang <kevinyang.wang@amd.com>
[ Upstream commit 048f4541b71fb19645fb79d6e62e6e4da23a4035 ]
amdgpu_dpm_get_gpu_metrics() returns a pointer to the shared metrics cache
after dropping adev->pm.mutex. The sysfs path then copies from that pointer.
Another reader can refresh the cache in place during the copy and return a
snapshot containing data from two generations.
Pass caller-provided storage through the DPM interface and copy the metrics
while the mutex is held. This keeps the cache pointer private and makes each
sysfs read observe one complete sample.
Fixes: 25c933b1c4fc ("drm/amd/powerplay: add new sysfs interface for retrieving gpu metrics(V2)")
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 862333bb48693ecafcae25af0c9d9ec31015ac77)
Cc: stable@vger.kernel.org
[ applied the fix at the sole caller `amdgpu_get_gpu_metrics()` since 5.10 lacks the `amdgpu_dpm_get_gpu_metrics()` wrapper function, wrapping both the swsmu and pp_funcs dispatch branches in `adev->pm.mutex` ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpu/drm/amd/pm/amdgpu_pm.c | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
--- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
@@ -1994,20 +1994,18 @@ static ssize_t amdgpu_get_gpu_metrics(st
return ret;
}
+ mutex_lock(&adev->pm.mutex);
if (is_support_sw_smu(adev))
size = smu_sys_get_gpu_metrics(&adev->smu, &gpu_metrics);
else if (adev->powerplay.pp_funcs->get_gpu_metrics)
size = amdgpu_dpm_get_gpu_metrics(adev, &gpu_metrics);
- if (size <= 0)
- goto out;
-
- if (size >= PAGE_SIZE)
- size = PAGE_SIZE - 1;
-
- memcpy(buf, gpu_metrics, size);
+ if (size > 0) {
+ size = min_t(ssize_t, size, PAGE_SIZE - 1);
+ memcpy(buf, gpu_metrics, size);
+ }
+ mutex_unlock(&adev->pm.mutex);
-out:
pm_runtime_mark_last_busy(ddev->dev);
pm_runtime_put_autosuspend(ddev->dev);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 210/235] ALSA: usx2y: Fix potential leaks of uninitialized memory
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (208 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 209/235] drm/amd/pm: fix torn gpu metrics reads Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 211/235] ALSA: usx2y: bound the hwdep mmap fault offset Greg Kroah-Hartman
` (27 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Takashi Iwai, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <tiwai@suse.de>
[ Upstream commit 4e268db74770b454b877ab5260f1868a457d212c ]
usx2y drivers may expose the allocated pages via mmap, but it performs
zero-clear only for the struct size, not aligned with the page size.
This leaves out some uninitialized trailing bytes.
This patch fixes the clearance to cover all memory that are exposed to
user-space.
Link: https://lore.kernel.org/r/20210517131545.27252-5-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Stable-dep-of: 2ca1eea3cd17 ("ALSA: usx2y: bound the hwdep mmap fault offset")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
sound/usb/usx2y/usX2Yhwdep.c | 8 ++++----
sound/usb/usx2y/usbus428ctldefs.h | 2 ++
sound/usb/usx2y/usbusx2y.c | 2 +-
sound/usb/usx2y/usx2yhwdeppcm.c | 13 ++++++++-----
4 files changed, 15 insertions(+), 10 deletions(-)
--- a/sound/usb/usx2y/usX2Yhwdep.c
+++ b/sound/usb/usx2y/usX2Yhwdep.c
@@ -55,17 +55,17 @@ static int snd_us428ctls_mmap(struct snd
return -EBUSY;
/* if userspace tries to mmap beyond end of our buffer, fail */
- if (size > PAGE_ALIGN(sizeof(struct us428ctls_sharedmem))) {
- snd_printd("%lu > %lu\n", size, (unsigned long)sizeof(struct us428ctls_sharedmem));
+ if (size > US428_SHAREDMEM_PAGES) {
+ snd_printd("%lu > %lu\n", size, (unsigned long)US428_SHAREDMEM_PAGES);
return -EINVAL;
}
if (!us428->us428ctls_sharedmem) {
init_waitqueue_head(&us428->us428ctls_wait_queue_head);
- us428->us428ctls_sharedmem = alloc_pages_exact(sizeof(struct us428ctls_sharedmem), GFP_KERNEL);
+ us428->us428ctls_sharedmem = alloc_pages_exact(US428_SHAREDMEM_PAGES, GFP_KERNEL);
if (!us428->us428ctls_sharedmem)
return -ENOMEM;
- memset(us428->us428ctls_sharedmem, -1, sizeof(struct us428ctls_sharedmem));
+ memset(us428->us428ctls_sharedmem, -1, US428_SHAREDMEM_PAGES);
us428->us428ctls_sharedmem->ctl_snapshot_last = -2;
}
area->vm_ops = &us428ctls_vm_ops;
--- a/sound/usb/usx2y/usbus428ctldefs.h
+++ b/sound/usb/usx2y/usbus428ctldefs.h
@@ -89,3 +89,5 @@ struct us428ctls_sharedmem {
struct us428_p4out p4out[N_US428_P4OUT_BUFS];
int p4out_last, p4out_sent;
};
+
+#define US428_SHAREDMEM_PAGES PAGE_ALIGN(sizeof(struct us428ctls_sharedmem))
--- a/sound/usb/usx2y/usbusx2y.c
+++ b/sound/usb/usx2y/usbusx2y.c
@@ -376,7 +376,7 @@ static void snd_usx2y_card_private_free(
usb_free_urb(usx2y->in04_urb);
if (usx2y->us428ctls_sharedmem)
free_pages_exact(usx2y->us428ctls_sharedmem,
- sizeof(*usx2y->us428ctls_sharedmem));
+ US428_SHAREDMEM_PAGES);
if (usx2y->card_index >= 0 && usx2y->card_index < SNDRV_CARDS)
snd_usx2y_card_used[usx2y->card_index] = 0;
}
--- a/sound/usb/usx2y/usx2yhwdeppcm.c
+++ b/sound/usb/usx2y/usx2yhwdeppcm.c
@@ -485,6 +485,9 @@ static int usx2y_usbpcm_urbs_start(struc
return err;
}
+#define USX2Y_HWDEP_PCM_PAGES \
+ PAGE_ALIGN(sizeof(struct snd_usx2y_hwdep_pcm_shm))
+
/*
* prepare callback
*
@@ -501,11 +504,11 @@ static int snd_usx2y_usbpcm_prepare(stru
snd_printdd("snd_usx2y_pcm_prepare(%p)\n", substream);
if (!usx2y->hwdep_pcm_shm) {
- usx2y->hwdep_pcm_shm = alloc_pages_exact(sizeof(struct snd_usx2y_hwdep_pcm_shm),
+ usx2y->hwdep_pcm_shm = alloc_pages_exact(USX2Y_HWDEP_PCM_PAGES,
GFP_KERNEL);
if (!usx2y->hwdep_pcm_shm)
return -ENOMEM;
- memset(usx2y->hwdep_pcm_shm, 0, sizeof(struct snd_usx2y_hwdep_pcm_shm));
+ memset(usx2y->hwdep_pcm_shm, 0, USX2Y_HWDEP_PCM_PAGES);
}
mutex_lock(&usx2y->pcm_mutex);
@@ -692,8 +695,8 @@ static int snd_usx2y_hwdep_pcm_mmap(stru
return -EBUSY;
/* if userspace tries to mmap beyond end of our buffer, fail */
- if (size > PAGE_ALIGN(sizeof(struct snd_usx2y_hwdep_pcm_shm))) {
- snd_printd("%lu > %lu\n", size, (unsigned long)sizeof(struct snd_usx2y_hwdep_pcm_shm));
+ if (size > USX2Y_HWDEP_PCM_PAGES) {
+ snd_printd("%lu > %lu\n", size, (unsigned long)USX2Y_HWDEP_PCM_PAGES);
return -EINVAL;
}
@@ -711,7 +714,7 @@ static void snd_usx2y_hwdep_pcm_private_
struct usx2ydev *usx2y = hwdep->private_data;
if (usx2y->hwdep_pcm_shm)
- free_pages_exact(usx2y->hwdep_pcm_shm, sizeof(struct snd_usx2y_hwdep_pcm_shm));
+ free_pages_exact(usx2y->hwdep_pcm_shm, USX2Y_HWDEP_PCM_PAGES);
}
int usx2y_hwdep_pcm_new(struct snd_card *card)
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 211/235] ALSA: usx2y: bound the hwdep mmap fault offset
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (209 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 210/235] ALSA: usx2y: Fix potential leaks of uninitialized memory Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 212/235] sched/psi: Shut down rtpoll_timer in psi_cgroup_free() Greg Kroah-Hartman
` (26 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Federico Kirschbaum, Baul Lee,
Takashi Iwai, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baul Lee <baul.lee@xbow.com>
[ Upstream commit 2ca1eea3cd17930daffe9e429a7c89232036ec24 ]
snd_us428ctls_vm_fault() turns the faulting page offset into a kernel
address with no bound of any kind:
offset = vmf->pgoff << PAGE_SHIFT;
vaddr = (char *)(...)->us428ctls_sharedmem + offset;
page = virt_to_page(vaddr);
get_page(page);
vmf->page = page;
return 0;
snd_us428ctls_mmap() checks only the length of the mapping, never the
offset, and us428ctls_sharedmem is a single page from
alloc_pages_exact(). For a character device file_mmap_size_max()
returns ULONG_MAX, so the mm layer imposes no ceiling either. Every page
offset above zero resolves to a struct page outside the object, and the
handler installs it into the caller's address space read-write; the vma
is not marked read-only.
The caller picks the page frame with a single mmap() argument and gets
read-write access to a page of kernel memory it does not own; an offset
that lands in an unpopulated vmemmap region oopses instead.
A process that can open the hwdep node of an attached US-X2Y reaches
this after loading the FPGA image through the same node; no capability
check is involved.
On 7.2.0-rc5 (arm64), mmap() with a large offset:
Unable to handle kernel paging request at virtual address fffffdffc45d5ac8
pc : snd_us428ctls_vm_fault+0x68/0x140 [snd_usb_usx2y]
Call trace:
snd_us428ctls_vm_fault+0x68/0x140 [snd_usb_usx2y]
__do_fault
__handle_mm_fault
handle_mm_fault
el0_da
Reject any offset outside the shared region. The pcm hwdep handler in
usx2yhwdeppcm.c computes its address the same way and needs the same
bound.
Discovered by XBOW, triaged by Baul Lee <baul.lee@xbow.com>
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reported-by: Federico Kirschbaum <federico.kirschbaum@xbow.com>
Reported-by: Baul Lee <baul.lee@xbow.com>
Cc: stable@vger.kernel.org
Signed-off-by: Baul Lee <baul.lee@xbow.com>
Link: https://patch.msgid.link/20260805013445.38283-1-baul.lee@xbow.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/usb/usx2y/usX2Yhwdep.c | 2 ++
sound/usb/usx2y/usx2yhwdeppcm.c | 2 ++
2 files changed, 4 insertions(+)
--- a/sound/usb/usx2y/usX2Yhwdep.c
+++ b/sound/usb/usx2y/usX2Yhwdep.c
@@ -29,6 +29,8 @@ static vm_fault_t snd_us428ctls_vm_fault
vmf->pgoff);
offset = vmf->pgoff << PAGE_SHIFT;
+ if (offset >= US428_SHAREDMEM_PAGES)
+ return VM_FAULT_SIGBUS;
vaddr = (char *)((struct usx2ydev *)vmf->vma->vm_private_data)->us428ctls_sharedmem + offset;
page = virt_to_page(vaddr);
get_page(page);
--- a/sound/usb/usx2y/usx2yhwdeppcm.c
+++ b/sound/usb/usx2y/usx2yhwdeppcm.c
@@ -674,6 +674,8 @@ static vm_fault_t snd_usx2y_hwdep_pcm_vm
void *vaddr;
offset = vmf->pgoff << PAGE_SHIFT;
+ if (offset >= USX2Y_HWDEP_PCM_PAGES)
+ return VM_FAULT_SIGBUS;
vaddr = (char *)((struct usx2ydev *)vmf->vma->vm_private_data)->hwdep_pcm_shm + offset;
vmf->page = virt_to_page(vaddr);
get_page(vmf->page);
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 212/235] sched/psi: Shut down rtpoll_timer in psi_cgroup_free()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (210 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 211/235] ALSA: usx2y: bound the hwdep mmap fault offset Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 213/235] net/sched: act_gact, act_police: range check the fallback control action Greg Kroah-Hartman
` (25 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sashiko AI, Tejun Heo,
Johannes Weiner, Matt Fleming, Suren Baghdasaryan, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tejun Heo <tj@kernel.org>
[ Upstream commit 5457025fa8ca3c0d2732109513de839e3e797190 ]
psi_schedule_rtpoll_work() is called locklessly from the scheduler hotpath
and can race psi_trigger_destroy() taking down the last rtpoll trigger under
rtpoll_trigger_lock:
psi_schedule_rtpoll_work() psi_trigger_destroy()
rcu_read_lock();
task = rcu_dereference(rtpoll_task);
rcu_assign_pointer(rtpoll_task, NULL);
timer_delete(&rtpoll_timer);
mod_timer(&rtpoll_timer, ...);
rcu_read_unlock();
synchronize_rcu();
kthread_stop(task_to_destroy);
The group can then be freed with the re-armed timer still pending, and
poll_timer_fn() runs on freed memory.
461daba06bdc ("psi: eliminate kthread_worker from psi trigger scheduling
mechanism") deleted the timer synchronously after the synchronize_rcu(),
which prevented this but raced trigger creation instead: the deletion could
cancel the timer that a new trigger set armed during the grace period and,
as creation also reinitialized the timer at the time, corrupt it.
8f91efd870ea ("psi: Fix race between psi_trigger_create/destroy") moved the
initialization into group_init() and the deletion into the locked section,
trading the creation races for the window above.
Neither placement in the destruction path works. A pending timer firing
while the group is alive is harmless though. poll_timer_fn() just wakes the
rtpoll waitqueue and doesn't re-arm itself. Bind the timer to the group's
lifetime instead and shut it down in psi_cgroup_free(). Nothing can arm it
by then. timer_shutdown_sync() because the timer is never armed again.
Fixes: 8f91efd870ea ("psi: Fix race between psi_trigger_create/destroy")
Cc: stable@vger.kernel.org # v5.10+
Reported-by: Sashiko AI <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/all/20260711000434.36C4A1F000E9@smtp.kernel.org/
Signed-off-by: Tejun Heo <tj@kernel.org>
Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Tested-by: Matt Fleming <mfleming@cloudflare.com>
Acked-by: Suren Baghdasaryan <surenb@google.com>
[ Adapted `cgroup->psi->` to embedded `cgroup->psi.`, `rtpoll_timer` to `poll_timer`, and `timer_shutdown_sync()` to `timer_delete_sync()`. ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
kernel/sched/psi.c | 6 ++++++
1 file changed, 6 insertions(+)
--- a/kernel/sched/psi.c
+++ b/kernel/sched/psi.c
@@ -950,6 +950,12 @@ void psi_cgroup_free(struct cgroup *cgro
return;
cancel_delayed_work_sync(&cgroup->psi.avgs_work);
+ /*
+ * A psi_schedule_poll_work() call racing the last trigger's
+ * destruction may have re-armed the timer after psi_trigger_destroy()
+ * deleted it. Spurious firing while the group is alive is harmless.
+ */
+ timer_delete_sync(&cgroup->psi.poll_timer);
free_percpu(cgroup->psi.pcpu);
/* All triggers must be removed by now */
WARN_ONCE(cgroup->psi.poll_states, "psi: trigger leak\n");
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 213/235] net/sched: act_gact, act_police: range check the fallback control action
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (211 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 212/235] sched/psi: Shut down rtpoll_timer in psi_cgroup_free() Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 214/235] mm/ptdump: always stabilise against page table freeing using init_mm Greg Kroah-Hartman
` (24 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Hyunjung Ko, Jamal Hadi Salim,
Victor Nogueira, Jakub Kicinski, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hyunjung Ko <hj351016@gmail.com>
[ Upstream commit 883b56ae58fe657d8497806c7059646e9ba6dbd0 ]
tcf_action_check_ctrlact() range checks the primary control action:
if (!opcode)
ret = action > TC_ACT_VALUE_MAX ? -EINVAL : 0;
TC_ACT_VALUE_MAX is TC_ACT_TRAP, so kernel-internal verdicts above it
cannot be set that way. But act_gact and act_police each carry a second,
independent control action supplied by user space that never reaches that
helper - TCA_GACT_PROB.paction and TCA_POLICE_RESULT. Both only reject
TC_ACT_GOTO_CHAIN, so any other value is stored verbatim and returned
verbatim from the action.
In particular user space can store TC_ACT_CONSUMED, which is
TC_ACT_VALUE_MAX + 1 and is deliberately not part of the UAPI value
range. That verdict tells every caller the action took ownership of the
skb, so nobody frees it: sch_handle_ingress(), sch_handle_egress() and
tcf_qevent_handle() all deliberately skip the free for it. The result is
one leaked sk_buff plus its data buffer per packet traversing the filter,
unbounded, for all traffic on the chain including kernel-generated
packets.
Both are trivially deterministic. act_gact clamps tcfg_pval to >= 1, so
with pval = 1 gact_determ() returns the fallback for every packet.
act_police has no mandatory rate, so rate = 0 leaves tcfp_mtu = ~0 and
tcf_police_mtu_check() always passes.
TC_ACT_CONSUMED was added by commit 720f22fed81b ("net: sched: refactor
reinsert action"), after both goto-chain guards were written:
commit 9469f375ab09 ("net/sched: act_gact: disallow 'goto chain' on
fallback control action") and
commit c08f5ed5d625 ("net/sched: act_police: disallow 'goto chain' on
fallback control action"). Neither guard was widened when the new
verdict appeared.
Factor the existing range test out of tcf_action_check_ctrlact() as
tcf_action_valid() and apply it to both fallbacks. The helper cannot call
tcf_action_check_ctrlact() directly because that also allocates a
goto_chain, which is exactly what these two sites must not do.
Reproduced on v7.2-rc6: kmemleak reports one leaked 232-byte
skbuff_head_cache object plus its 704-byte data buffer per packet. With
this patch both configurations are rejected with -EINVAL and kmemleak
reports none.
Fixes: 720f22fed81b ("net: sched: refactor reinsert action")
Cc: stable@vger.kernel.org # v5.3+
Signed-off-by: Hyunjung Ko <hj351016@gmail.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Tested-by: Victor Nogueira <victor@mojatatu.com>
Link: https://patch.msgid.link/20260806101252.809593-1-hj351016@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
[ Kept only the new helper lines and dropped the surrounding upstream-only context (CONFIG_INET/tcf_frag_xmit_count block) absent in 5.10. ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
include/net/act_api.h | 20 ++++++++++++++++++++
net/sched/act_gact.c | 5 +++++
net/sched/act_police.c | 6 ++++++
3 files changed, 31 insertions(+)
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -240,6 +240,26 @@ int tcf_action_check_ctrlact(int action,
struct netlink_ext_ack *newchain);
struct tcf_chain *tcf_action_set_ctrlact(struct tc_action *a, int action,
struct tcf_chain *newchain);
+
+/* Range check for a control action supplied by user space.
+ *
+ * This is the same test tcf_action_check_ctrlact() applies to the primary
+ * control action, factored out for the *fallback* control actions
+ * (act_gact's TCA_GACT_PROB.paction and act_police's TCA_POLICE_RESULT),
+ * which must not reach tcf_action_check_ctrlact() because they have no
+ * goto_chain to allocate. Without it, user space can store kernel-internal
+ * verdicts such as TC_ACT_CONSUMED, which is TC_ACT_VALUE_MAX + 1 and is
+ * deliberately not part of the UAPI value range.
+ */
+static inline bool tcf_action_valid(int action)
+{
+ int opcode = TC_ACT_EXT_OPCODE(action);
+
+ if (!opcode)
+ return action <= TC_ACT_VALUE_MAX;
+ return opcode <= TC_ACT_EXT_OPCODE_MAX || action == TC_ACT_UNSPEC;
+}
+
#endif /* CONFIG_NET_CLS_ACT */
static inline void tcf_action_stats_update(struct tc_action *a, u64 bytes,
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -89,6 +89,11 @@ static int tcf_gact_init(struct net *net
p_parm = nla_data(tb[TCA_GACT_PROB]);
if (p_parm->ptype >= MAX_RAND)
return -EINVAL;
+ if (!tcf_action_valid(p_parm->paction)) {
+ NL_SET_ERR_MSG(extack,
+ "invalid fallback control action");
+ return -EINVAL;
+ }
if (TC_ACT_EXT_CMP(p_parm->paction, TC_ACT_GOTO_CHAIN)) {
NL_SET_ERR_MSG(extack,
"goto chain not allowed on fallback");
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -134,6 +134,12 @@ static int tcf_police_init(struct net *n
if (tb[TCA_POLICE_RESULT]) {
tcfp_result = nla_get_u32(tb[TCA_POLICE_RESULT]);
+ if (!tcf_action_valid(tcfp_result)) {
+ NL_SET_ERR_MSG(extack,
+ "invalid fallback control action");
+ err = -EINVAL;
+ goto failure;
+ }
if (TC_ACT_EXT_CMP(tcfp_result, TC_ACT_GOTO_CHAIN)) {
NL_SET_ERR_MSG(extack,
"goto chain not allowed on fallback");
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 214/235] mm/ptdump: always stabilise against page table freeing using init_mm
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (212 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 213/235] net/sched: act_gact, act_police: range check the fallback control action Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 215/235] net: atlantic: free stranded TX buffers on ring deinit Greg Kroah-Hartman
` (23 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Lorenzo Stoakes (ARM),
Mike Rapoport (Microsoft), David Hildenbrand (Arm),
Kiryl Shutsemau, Andy Lutomirski, Borah, Chaitanya Kumar,
Borislav Petkov (AMD), Catalin Marinas, Dave Hansen,
David Carlier, Dev Jain, H. Peter Anvin, Ingo Molnar,
Liam R. Howlett, Michal Hocko, Peter Zijlstra, Ryan Roberts,
Shakeel Butt, Suren Baghdasaryan, Toshi Kani,
Uladzislau Rezki (Sony), Vlastimil Babka, Will Deacon,
Andrew Morton, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: "Lorenzo Stoakes (ARM)" <ljs@kernel.org>
[ Upstream commit 27c32e5538344b13c1505a08861e04620c125d47 ]
Previous commits have established the invariant that kernel page table
freeing is performed while an mmap read lock on init_mm is held, which
fixes races between ptdump and kernel page table freeing over init_mm.
However, x86 and arm64 can perform a ptdump over an mm other than init_mm
via ptdump_walk_pgd() and since kernel memory ranges are shared across
non-kernel mm's, this means that the race still exists for these cases.
Fix this by acquiring a nested mmap write lock for init_mm in
ptdump_walk_pgd().
This is safe as we take this after mmap write locking the mm, and nothing
acquires the init_mm lock first before locking an arbitrary mm, so no
deadlock is possible.
Also update walk_page_range_debug() to assert that init_mm is write
locked, add a comment explaining why and remove some redundant code, and
eliminate the unnecessary and confusing invocation of
walk_kernel_page_table_range().
We can safely remove the non-NULL check for walk.mm, as the mmap lock
asserts would NULL pointer deref if it was (and of course no callers do
this).
The first point at which ptdump can race kernel page table freeing is
commit b6bdb7517c3d ("mm/vmalloc: add interfaces to free unmapped page
table"), so we target this in the Fixes tag.
Link: https://lore.kernel.org/20260723-series-vmap-race-fix-v6-4-8cc77dcc0018@kernel.org
Fixes: b6bdb7517c3d ("mm/vmalloc: add interfaces to free unmapped page table")
Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Acked-by: David Hildenbrand (Arm) <david@kernel.org>
Reviewed-by: Kiryl Shutsemau <kas@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: "Borah, Chaitanya Kumar" <chaitanya.kumar.borah@intel.com>
Cc: "Borislav Petkov (AMD)" <bp@alien8.de>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: David Carlier <devnexen@gmail.com>
Cc: Dev Jain <dev.jain@arm.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Liam R. Howlett <liam@infradead.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Toshi Kani <toshi.kani@hpe.com>
Cc: "Uladzislau Rezki (Sony)" <urezki@gmail.com>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: Will Deacon <will@kernel.org>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
[ Adapted the hunk to `walk_page_range_novma()` since 5.15 lacks the `walk_page_range_debug()` rename and the `walk_kernel_page_table_range()` dispatch, keeping the existing `!walk.mm` guard. ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
mm/pagewalk.c | 8 ++++++++
mm/ptdump.c | 7 +++++++
2 files changed, 15 insertions(+)
--- a/mm/pagewalk.c
+++ b/mm/pagewalk.c
@@ -457,6 +457,14 @@ int walk_page_range_novma(struct mm_stru
return -EINVAL;
mmap_assert_write_locked(walk.mm);
+ /*
+ * x86, arm64 ptdump allow walks of efi mm's and x86 ptdump allows walks
+ * of arbitrary mm's.
+ *
+ * However, they both must also hold the init_mm lock to account for
+ * concurrent kernel page table freeing.
+ */
+ mmap_assert_write_locked(&init_mm);
return walk_pgd_range(start, end, &walk);
}
--- a/mm/ptdump.c
+++ b/mm/ptdump.c
@@ -143,11 +143,18 @@ void ptdump_walk_pgd(struct ptdump_state
get_online_mems();
mmap_write_lock(mm);
+ /* To stabilise kernel page tables we must hold the init_mm lock too. */
+ if (mm != &init_mm)
+ mmap_write_lock_nested(&init_mm, SINGLE_DEPTH_NESTING);
+
while (range->start != range->end) {
walk_page_range_novma(mm, range->start, range->end,
&ptdump_ops, pgd, st);
range++;
}
+
+ if (mm != &init_mm)
+ mmap_write_unlock(&init_mm);
mmap_write_unlock(mm);
put_online_mems();
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 215/235] net: atlantic: free stranded TX buffers on ring deinit
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (213 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 214/235] mm/ptdump: always stabilise against page table freeing using init_mm Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 216/235] arm64: tegra: Add EL2 virtual timer interrupt for Tegra194 Greg Kroah-Hartman
` (22 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Sukhdeep Singh, Yangyu Chen,
Mina Almasry, Jakub Kicinski, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yangyu Chen <cyy@cyyself.name>
commit 452636ea5410a96e02ebaaf80b21e3620b98e0dd upstream.
aq_vec_deinit() drains the TX rings with a single aq_ring_tx_clean()
call, which frees at most AQ_CFG_TX_CLEAN_BUDGET (256) descriptors and
stops at hw_head, which no longer moves once aq_vec_stop() has stopped
the hardware and NAPI. Completed descriptors beyond the budget and
everything still posted in [hw_head, sw_tail) keep their skb or
xdp_frame when the interface goes down: aq_vec_ring_free() then frees
the buffer ring and the references are lost for good.
Today this is a silent memory leak on every interface down under
TX/XDP_TX load. With the conversion of the RX path to page_pool posted
for net-next it becomes much more visible: XDP_TX frames carry fragment
references on the RX ring's page_pool, so a single stranded frame keeps
the pool's inflight count above zero forever. page_pool_destroy() then
never completes, the pool is leaked together with its pages, and
"page_pool_release_retry() stalled pool shutdown" is warned every 60
seconds from that point on, on every ifdown, XDP detach or ring resize
under XDP_TX load.
Bring back aq_ring_tx_deinit() as it was before the removal and use it
for teardown again, with one extension: TX rings can hold xdp_frames
nowadays, so release those too. They are returned with
xdp_return_frame() since this runs in process context.
Fixes: eb36bedf28be ("net: aquantia: remove function aq_ring_tx_deinit")
Cc: stable@vger.kernel.org # v4.11+
Reviewed-by: Sukhdeep Singh <sukhdeeps@marvell.com>
Signed-off-by: Yangyu Chen <cyy@cyyself.name>
Acked-by: Mina Almasry <almasrymina@google.com>
Link: https://patch.msgid.link/tencent_EEDC35FAF2750A3A6A0B39BAE0E2C484860A@qq.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
[ Dropped the XDP frame arm from the new teardown loop since `buff->xdpf` and `xdp_return_frame()` don't exist in 5.15, and omitted the `aq_xdp_xmit()` context line in the header hunk. ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/aquantia/atlantic/aq_ring.c | 25 +++++++++++++++++++++++
drivers/net/ethernet/aquantia/atlantic/aq_ring.h | 1
drivers/net/ethernet/aquantia/atlantic/aq_vec.c | 2 -
3 files changed, 27 insertions(+), 1 deletion(-)
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
@@ -314,6 +314,31 @@ bool aq_ring_tx_clean(struct aq_ring_s *
return !!budget;
}
+void aq_ring_tx_deinit(struct aq_ring_s *self)
+{
+ if (!self)
+ return;
+
+ for (; self->sw_head != self->sw_tail;
+ self->sw_head = aq_ring_next_dx(self, self->sw_head)) {
+ struct aq_ring_buff_s *buff = &self->buff_ring[self->sw_head];
+ struct device *ndev = aq_nic_get_dev(self->aq_nic);
+
+ if (buff->is_mapped) {
+ if (buff->is_sop) {
+ dma_unmap_single(ndev, buff->pa, buff->len,
+ DMA_TO_DEVICE);
+ } else {
+ dma_unmap_page(ndev, buff->pa, buff->len,
+ DMA_TO_DEVICE);
+ }
+ }
+
+ if (buff->is_eop && buff->skb)
+ dev_kfree_skb_any(buff->skb);
+ }
+}
+
static void aq_rx_checksum(struct aq_ring_s *self,
struct aq_ring_buff_s *buff,
struct sk_buff *skb)
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h
@@ -182,6 +182,7 @@ void aq_ring_update_queue_state(struct a
void aq_ring_queue_wake(struct aq_ring_s *ring);
void aq_ring_queue_stop(struct aq_ring_s *ring);
bool aq_ring_tx_clean(struct aq_ring_s *self);
+void aq_ring_tx_deinit(struct aq_ring_s *self);
int aq_ring_rx_clean(struct aq_ring_s *self,
struct napi_struct *napi,
int *work_done,
--- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c
@@ -270,7 +270,7 @@ void aq_vec_deinit(struct aq_vec_s *self
for (i = 0U; self->tx_rings > i; ++i) {
ring = self->ring[i];
- aq_ring_tx_clean(&ring[AQ_VEC_TX_ID]);
+ aq_ring_tx_deinit(&ring[AQ_VEC_TX_ID]);
aq_ring_rx_deinit(&ring[AQ_VEC_RX_ID]);
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 216/235] arm64: tegra: Add EL2 virtual timer interrupt for Tegra194
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (214 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 215/235] net: atlantic: free stranded TX buffers on ring deinit Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 217/235] crypto: ccm - Set rfc4309 maxauthsize from child Greg Kroah-Hartman
` (21 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Jon Hunter, Thierry Reding,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jon Hunter <jonathanh@nvidia.com>
[ Upstream commit a7c28483fd57dd0e1487024af70622315320774b ]
Commit d87773de9efe ("clocksource/drivers/arm_arch_timer: Default to EL2
virtual timer when running VHE") updated the ARM arch timer driver to
use the virtual timer by default if the CPU is running at EL2 with VHE
enabled. If the CPU is running at EL2 with VHE enabled but there is no
interrupt provided for the virtual timer, then the following warning is
displayed:
arch_timer: [Firmware Bug]: VHE-capable CPU without EL2 virtual timer
interrupt
This warning is observed on Tegra194 platforms. Tegra194 SoC includes
NVIDIA Carmel ARM v8.2 CPUs and support an EL2 virtual timer. Fix the
above warning by adding the PPI for the EL2 virtual timer interrupt for
Tegra194.
Fixes: 5425fb15d8ee ("arm64: tegra: Add Tegra194 chip device tree")
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
arch/arm64/boot/dts/nvidia/tegra194.dtsi | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm64/boot/dts/nvidia/tegra194.dtsi b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
index 05cf606b85c9f..b38c16f25f1ff 100644
--- a/arch/arm64/boot/dts/nvidia/tegra194.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
@@ -2375,6 +2375,8 @@ timer {
<GIC_PPI 11
(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 10
+ (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 15
(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
interrupt-parent = <&gic>;
always-on;
--
2.53.0
^ permalink raw reply related [flat|nested] 239+ messages in thread
* [PATCH 5.10 217/235] crypto: ccm - Set rfc4309 maxauthsize from child
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (215 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 216/235] arm64: tegra: Add EL2 virtual timer interrupt for Tegra194 Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 218/235] netfilter: ipset: fix refcount race between list:set GC and swap Greg Kroah-Hartman
` (20 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Seohyeon Maeng, Herbert Xu,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Herbert Xu <herbert@gondor.apana.org.au>
[ Upstream commit 438f4896f78f69ec73d5f32d2c024193f1223569 ]
Set the maxauthsize of rfc4309 using that of the child algorithm.
Fixes: 4a49b499dfa0 ("[CRYPTO] ccm: Added CCM mode")
Reported-by: Seohyeon Maeng <bioloidgp@gmail.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
crypto/ccm.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/crypto/ccm.c b/crypto/ccm.c
index 494d709011862..52ace42e11e82 100644
--- a/crypto/ccm.c
+++ b/crypto/ccm.c
@@ -752,7 +752,7 @@ static int crypto_rfc4309_create(struct crypto_template *tmpl,
inst->alg.ivsize = 8;
inst->alg.chunksize = crypto_aead_alg_chunksize(alg);
- inst->alg.maxauthsize = 16;
+ inst->alg.maxauthsize = crypto_aead_alg_maxauthsize(alg);
inst->alg.base.cra_ctxsize = sizeof(struct crypto_rfc4309_ctx);
--
2.53.0
^ permalink raw reply related [flat|nested] 239+ messages in thread
* [PATCH 5.10 218/235] netfilter: ipset: fix refcount race between list:set GC and swap
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (216 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 217/235] crypto: ccm - Set rfc4309 maxauthsize from child Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 219/235] netfilter: nf_tables_offload: suppress WARN_ON_ONCE for ENOMEM in abort path Greg Kroah-Hartman
` (19 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, AutonomousCodeSecurity,
Xiang Mei (Microsoft), Jozsef Kadlecsik, Pablo Neira Ayuso,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei (Microsoft) <xmei5@asu.edu>
[ Upstream commit 0c88868271653537ed443272dd8e7d13634d214b ]
__ip_set_put_byindex() resolved the index to a set pointer under RCU,
then took ip_set_ref_lock in __ip_set_put() to decrement set->ref.
ip_set_swap() holds that same lock while swapping both the ip_set_list
slots and the two sets' ref counters, so it can interleave between the
dereference and the lock acquisition, leaving the caller to decrement a
set whose reference already moved to the other index and hit
BUG_ON(set->ref == 0). list_set_gc() reaches this from timer softirq,
which the nfnl mutex does not serialize against swap: an expiring
list:set member calls list_set_del() -> ip_set_put_byindex() while
IPSET_CMD_SWAP runs on the referenced sets.
Resolve the index and decrement under ip_set_ref_lock, as ip_set_swap()
already does, keeping the refcount tied to the index rather than to a
stale set pointer.
kernel BUG at net/netfilter/ipset/ip_set_core.c:685!
Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI
RIP: 0010:ip_set_put_byindex (net/netfilter/ipset/ip_set_core.c:870)
Call Trace:
<IRQ>
list_set_del (net/netfilter/ipset/ip_set_list_set.c:159)
set_cleanup_entries (net/netfilter/ipset/ip_set_list_set.c:181)
list_set_gc (net/netfilter/ipset/ip_set_list_set.c:578)
call_timer_fn (kernel/time/timer.c:1748)
__run_timers (kernel/time/timer.c:1799 kernel/time/timer.c:2374)
run_timer_softirq (kernel/time/timer.c:2405)
</IRQ>
Kernel panic - not syncing: Fatal exception in interrupt
Fixes: 9076aea76538 ("netfilter: ipset: Increase the number of maximal sets automatically")
Reported-by: AutonomousCodeSecurity@microsoft.com
Signed-off-by: Xiang Mei (Microsoft) <xmei5@asu.edu>
Acked-by: Jozsef Kadlecsik <kadlec@netfilter.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/netfilter/ipset/ip_set_core.c | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
index 11e5536d8b263..dcf23460b6df9 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -679,11 +679,18 @@ __ip_set_get(struct ip_set *set)
}
static void
-__ip_set_put(struct ip_set *set)
+__ip_set_put_locked(struct ip_set *set)
{
- write_lock_bh(&ip_set_ref_lock);
+ lockdep_assert_held(&ip_set_ref_lock);
BUG_ON(set->ref == 0);
set->ref--;
+}
+
+static void
+__ip_set_put(struct ip_set *set)
+{
+ write_lock_bh(&ip_set_ref_lock);
+ __ip_set_put_locked(set);
write_unlock_bh(&ip_set_ref_lock);
}
@@ -856,11 +863,11 @@ __ip_set_put_byindex(struct ip_set_net *inst, ip_set_id_t index)
{
struct ip_set *set;
- rcu_read_lock();
- set = rcu_dereference(inst->ip_set_list)[index];
+ write_lock_bh(&ip_set_ref_lock);
+ set = ip_set(inst, index);
if (set)
- __ip_set_put(set);
- rcu_read_unlock();
+ __ip_set_put_locked(set);
+ write_unlock_bh(&ip_set_ref_lock);
}
void
--
2.53.0
^ permalink raw reply related [flat|nested] 239+ messages in thread
* [PATCH 5.10 219/235] netfilter: nf_tables_offload: suppress WARN_ON_ONCE for ENOMEM in abort path
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (217 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 218/235] netfilter: ipset: fix refcount race between list:set GC and swap Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 220/235] netfilter: flowtable: publish GC-visible tuple last Greg Kroah-Hartman
` (18 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Alexey Velichayshiy,
Pablo Neira Ayuso, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexey Velichayshiy <a.velichayshiy@ispras.ru>
[ Upstream commit d02f592064347e0c1e0d84f24941ad338838cc48 ]
In nft_flow_rule_offload_abort(), WARN_ON_ONCE(err) is triggered on every
error during rollback, including -ENOMEM. Memory allocation failures are
expected under low-memory conditions and do not indicate a kernel bug.
Trace for example:
nft_flow_offload_chain() // FLOW_BLOCK_BIND
nft_flow_block_chain()
nft_chain_offload_cmd()
nft_block_offload_cmd()
->ndo_setup_tc()
nsim_setup_tc()
flow_block_cb_setup_simple()
flow_block_cb_alloc() // fails to -ENOMEM
The warning was reproduced on the 5.10 stable kernel under memory pressure
via fault injection, but the underlying bug exists in mainline as well,
as demonstrated by the ENOMEM trace above. The following splat was
triggered during nf_tables transaction processing:
WARNING: CPU: 0 PID: 8567 at net/netfilter/nf_tables_offload.c:532 nft_flow_rule_offload_abort net/netfilter/nf_tables_offload.c:532 [inline]
WARNING: CPU: 0 PID: 8567 at net/netfilter/nf_tables_offload.c:532 nft_flow_rule_offload_commit+0x971/0xcd0 net/netfilter/nf_tables_offload.c:591
Modules linked in:
CPU: 0 PID: 8567 Comm: syz-executor.0 Not tainted 5.10.260-syzkaller #0
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 04/01/2014
RIP: 0010:nft_flow_rule_offload_abort net/netfilter/nf_tables_offload.c:532 [inline]
RIP: 0010:nft_flow_rule_offload_commit+0x971/0xcd0 net/netfilter/nf_tables_offload.c:591
Call Trace:
nf_tables_commit+0x3bd/0x4bd0 net/netfilter/nf_tables_api.c:8604
nfnetlink_rcv_batch+0xb1e/0x1f20 net/netfilter/nfnetlink.c:509
nfnetlink_rcv_skb_batch net/netfilter/nfnetlink.c:579 [inline]
nfnetlink_rcv+0x3b3/0x420 net/netfilter/nfnetlink.c:597
netlink_unicast_kernel net/netlink/af_netlink.c:1314 [inline]
netlink_unicast+0x6cd/0xa00 net/netfilter/af_netlink.c:1340
netlink_sendmsg+0x906/0xe10 net/netfilter/af_netlink.c:1919
sock_sendmsg_nosec net/socket.c:651 [inline]
__sock_sendmsg+0x155/0x190 net/socket.c:663
____sys_sendmsg+0x705/0x870 net/socket.c:2379
___sys_sendmsg+0x100/0x170 net/socket.c:2433
__sys_sendmsg+0xe9/0x1c0 net/socket.c:2462
do_syscall_64+0x33/0x40 arch/x86/entry/common.c:46
entry_SYSCALL_64_after_hwframe+0x67/0xd1
Change the condition to WARN_ON_ONCE(err && err != -ENOMEM) so that
warnings are only emitted for unexpected errors. This aligns with the
common kernel practice of not warning on -ENOMEM.
Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
Fixes: 63b48c73ff56 ("netfilter: nf_tables_offload: undo updates if transaction fails")
Signed-off-by: Alexey Velichayshiy <a.velichayshiy@ispras.ru>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/netfilter/nf_tables_offload.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/netfilter/nf_tables_offload.c b/net/netfilter/nf_tables_offload.c
index 5cfbb29d8a34a..f975df48ea622 100644
--- a/net/netfilter/nf_tables_offload.c
+++ b/net/netfilter/nf_tables_offload.c
@@ -522,7 +522,7 @@ static void nft_flow_rule_offload_abort(struct net *net,
break;
}
- if (WARN_ON_ONCE(err))
+ if (WARN_ON_ONCE(err && err != -ENOMEM))
break;
}
}
--
2.53.0
^ permalink raw reply related [flat|nested] 239+ messages in thread
* [PATCH 5.10 220/235] netfilter: flowtable: publish GC-visible tuple last
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (218 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 219/235] netfilter: nf_tables_offload: suppress WARN_ON_ONCE for ENOMEM in abort path Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 221/235] netfilter: ipset: fix list type element drift bug Greg Kroah-Hartman
` (17 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Jérémy Jean,
Pablo Neira Ayuso, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr>
[ Upstream commit 2014ac62df9d45bb9a004a043e85df7be09ed780 ]
nf_flow_table_iterate() only treats original-direction tuple nodes as
owning entries. Publishing the original node first lets GC observe and
free a flow while flow_offload_add() is still inserting the reply node.
Publish the reply node first and the original node last so GC never
sees a partially installed flow.
KASAN can trigger slab-use-after-free read and write reports in the
flowtable/rhashtable path (rht_deferred_worker, jhash, flow_offload_del,
flow_offload_lookup, etc.).
Fixes: ac2a66665e23 ("netfilter: add generic flow table infrastructure")
Signed-off-by: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr>
Assisted-by: Codex:gpt-5
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/netfilter/nf_flow_table_core.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c
index e05e09c07b971..8f6b791918ae7 100644
--- a/net/netfilter/nf_flow_table_core.c
+++ b/net/netfilter/nf_flow_table_core.c
@@ -228,17 +228,18 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT;
err = rhashtable_insert_fast(&flow_table->rhashtable,
- &flow->tuplehash[0].node,
+ &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node,
nf_flow_offload_rhash_params);
if (err < 0)
return err;
+ /* GC only iterates original-direction entries; publish original last. */
err = rhashtable_insert_fast(&flow_table->rhashtable,
- &flow->tuplehash[1].node,
+ &flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].node,
nf_flow_offload_rhash_params);
if (err < 0) {
rhashtable_remove_fast(&flow_table->rhashtable,
- &flow->tuplehash[0].node,
+ &flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].node,
nf_flow_offload_rhash_params);
return err;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 239+ messages in thread
* [PATCH 5.10 221/235] netfilter: ipset: fix list type element drift bug
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (219 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 220/235] netfilter: flowtable: publish GC-visible tuple last Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 222/235] net: packet: fix wrong transport_header when sending VLAN-tagged frame Greg Kroah-Hartman
` (16 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Florian Westphal, Jozsef Kadlecsik,
Pablo Neira Ayuso, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <fw@strlen.de>
[ Upstream commit 4cbd69766b35a089664cadb1f613bb85f7ef77a9 ]
If list_set_uadd() calls list_set_replace() to swap an expired entry,
the element count remains the same, therefore the increment must be elided.
Fixes: 702b71e7c666 ("netfilter: ipset: Add element count to all set types header")
Link: https://sashiko.dev/#/patchset/20260806101947.2802-1-fw%40strlen.de
Signed-off-by: Florian Westphal <fw@strlen.de>
Acked-by: Jozsef Kadlecsik <kadlec@netfilter.org>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/netfilter/ipset/ip_set_list_set.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c
index 7d1ba6ad514f5..25cfa8693f1a2 100644
--- a/net/netfilter/ipset/ip_set_list_set.c
+++ b/net/netfilter/ipset/ip_set_list_set.c
@@ -301,9 +301,12 @@ list_set_uadd(struct ip_set *set, void *value, const struct ip_set_ext *ext,
e->set = set;
INIT_LIST_HEAD(&e->list);
list_set_init_extensions(set, ext, e);
- if (n)
+ if (n) {
list_set_replace(set, e, n);
- else if (next)
+ return 0;
+ }
+
+ if (next)
list_add_tail_rcu(&e->list, &next->list);
else if (prev)
list_add_rcu(&e->list, &prev->list);
--
2.53.0
^ permalink raw reply related [flat|nested] 239+ messages in thread
* [PATCH 5.10 222/235] net: packet: fix wrong transport_header when sending VLAN-tagged frame
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (220 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 221/235] netfilter: ipset: fix list type element drift bug Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 223/235] ASoC: xilinx: formatter_pcm: pass aud_drv_data to irq handlers Greg Kroah-Hartman
` (15 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Wei Fang, Willem de Bruijn,
Paolo Abeni, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wei Fang <wei.fang@nxp.com>
[ Upstream commit 01fdecc0480d916c799dbee584833a4a37e94d06 ]
In packet_parse_headers(), when processing a VLAN-tagged frame,
skb_set_network_header() is called to advance network_header past the
VLAN tag to the inner protocol header. skb_probe_transport_header() is
then called with skb->protocol still set to the outer VLAN EtherType
(e.g. ETH_P_8021Q), while nhoff (derived from skb_network_offset())
already points past the VLAN tag to the inner protocol header.
In __skb_flow_dissect(), proto is initialized to ETH_P_8021Q and nhoff
points past the VLAN tag. When the dissector hits case ETH_P_8021Q, it
reads a struct vlan_hdr at nhoff via __skb_header_pointer(), but that
offset contains the inner protocol header (e.g. an IP header). The bytes
are misinterpreted as a VLAN header, yielding a garbage encapsulated
EtherType that matches no known protocol. The dissector returns false,
so skb_probe_transport_header() never calls skb_set_transport_header(),
leaving transport_header at its uninitialized sentinel value (~0U).
Move skb_probe_transport_header() to before skb_set_network_header(). At
the time skb_probe_transport_header() is called, network_header still
points to the VLAN header, so nhoff correctly points to the VLAN header.
The flow dissector can then parse the VLAN header, extract the inner
EtherType, and advance nhoff to the inner protocol header, allowing
transport_header to be set correctly.
Fixes: dfed913e8b55 ("net/af_packet: add VLAN support for AF_PACKET SOCK_RAW GSO")
Assisted-by: WChat:claude-opus-4-8
Signed-off-by: Wei Fang <wei.fang@nxp.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20260807063405.688780-2-wei.fang@oss.nxp.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/packet/af_packet.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index f73e2c3b813d9..8d70d3550b7f5 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1945,13 +1945,13 @@ static void packet_parse_headers(struct sk_buff *skb, struct socket *sock)
sock->type == SOCK_RAW)
skb->protocol = dev_parse_header_protocol(skb);
+ skb_probe_transport_header(skb);
+
/* Move network header to the right position for VLAN tagged packets */
if (likely(skb->dev->type == ARPHRD_ETHER) &&
eth_type_vlan(skb->protocol) &&
vlan_get_protocol_and_depth(skb, skb->protocol, &depth) != 0)
skb_set_network_header(skb, depth);
-
- skb_probe_transport_header(skb);
}
/*
--
2.53.0
^ permalink raw reply related [flat|nested] 239+ messages in thread
* [PATCH 5.10 223/235] ASoC: xilinx: formatter_pcm: pass aud_drv_data to irq handlers
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (221 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 222/235] net: packet: fix wrong transport_header when sending VLAN-tagged frame Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 224/235] af_packet: Dont send zero-byte data in tpacket_snd() Greg Kroah-Hartman
` (14 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Rosen Penev, Michal Simek,
Mark Brown, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rosen Penev <rosenp@gmail.com>
[ Upstream commit f12afefb7b01f94d6d66d397f323a9914edbf70e ]
The irq handlers take a struct device pointer and call
dev_get_drvdata() to obtain the driver data. However, the driver
data is only set at the end of probe, after devm_request_irq(),
so an interrupt taken in between causes the handlers to pass a
NULL pointer to readl() and crash.
Pass the private data directly as the devm_request_irq() argument
instead of the device pointer, matching what the handlers expect.
Fixes: 6f6c3c36f091 ("ASoC: xlnx: add pcm formatter platform driver")
Assisted-by: opencode:deepseek-v4-flash-free
Signed-off-by: Rosen Penev <rosenp@gmail.com>
Reviewed-by: Michal Simek <michal.simek@amd.com>
Link: https://patch.msgid.link/20260806233231.30631-1-rosenp@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
sound/soc/xilinx/xlnx_formatter_pcm.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/sound/soc/xilinx/xlnx_formatter_pcm.c b/sound/soc/xilinx/xlnx_formatter_pcm.c
index 5c4158069a5a8..dccc056e0e0a6 100644
--- a/sound/soc/xilinx/xlnx_formatter_pcm.c
+++ b/sound/soc/xilinx/xlnx_formatter_pcm.c
@@ -281,8 +281,7 @@ static irqreturn_t xlnx_mm2s_irq_handler(int irq, void *arg)
{
u32 val;
void __iomem *reg;
- struct device *dev = arg;
- struct xlnx_pcm_drv_data *adata = dev_get_drvdata(dev);
+ struct xlnx_pcm_drv_data *adata = arg;
reg = adata->mmio + XLNX_MM2S_OFFSET + XLNX_AUD_STS;
val = readl(reg);
@@ -300,8 +299,7 @@ static irqreturn_t xlnx_s2mm_irq_handler(int irq, void *arg)
{
u32 val;
void __iomem *reg;
- struct device *dev = arg;
- struct xlnx_pcm_drv_data *adata = dev_get_drvdata(dev);
+ struct xlnx_pcm_drv_data *adata = arg;
reg = adata->mmio + XLNX_S2MM_OFFSET + XLNX_AUD_STS;
val = readl(reg);
@@ -637,7 +635,7 @@ static int xlnx_formatter_pcm_probe(struct platform_device *pdev)
}
ret = devm_request_irq(dev, aud_drv_data->mm2s_irq,
xlnx_mm2s_irq_handler, 0,
- "xlnx_formatter_pcm_mm2s_irq", dev);
+ "xlnx_formatter_pcm_mm2s_irq", aud_drv_data);
if (ret) {
dev_err(dev, "xlnx audio mm2s irq request failed\n");
goto clk_err;
@@ -664,7 +662,7 @@ static int xlnx_formatter_pcm_probe(struct platform_device *pdev)
ret = devm_request_irq(dev, aud_drv_data->s2mm_irq,
xlnx_s2mm_irq_handler, 0,
"xlnx_formatter_pcm_s2mm_irq",
- dev);
+ aud_drv_data);
if (ret) {
dev_err(dev, "xlnx audio s2mm irq request failed\n");
goto clk_err;
--
2.53.0
^ permalink raw reply related [flat|nested] 239+ messages in thread
* [PATCH 5.10 224/235] af_packet: Dont send zero-byte data in tpacket_snd().
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (222 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 223/235] ASoC: xilinx: formatter_pcm: pass aud_drv_data to irq handlers Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 225/235] net: ethernet: ti: am65-cpsw: move ale selection in pdata Greg Kroah-Hartman
` (13 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, syzbot+30b93b6845b19cc38581,
Eric Dumazet, Willem de Bruijn, Jiayuan Chen, Jakub Kicinski,
Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <edumazet@google.com>
[ Upstream commit 6bcd76c134c55c697148acb5c0194e9666abdf84 ]
syzbot reported a WARNING in __dev_queue_xmit() triggered via tpacket_snd():
skb_assert_len
WARNING: at include/linux/skbuff.h:2753 skb_assert_len
WARNING: at __dev_queue_xmit+0x21bc/0x4970 net/core/dev.c:4781
Call Trace:
<TASK>
dev_queue_xmit include/linux/netdevice.h:3448 [inline]
packet_xmit+0x243/0x310 net/packet/af_packet.c:276
tpacket_snd net/packet/af_packet.c:2907 [inline]
packet_sendmsg+0x28d6/0x4eb0 net/packet/af_packet.c:3134
When sending 0-byte packets via TPACKET ring buffer on devices with no
hard header (e.g. dev->hard_header_len == 0), tpacket_fill_skb()
populates an skb with skb->len == 0 and returns 0. tpacket_snd() then
forwards this empty skb to packet_xmit(), causing __dev_queue_xmit() to
hit skb_assert_len(skb).
Similar checks exist in packet_snd() via commit dc633700f00f
("net/af_packet: check len when min_header_len equals to 0") and in
packet_sendmsg_spkt() via commit 6a341729fb31 ("af_packet: Don't send
zero-byte data in packet_sendmsg_spkt().").
Return -EINVAL in tpacket_fill_skb() when skb->len is zero to reject
zero-length packets in tpacket_snd().
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reported-by: syzbot+30b93b6845b19cc38581@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/netdev/6a79e807.01d0871a.3a0d52.00ac.GAE@google.com/T/#u
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
Link: https://patch.msgid.link/20260810150447.1220864-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/packet/af_packet.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 8d70d3550b7f5..b040b20b5e920 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -2649,6 +2649,9 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
len = ((to_write > len_max) ? len_max : to_write);
}
+ if (unlikely(!skb->len))
+ return -EINVAL;
+
packet_parse_headers(skb, sock);
return tp_len;
--
2.53.0
^ permalink raw reply related [flat|nested] 239+ messages in thread
* [PATCH 5.10 225/235] net: ethernet: ti: am65-cpsw: move ale selection in pdata
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (223 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 224/235] af_packet: Dont send zero-byte data in tpacket_snd() Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 226/235] net: ethernet: ti: am65-cpsw: move free desc queue mode " Greg Kroah-Hartman
` (12 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Grygorii Strashko, Jesse Brandeburg,
Jakub Kicinski, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Grygorii Strashko <grygorii.strashko@ti.com>
[ Upstream commit 7747d4b72f7702b2f19b9f91cc783eb38a2028bf ]
In preparation of adding more multi-port K3 CPSW versions move ALE
selection in am65_cpsw_pdata, so it can be selected basing on DT
compatibility property.
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Reviewed-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: 36a05d282007 ("net: ethernet: ti: am65-cpsw-nuss: Fix port_id extraction from SRC TAG")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/ti/am65-cpsw-nuss.c | 4 +++-
drivers/net/ethernet/ti/am65-cpsw-nuss.h | 1 +
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index 2dc3e5be1d717..d1bf457acba04 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -1988,10 +1988,12 @@ static const struct soc_device_attribute am65_cpsw_socinfo[] = {
static const struct am65_cpsw_pdata am65x_sr1_0 = {
.quirks = AM65_CPSW_QUIRK_I2027_NO_TX_CSUM,
+ .ale_dev_id = "am65x-cpsw2g",
};
static const struct am65_cpsw_pdata j721e_pdata = {
.quirks = 0,
+ .ale_dev_id = "am65x-cpsw2g",
};
static const struct of_device_id am65_cpsw_nuss_of_mtable[] = {
@@ -2123,7 +2125,7 @@ static int am65_cpsw_nuss_probe(struct platform_device *pdev)
ale_params.ale_ageout = AM65_CPSW_ALE_AGEOUT_DEFAULT;
ale_params.ale_ports = common->port_num + 1;
ale_params.ale_regs = common->cpsw_base + AM65_CPSW_NU_ALE_BASE;
- ale_params.dev_id = "am65x-cpsw2g";
+ ale_params.dev_id = common->pdata.ale_dev_id;
ale_params.bus_freq = common->bus_freq;
common->ale = cpsw_ale_create(&ale_params);
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.h b/drivers/net/ethernet/ti/am65-cpsw-nuss.h
index 993e1d4d3222f..9c2186b8eae90 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.h
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.h
@@ -77,6 +77,7 @@ struct am65_cpsw_rx_chn {
struct am65_cpsw_pdata {
u32 quirks;
+ const char *ale_dev_id;
};
struct am65_cpsw_common {
--
2.53.0
^ permalink raw reply related [flat|nested] 239+ messages in thread
* [PATCH 5.10 226/235] net: ethernet: ti: am65-cpsw: move free desc queue mode selection in pdata
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (224 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 225/235] net: ethernet: ti: am65-cpsw: move ale selection in pdata Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 227/235] net: ethernet: ti: am65-cpsw: add multi port support in mac-only mode Greg Kroah-Hartman
` (11 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Grygorii Strashko, Jesse Brandeburg,
Jakub Kicinski, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Grygorii Strashko <grygorii.strashko@ti.com>
[ Upstream commit c6275c02a09730b365fffe3372fbe768cef8eb37 ]
In preparation of adding more multi-port K3 CPSW versions move free
descriptor queue mode selection in am65_cpsw_pdata, so it can be selected
basing on DT compatibility property.
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Reviewed-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: 36a05d282007 ("net: ethernet: ti: am65-cpsw-nuss: Fix port_id extraction from SRC TAG")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/ti/am65-cpsw-nuss.c | 4 +++-
drivers/net/ethernet/ti/am65-cpsw-nuss.h | 2 ++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index d1bf457acba04..0b228205d08c6 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -1578,7 +1578,6 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
};
struct k3_ring_cfg fdqring_cfg = {
.elm_size = K3_RINGACC_RING_ELSIZE_8,
- .mode = K3_RINGACC_RING_MODE_MESSAGE,
.flags = K3_RINGACC_RING_SHARED,
};
struct k3_udma_glue_rx_flow_cfg rx_flow_cfg = {
@@ -1592,6 +1591,7 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
rx_flow_cfg.ring_rxfdq0_id = fdqring_id;
rx_flow_cfg.rx_cfg.size = max_desc_num;
rx_flow_cfg.rxfdq_cfg.size = max_desc_num;
+ rx_flow_cfg.rxfdq_cfg.mode = common->pdata.fdqring_mode;
ret = k3_udma_glue_rx_flow_init(rx_chn->rx_chn,
i, &rx_flow_cfg);
@@ -1989,11 +1989,13 @@ static const struct soc_device_attribute am65_cpsw_socinfo[] = {
static const struct am65_cpsw_pdata am65x_sr1_0 = {
.quirks = AM65_CPSW_QUIRK_I2027_NO_TX_CSUM,
.ale_dev_id = "am65x-cpsw2g",
+ .fdqring_mode = K3_RINGACC_RING_MODE_MESSAGE,
};
static const struct am65_cpsw_pdata j721e_pdata = {
.quirks = 0,
.ale_dev_id = "am65x-cpsw2g",
+ .fdqring_mode = K3_RINGACC_RING_MODE_MESSAGE,
};
static const struct of_device_id am65_cpsw_nuss_of_mtable[] = {
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.h b/drivers/net/ethernet/ti/am65-cpsw-nuss.h
index 9c2186b8eae90..b6f228ddc3a09 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.h
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.h
@@ -11,6 +11,7 @@
#include <linux/netdevice.h>
#include <linux/phy.h>
#include <linux/platform_device.h>
+#include <linux/soc/ti/k3-ringacc.h>
#include "am65-cpsw-qos.h"
struct am65_cpts;
@@ -77,6 +78,7 @@ struct am65_cpsw_rx_chn {
struct am65_cpsw_pdata {
u32 quirks;
+ enum k3_ring_mode fdqring_mode;
const char *ale_dev_id;
};
--
2.53.0
^ permalink raw reply related [flat|nested] 239+ messages in thread
* [PATCH 5.10 227/235] net: ethernet: ti: am65-cpsw: add multi port support in mac-only mode
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (225 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 226/235] net: ethernet: ti: am65-cpsw: move free desc queue mode " Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 228/235] net: ethernet: ti: am65-cpsw-nuss: Fix port_id extraction from SRC TAG Greg Kroah-Hartman
` (10 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Grygorii Strashko, Jesse Brandeburg,
Jakub Kicinski, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Grygorii Strashko <grygorii.strashko@ti.com>
[ Upstream commit 84b4aa4932490c9f88f13d8f3b3cd1f3b6116991 ]
This patch adds final multi-port support to TI AM65x CPSW driver path in
preparation for adding support for multi-port devices, like Main CPSW0 on
K3 J721E SoC or future CPSW3g on K3 AM64x SoC.
- the separate netdev is created for every enabled external Port;
- DMA channels are common/shared for all external Ports and the RX/TX NAPI
and DMA processing assigned to first available netdev;
- external Ports are configured in mac-only mode, which is similar to TI
"dual-mac" mode for legacy TI CPSW - packets are sent to the Host port only
in ingress and directly to the Port on egress. No packet switching between
external ports happens.
- every port supports the same features as current AM65x CPSW on external
device.
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Reviewed-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: 36a05d282007 ("net: ethernet: ti: am65-cpsw-nuss: Fix port_id extraction from SRC TAG")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/ti/am65-cpsw-nuss.c | 129 ++++++++++++++---------
drivers/net/ethernet/ti/am65-cpsw-nuss.h | 1 +
2 files changed, 82 insertions(+), 48 deletions(-)
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index 0b228205d08c6..3fb87601b329c 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -270,8 +270,8 @@ static int am65_cpsw_nuss_ndo_slave_kill_vid(struct net_device *ndev,
return ret;
}
-static void am65_cpsw_slave_set_promisc_2g(struct am65_cpsw_port *port,
- bool promisc)
+static void am65_cpsw_slave_set_promisc(struct am65_cpsw_port *port,
+ bool promisc)
{
struct am65_cpsw_common *common = port->common;
@@ -296,7 +296,7 @@ static void am65_cpsw_nuss_ndo_slave_set_rx_mode(struct net_device *ndev)
bool promisc;
promisc = !!(ndev->flags & IFF_PROMISC);
- am65_cpsw_slave_set_promisc_2g(port, promisc);
+ am65_cpsw_slave_set_promisc(port, promisc);
if (promisc)
return;
@@ -627,13 +627,13 @@ static int am65_cpsw_nuss_ndo_slave_open(struct net_device *ndev)
am65_cpsw_port_set_sl_mac(port, ndev->dev_addr);
- if (port->slave.mac_only)
+ if (port->slave.mac_only) {
/* enable mac-only mode on port */
cpsw_ale_control_set(common->ale, port->port_id,
ALE_PORT_MACONLY, 1);
- if (AM65_CPSW_IS_CPSW2G(common))
cpsw_ale_control_set(common->ale, port->port_id,
ALE_PORT_NOLEARN, 1);
+ }
port_mask = BIT(port->port_id) | ALE_PORT_HOST;
cpsw_ale_add_ucast(common->ale, ndev->dev_addr,
@@ -1367,7 +1367,7 @@ static void am65_cpsw_nuss_ndo_get_stats(struct net_device *dev,
stats->tx_dropped = dev->stats.tx_dropped;
}
-static const struct net_device_ops am65_cpsw_nuss_netdev_ops_2g = {
+static const struct net_device_ops am65_cpsw_nuss_netdev_ops = {
.ndo_open = am65_cpsw_nuss_ndo_slave_open,
.ndo_stop = am65_cpsw_nuss_ndo_slave_stop,
.ndo_start_xmit = am65_cpsw_nuss_ndo_slave_xmit,
@@ -1389,7 +1389,6 @@ static void am65_cpsw_nuss_slave_disable_unused(struct am65_cpsw_port *port)
if (!port->disabled)
return;
- common->disabled_ports_mask |= BIT(port->port_id);
cpsw_ale_control_set(common->ale, port->port_id,
ALE_PORT_STATE, ALE_PORT_STATE_DISABLE);
@@ -1754,8 +1753,10 @@ static int am65_cpsw_nuss_init_slave_ports(struct am65_cpsw_common *common)
}
port->disabled = !of_device_is_available(port_np);
- if (port->disabled)
+ if (port->disabled) {
+ common->disabled_ports_mask |= BIT(port->port_id);
continue;
+ }
port->slave.ifphy = devm_of_phy_get(dev, port_np, NULL);
if (IS_ERR(port->slave.ifphy)) {
@@ -1810,6 +1811,12 @@ static int am65_cpsw_nuss_init_slave_ports(struct am65_cpsw_common *common)
}
of_node_put(node);
+ /* is there at least one ext.port */
+ if (!(~common->disabled_ports_mask & GENMASK(common->port_num, 1))) {
+ dev_err(dev, "No Ext. port are available\n");
+ return -ENODEV;
+ }
+
return 0;
of_node_put:
@@ -1825,14 +1832,18 @@ static void am65_cpsw_pcpu_stats_free(void *data)
free_percpu(stats);
}
-static int am65_cpsw_nuss_init_ndev_2g(struct am65_cpsw_common *common)
+static int
+am65_cpsw_nuss_init_port_ndev(struct am65_cpsw_common *common, u32 port_idx)
{
struct am65_cpsw_ndev_priv *ndev_priv;
struct device *dev = common->dev;
struct am65_cpsw_port *port;
int ret;
- port = am65_common_get_port(common, 1);
+ port = &common->ports[port_idx];
+
+ if (port->disabled)
+ return 0;
/* alloc netdev */
port->ndev = devm_alloc_etherdev_mqs(common->dev,
@@ -1862,7 +1873,7 @@ static int am65_cpsw_nuss_init_ndev_2g(struct am65_cpsw_common *common)
port->ndev->features = port->ndev->hw_features |
NETIF_F_HW_VLAN_CTAG_FILTER;
port->ndev->vlan_features |= NETIF_F_SG;
- port->ndev->netdev_ops = &am65_cpsw_nuss_netdev_ops_2g;
+ port->ndev->netdev_ops = &am65_cpsw_nuss_netdev_ops;
port->ndev->ethtool_ops = &am65_cpsw_ethtool_ops_slave;
/* Disable TX checksum offload by default due to HW bug */
@@ -1875,29 +1886,41 @@ static int am65_cpsw_nuss_init_ndev_2g(struct am65_cpsw_common *common)
ret = devm_add_action_or_reset(dev, am65_cpsw_pcpu_stats_free,
ndev_priv->stats);
- if (ret) {
- dev_err(dev, "Failed to add percpu stat free action %d\n", ret);
- return ret;
+ if (ret)
+ dev_err(dev, "failed to add percpu stat free action %d\n", ret);
+
+ if (!common->dma_ndev)
+ common->dma_ndev = port->ndev;
+
+ return ret;
+}
+
+static int am65_cpsw_nuss_init_ndevs(struct am65_cpsw_common *common)
+{
+ int ret;
+ int i;
+
+ for (i = 0; i < common->port_num; i++) {
+ ret = am65_cpsw_nuss_init_port_ndev(common, i);
+ if (ret)
+ return ret;
}
- netif_napi_add(port->ndev, &common->napi_rx,
+ netif_napi_add(common->dma_ndev, &common->napi_rx,
am65_cpsw_nuss_rx_poll, NAPI_POLL_WEIGHT);
return ret;
}
-static int am65_cpsw_nuss_ndev_add_napi_2g(struct am65_cpsw_common *common)
+static int am65_cpsw_nuss_ndev_add_tx_napi(struct am65_cpsw_common *common)
{
struct device *dev = common->dev;
- struct am65_cpsw_port *port;
int i, ret = 0;
- port = am65_common_get_port(common, 1);
-
for (i = 0; i < common->tx_ch_num; i++) {
struct am65_cpsw_tx_chn *tx_chn = &common->tx_chns[i];
- netif_tx_napi_add(port->ndev, &tx_chn->napi_tx,
+ netif_tx_napi_add(common->dma_ndev, &tx_chn->napi_tx,
am65_cpsw_nuss_tx_poll, NAPI_POLL_WEIGHT);
ret = devm_request_irq(dev, tx_chn->irq,
@@ -1915,16 +1938,27 @@ static int am65_cpsw_nuss_ndev_add_napi_2g(struct am65_cpsw_common *common)
return ret;
}
-static int am65_cpsw_nuss_ndev_reg_2g(struct am65_cpsw_common *common)
+static void am65_cpsw_nuss_cleanup_ndev(struct am65_cpsw_common *common)
+{
+ struct am65_cpsw_port *port;
+ int i;
+
+ for (i = 0; i < common->port_num; i++) {
+ port = &common->ports[i];
+ if (port->ndev)
+ unregister_netdev(port->ndev);
+ }
+}
+
+static int am65_cpsw_nuss_register_ndevs(struct am65_cpsw_common *common)
{
struct device *dev = common->dev;
struct am65_cpsw_port *port;
- int ret = 0;
+ int ret = 0, i;
- port = am65_common_get_port(common, 1);
- ret = am65_cpsw_nuss_ndev_add_napi_2g(common);
+ ret = am65_cpsw_nuss_ndev_add_tx_napi(common);
if (ret)
- goto err;
+ return ret;
ret = devm_request_irq(dev, common->rx_chns.irq,
am65_cpsw_nuss_rx_irq,
@@ -1932,17 +1966,31 @@ static int am65_cpsw_nuss_ndev_reg_2g(struct am65_cpsw_common *common)
if (ret) {
dev_err(dev, "failure requesting rx irq %u, %d\n",
common->rx_chns.irq, ret);
- goto err;
+ return ret;
+ }
+
+ for (i = 0; i < common->port_num; i++) {
+ port = &common->ports[i];
+
+ if (!port->ndev)
+ continue;
+
+ ret = register_netdev(port->ndev);
+ if (ret) {
+ dev_err(dev, "error registering slave net device%i %d\n",
+ i, ret);
+ goto err_cleanup_ndev;
+ }
}
- ret = register_netdev(port->ndev);
- if (ret)
- dev_err(dev, "error registering slave net device %d\n", ret);
/* can't auto unregister ndev using devm_add_action() due to
* devres release sequence in DD core for DMA
*/
-err:
+ return 0;
+
+err_cleanup_ndev:
+ am65_cpsw_nuss_cleanup_ndev(common);
return ret;
}
@@ -1955,19 +2003,7 @@ int am65_cpsw_nuss_update_tx_chns(struct am65_cpsw_common *common, int num_tx)
if (ret)
return ret;
- return am65_cpsw_nuss_ndev_add_napi_2g(common);
-}
-
-static void am65_cpsw_nuss_cleanup_ndev(struct am65_cpsw_common *common)
-{
- struct am65_cpsw_port *port;
- int i;
-
- for (i = 0; i < common->port_num; i++) {
- port = &common->ports[i];
- if (port->ndev)
- unregister_netdev(port->ndev);
- }
+ return am65_cpsw_nuss_ndev_add_tx_napi(common);
}
struct am65_cpsw_soc_pdata {
@@ -2055,9 +2091,6 @@ static int am65_cpsw_nuss_probe(struct platform_device *pdev)
if (common->port_num < 1 || common->port_num > AM65_CPSW_MAX_PORTS)
return -ENOENT;
- if (common->port_num != 1)
- return -EOPNOTSUPP;
-
common->rx_flow_id_base = -1;
init_completion(&common->tdown_complete);
common->tx_ch_num = 1;
@@ -2147,11 +2180,11 @@ static int am65_cpsw_nuss_probe(struct platform_device *pdev)
dev_set_drvdata(dev, common);
- ret = am65_cpsw_nuss_init_ndev_2g(common);
+ ret = am65_cpsw_nuss_init_ndevs(common);
if (ret)
goto err_of_clear;
- ret = am65_cpsw_nuss_ndev_reg_2g(common);
+ ret = am65_cpsw_nuss_register_ndevs(common);
if (ret)
goto err_of_clear;
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.h b/drivers/net/ethernet/ti/am65-cpsw-nuss.h
index b6f228ddc3a09..b5da51bfecd85 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.h
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.h
@@ -94,6 +94,7 @@ struct am65_cpsw_common {
struct am65_cpsw_host host;
struct am65_cpsw_port *ports;
u32 disabled_ports_mask;
+ struct net_device *dma_ndev;
int usage_count; /* number of opened ports */
struct cpsw_ale *ale;
--
2.53.0
^ permalink raw reply related [flat|nested] 239+ messages in thread
* [PATCH 5.10 228/235] net: ethernet: ti: am65-cpsw-nuss: Fix port_id extraction from SRC TAG
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (226 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 227/235] net: ethernet: ti: am65-cpsw: add multi port support in mac-only mode Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 229/235] net/smc: rdma write inline if qp has sufficient inline space Greg Kroah-Hartman
` (9 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Siddharth Vadapalli, Chintan Vankar,
Simon Horman, Jakub Kicinski, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Siddharth Vadapalli <s-vadapalli@ti.com>
[ Upstream commit 36a05d2820077bb3955acb8111e1041d39148037 ]
On the packet reception path, the ID of the MAC Port on which the packet
was received, is embedded in the RX DMA Descriptor's metadata. The ID is
extracted using the helper function cppi5_desc_get_tags_ids() which fills
in the 16-bit Source Tag into the 'port_id' variable. However, it is only
the lower 8-bits of the 16-bit Source Tag that represent the MAC Port ID,
while the upper 8-bits are Hardware-Reserved and carry an arbitrary value.
With the existing logic, sporadic kernel crash is observed due to the
subsequent driver code accessing out-of-bound memory because of an invalid
port_id.
Hence, fix the port_id extraction logic to use only the lower 8-bits of the
Source Tag as the MAC Port ID.
Fixes: 93a76530316a ("net: ethernet: ti: introduce am65x/j721e gigabit eth subsystem driver")
Signed-off-by: Siddharth Vadapalli <s-vadapalli@ti.com>
Reviewed-by: Chintan Vankar <c-vankar@ti.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260807111738.2055900-1-s-vadapalli@ti.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/net/ethernet/ti/am65-cpsw-nuss.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index 3fb87601b329c..7128d43ead502 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -779,6 +779,8 @@ static int am65_cpsw_nuss_rx_packets(struct am65_cpsw_common *common,
cppi5_hdesc_get_obuf(desc_rx, &buf_dma, &buf_dma_len);
pkt_len = cppi5_hdesc_get_pktlen(desc_rx);
cppi5_desc_get_tags_ids(&desc_rx->hdr, &port_id, NULL);
+ /* Port ID is contained in the lower 8-bits of the 16-bit Source Tag */
+ port_id &= 0xFF;
dev_dbg(dev, "%s rx port_id:%d\n", __func__, port_id);
port = am65_common_get_port(common, port_id);
ndev = port->ndev;
--
2.53.0
^ permalink raw reply related [flat|nested] 239+ messages in thread
* [PATCH 5.10 229/235] net/smc: rdma write inline if qp has sufficient inline space
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (227 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 228/235] net: ethernet: ti: am65-cpsw-nuss: Fix port_id extraction from SRC TAG Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 230/235] net: smc: fix splice entry lifetime imbalance in smc_rx_splice Greg Kroah-Hartman
` (8 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Guangguan Wang, Tony Lu,
kernel test robot, Karsten Graul, Jakub Kicinski, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangguan Wang <guangguan.wang@linux.alibaba.com>
commit 793a7df63071eb09e5b88addf2a569d7bfd3c973 upstream.
Rdma write with inline flag when sending small packages,
whose length is shorter than the qp's max_inline_data, can
help reducing latency.
In my test environment, which are 2 VMs running on the same
physical host and whose NICs(ConnectX-4Lx) are working on
SR-IOV mode, qperf shows 0.5us-0.7us improvement in latency.
Test command:
server: smc_run taskset -c 1 qperf
client: smc_run taskset -c 1 qperf <server ip> -oo \
msg_size:1:2K:*2 -t 30 -vu tcp_lat
The results shown below:
msgsize before after
1B 11.2 us 10.6 us (-0.6 us)
2B 11.2 us 10.7 us (-0.5 us)
4B 11.3 us 10.7 us (-0.6 us)
8B 11.2 us 10.6 us (-0.6 us)
16B 11.3 us 10.7 us (-0.6 us)
32B 11.3 us 10.6 us (-0.7 us)
64B 11.2 us 11.2 us (0 us)
128B 11.2 us 11.2 us (0 us)
256B 11.2 us 11.2 us (0 us)
512B 11.4 us 11.3 us (-0.1 us)
1KB 11.4 us 11.5 us (0.1 us)
2KB 11.5 us 11.5 us (0 us)
Signed-off-by: Guangguan Wang <guangguan.wang@linux.alibaba.com>
Reviewed-by: Tony Lu <tonylu@linux.alibaba.com>
Tested-by: kernel test robot <lkp@intel.com>
Acked-by: Karsten Graul <kgraul@linux.ibm.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: 5d9686af2976 ("net: smc: fix splice entry lifetime imbalance in smc_rx_splice")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/smc/smc_tx.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
--- a/net/smc/smc_tx.c
+++ b/net/smc/smc_tx.c
@@ -320,12 +320,20 @@ static int smcr_tx_rdma_writes(struct sm
int rc;
for (dstchunk = 0; dstchunk < 2; dstchunk++) {
- struct ib_sge *sge =
- wr_rdma_buf->wr_tx_rdma[dstchunk].wr.sg_list;
+ struct ib_rdma_wr *wr = &wr_rdma_buf->wr_tx_rdma[dstchunk];
+ struct ib_sge *sge = wr->wr.sg_list;
+ u64 base_addr = dma_addr;
+
+ if (dst_len < link->qp_attr.cap.max_inline_data) {
+ base_addr = (uintptr_t)conn->sndbuf_desc->cpu_addr;
+ wr->wr.send_flags |= IB_SEND_INLINE;
+ } else {
+ wr->wr.send_flags &= ~IB_SEND_INLINE;
+ }
num_sges = 0;
for (srcchunk = 0; srcchunk < 2; srcchunk++) {
- sge[srcchunk].addr = dma_addr + src_off;
+ sge[srcchunk].addr = base_addr + src_off;
sge[srcchunk].length = src_len;
num_sges++;
@@ -339,8 +347,7 @@ static int smcr_tx_rdma_writes(struct sm
src_len = dst_len - src_len; /* remainder */
src_len_sum += src_len;
}
- rc = smc_tx_rdma_write(conn, dst_off, num_sges,
- &wr_rdma_buf->wr_tx_rdma[dstchunk]);
+ rc = smc_tx_rdma_write(conn, dst_off, num_sges, wr);
if (rc)
return rc;
if (dst_len_sum == len)
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 230/235] net: smc: fix splice entry lifetime imbalance in smc_rx_splice
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (228 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 229/235] net/smc: rdma write inline if qp has sufficient inline space Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 231/235] binfmt_misc: use exe_file_deny_write_access() for the interpreter clone Greg Kroah-Hartman
` (7 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Vega, Xiao Liu, Daming Li, Ren Wei,
Dust Li, Sidraya Jayagond, Jakub Kicinski, Sasha Levin
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daming Li <d4n.for.sec@gmail.com>
commit 5d9686af2976741bbd79b150d1c9e60b81e7f12e upstream.
smc_rx_splice() passes pages to splice_to_pipe() before taking the
references that cover the lifetime of each splice entry. In the
VM-backed RMB path, splice_to_pipe() may drop unqueued entries through
smc_rx_spd_release(), while queued entries are released later via the
pipe buffer callback.
The old post-splice accounting also derives the number of queued VM pages
from an offset mutated while building the descriptor, and a multi-page
splice pairs one sock_hold() with multiple sock_put() calls.
Take the page and socket references for every candidate entry before
splice_to_pipe(), and drop the matching private state, page reference,
and socket reference from smc_rx_spd_release() for entries that never
get queued. This fixes a refcount imbalance that can underflow page
refcounts and trigger a use-after-free.
Fixes: 9014db202cb7 ("smc: add support for splice()")
Cc: stable@vger.kernel.org
Reported-by: Vega <vega@nebusec.ai>
Co-developed-by: Xiao Liu <lx24@stu.ynu.edu.cn>
Signed-off-by: Xiao Liu <lx24@stu.ynu.edu.cn>
Signed-off-by: Daming Li <d4n.for.sec@gmail.com>
Signed-off-by: Ren Wei <enjou1224z@gmail.com>
Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
Reviewed-by: Sidraya Jayagond <sidraya@linux.ibm.com>
Link: https://patch.msgid.link/20260730145552.360287-2-enjou1224z@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
[ collapsed the multi-page get_page()/sock_hold() loop to a single get_page()/sock_hold() pair and dropped the trailing kfree() calls, as 5.15 lacks the multi-page pages[]/partial[]/priv[] arrays ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
net/smc/smc_rx.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
--- a/net/smc/smc_rx.c
+++ b/net/smc/smc_rx.c
@@ -144,7 +144,12 @@ static const struct pipe_buf_operations
static void smc_rx_spd_release(struct splice_pipe_desc *spd,
unsigned int i)
{
+ struct smc_spd_priv *priv = (struct smc_spd_priv *)spd->partial[i].private;
+ struct sock *sk = &priv->smc->sk;
+
+ kfree(priv);
put_page(spd->pages[i]);
+ sock_put(sk);
}
static int smc_rx_splice(struct pipe_inode_info *pipe, char *src, size_t len,
@@ -164,6 +169,8 @@ static int smc_rx_splice(struct pipe_ino
partial.len = len;
partial.private = (unsigned long)priv;
+ get_page(smc->conn.rmb_desc->pages);
+ sock_hold(&smc->sk);
spd.nr_pages_max = 1;
spd.nr_pages = 1;
spd.pages = &smc->conn.rmb_desc->pages;
@@ -172,11 +179,8 @@ static int smc_rx_splice(struct pipe_ino
spd.spd_release = smc_rx_spd_release;
bytes = splice_to_pipe(pipe, &spd);
- if (bytes > 0) {
- sock_hold(&smc->sk);
- get_page(smc->conn.rmb_desc->pages);
+ if (bytes > 0)
atomic_add(bytes, &smc->conn.splice_pending);
- }
return bytes;
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 231/235] binfmt_misc: use exe_file_deny_write_access() for the interpreter clone
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (229 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 230/235] net: smc: fix splice entry lifetime imbalance in smc_rx_splice Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 232/235] udmabuf: Ensure to perform cache synchronisation in begin_cpu_udmabuf() Greg Kroah-Hartman
` (6 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Christian Brauner (Amutable)
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Brauner <brauner@kernel.org>
commit fa5990ca8fd917003e526036bcc50413edb9722c upstream.
For MISC_FMT_OPEN_FILE entries load_misc_binary() clones the
registered interpreter file and denies write access to the clone via
plain deny_write_access(). The clone is installed as
bprm->interpreter and later released by the exec machinery through
exe_file_allow_write_access() which skips the i_writecount increment
for files with FMODE_FSNOTIFY_HSM set.
The deny and allow side can therefore come to different conclusions
when pre-content watches are in play: if a pre-content watch is added
to the interpreter after registration every subsequent exec through
that entry takes a write denial on the clone that is never paired
with a write allowance, driving the interpreter inode's i_writecount
further down with each exec and leaving the interpreter unwritable
even after the entry and all its users are gone.
Take the write denial via exe_file_deny_write_access() so both sides
of the pairing base their decision on the same file mode, and
propagate failure instead of silently ignoring it: an interpreter
that is concurrently open for writing now fails the exec with
ETXTBSY, exactly like an interpreter freshly opened via open_exec()
would.
Link: https://patch.msgid.link/20260710-work-binfmt_misc-locking-v3-2-a162f7cb58d6@kernel.org
Fixes: 0357ef03c94e ("fs: don't block write during exec on pre-content watched files")
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 | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -220,8 +220,14 @@ static int load_misc_binary(struct linux
if (fmt->flags & MISC_FMT_OPEN_FILE) {
interp_file = file_clone_open(fmt->interp_file);
- if (!IS_ERR(interp_file))
- deny_write_access(interp_file);
+ if (!IS_ERR(interp_file)) {
+ int err = exe_file_deny_write_access(interp_file);
+
+ if (err) {
+ fput(interp_file);
+ interp_file = ERR_PTR(err);
+ }
+ }
} else {
interp_file = open_exec(fmt->interpreter);
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 232/235] udmabuf: Ensure to perform cache synchronisation in begin_cpu_udmabuf()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (230 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 231/235] binfmt_misc: use exe_file_deny_write_access() for the interpreter clone Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 233/235] i2c: smbus: Check for parent device before dereference Greg Kroah-Hartman
` (5 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Robert Mader, Mikhail Gavrilov,
Vivek Kasireddy
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Robert Mader <robert.mader@collabora.com>
commit 1d0e25c1ddf2063c499264fb2ba0fa6a3e4f8a00 upstream.
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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/dma-buf/udmabuf.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
--- a/drivers/dma-buf/udmabuf.c
+++ b/drivers/dma-buf/udmabuf.c
@@ -121,21 +121,22 @@ static int begin_cpu_udmabuf(struct dma_
{
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,
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 233/235] i2c: smbus: Check for parent device before dereference
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (231 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 232/235] udmabuf: Ensure to perform cache synchronisation in begin_cpu_udmabuf() Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 234/235] net: ethernet: ti: am65-cpsw: fix error handling in am65_cpsw_nuss_probe() Greg Kroah-Hartman
` (4 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, syzbot+0591ccf54ee05344e4eb,
Andy Shevchenko, Wolfram Sang
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
commit 8302532f47bb6c3aa1ed2043d30187ca307f176a upstream.
An I²C adapter might be instantiated without parent. In such case
there is no property can be retrieved. Skip SMBus alert setup when
this happens.
Fixes: a263a84088f6 ("i2c: smbus: Use device_*() functions instead of of_*()")
Reported-by: syzbot+0591ccf54ee05344e4eb@syzkaller.appspotmail.com
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Wolfram Sang <wsa@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/i2c/i2c-core-smbus.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
--- a/drivers/i2c/i2c-core-smbus.c
+++ b/drivers/i2c/i2c-core-smbus.c
@@ -703,10 +703,14 @@ EXPORT_SYMBOL_GPL(i2c_new_smbus_alert_de
#if IS_ENABLED(CONFIG_I2C_SMBUS)
int i2c_setup_smbus_alert(struct i2c_adapter *adapter)
{
+ struct device *parent = adapter->dev.parent;
int irq;
- irq = device_property_match_string(adapter->dev.parent, "interrupt-names",
- "smbus_alert");
+ /* Adapter instantiated without parent, skip the SMBus alert setup */
+ if (!parent)
+ return 0;
+
+ irq = device_property_match_string(parent, "interrupt-names", "smbus_alert");
if (irq == -EINVAL || irq == -ENODATA)
return 0;
else if (irq < 0)
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 234/235] net: ethernet: ti: am65-cpsw: fix error handling in am65_cpsw_nuss_probe()
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (232 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 233/235] i2c: smbus: Check for parent device before dereference Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 235/235] USB: serial: keyspan_pda: fix information leak Greg Kroah-Hartman
` (3 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable
Cc: Greg Kroah-Hartman, patches, Zhang Changzhong, Maciej Fijalkowski,
David S. Miller
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Changzhong <zhangchangzhong@huawei.com>
commit 46fb6512538d201d9a5b2bd7138b6751c37fdf0b upstream.
The am65_cpsw_nuss_cleanup_ndev() function calls unregister_netdev()
even if register_netdev() fails, which triggers WARN_ON(1) in
unregister_netdevice_many(). To fix it, make sure that
unregister_netdev() is called only on registered netdev.
Compile tested only.
Fixes: 84b4aa493249 ("net: ethernet: ti: am65-cpsw: add multi port support in mac-only mode")
Signed-off-by: Zhang Changzhong <zhangchangzhong@huawei.com>
Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/net/ethernet/ti/am65-cpsw-nuss.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -1947,7 +1947,7 @@ static void am65_cpsw_nuss_cleanup_ndev(
for (i = 0; i < common->port_num; i++) {
port = &common->ports[i];
- if (port->ndev)
+ if (port->ndev && port->ndev->reg_state == NETREG_REGISTERED)
unregister_netdev(port->ndev);
}
}
^ permalink raw reply [flat|nested] 239+ messages in thread
* [PATCH 5.10 235/235] USB: serial: keyspan_pda: fix information leak
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (233 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 234/235] net: ethernet: ti: am65-cpsw: fix error handling in am65_cpsw_nuss_probe() Greg Kroah-Hartman
@ 2026-08-20 14:57 ` Greg Kroah-Hartman
2026-08-20 17:46 ` [PATCH 5.10 000/235] 5.10.266-rc1 review Florian Fainelli
` (2 subsequent siblings)
237 siblings, 0 replies; 239+ messages in thread
From: Greg Kroah-Hartman @ 2026-08-20 14:57 UTC (permalink / raw)
To: stable; +Cc: Greg Kroah-Hartman, patches, Johan Hovold
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <johan@kernel.org>
commit 6bfc8d01ac4068eced509f8fc74d0cd205e4dcec upstream.
The write() callback is supposed to return the number of characters
accepted or a negative errno. Since the addition of write fifo support
the keyspan_pda implementation will however return the number characters
submitted to the device if the write urb is not already in use. If this
number is larger than the number of characters passed to write(), the
line discipline continues writing data from beyond the tty write buffer.
Fix the information leak by making sure that keyspan_pda_write_start()
returns zero on success as intended.
Fixes: 034e38e8f687 ("USB: serial: keyspan_pda: add write-fifo support")
Cc: stable@vger.kernel.org # 5.11
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/usb/serial/keyspan_pda.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/usb/serial/keyspan_pda.c
+++ b/drivers/usb/serial/keyspan_pda.c
@@ -606,7 +606,7 @@ static int keyspan_pda_write(struct tty_
if (rc)
return rc;
- return count;
+ return 0;
}
static void keyspan_pda_dtr_rts(struct usb_serial_port *port, int on)
^ permalink raw reply [flat|nested] 239+ messages in thread
* Re: [PATCH 5.10 000/235] 5.10.266-rc1 review
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (234 preceding siblings ...)
2026-08-20 14:57 ` [PATCH 5.10 235/235] USB: serial: keyspan_pda: fix information leak Greg Kroah-Hartman
@ 2026-08-20 17:46 ` Florian Fainelli
2026-08-20 18:27 ` Pavel Machek
2026-08-20 20:24 ` Brett A C Sheffield
237 siblings, 0 replies; 239+ messages in thread
From: Florian Fainelli @ 2026-08-20 17:46 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 8/20/26 07:53, Greg Kroah-Hartman wrote:
> This is the start of the stable review cycle for the 5.10.266 release.
> There are 235 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, 22 Aug 2026 14:51:11 +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/v5.x/stable-review/patch-5.10.266-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-5.10.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] 239+ messages in thread
* Re: [PATCH 5.10 000/235] 5.10.266-rc1 review
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (235 preceding siblings ...)
2026-08-20 17:46 ` [PATCH 5.10 000/235] 5.10.266-rc1 review Florian Fainelli
@ 2026-08-20 18:27 ` Pavel Machek
2026-08-20 20:24 ` Brett A C Sheffield
237 siblings, 0 replies; 239+ messages in thread
From: Pavel Machek @ 2026-08-20 18:27 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: stable, patches, linux-kernel, torvalds, akpm, linux, shuah,
patches, lkft-triage, pavel, jonathanh, f.fainelli,
sudipm.mukherjee, rwarsow, conor, hargar, broonie, achill, sr
[-- Attachment #1: Type: text/plain, Size: 382 bytes --]
Hi!
> This is the start of the stable review cycle for the 5.10.266 release.
> There are 235 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.
Similar failure to 5.15:
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/pipelines/2776649189
Best regards,
Pavel
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
^ permalink raw reply [flat|nested] 239+ messages in thread
* Re: [PATCH 5.10 000/235] 5.10.266-rc1 review
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
` (236 preceding siblings ...)
2026-08-20 18:27 ` Pavel Machek
@ 2026-08-20 20:24 ` Brett A C Sheffield
237 siblings, 0 replies; 239+ messages in thread
From: Brett A C Sheffield @ 2026-08-20 20:24 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 5.10.266-rc1-01309-g7ceedcd42fa3 #1 SMP Thu Aug 20 19:44:41 -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] 239+ messages in thread
end of thread, other threads:[~2026-08-20 20:24 UTC | newest]
Thread overview: 239+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-20 14:53 [PATCH 5.10 000/235] 5.10.266-rc1 review Greg Kroah-Hartman
2026-08-20 14:53 ` [PATCH 5.10 001/235] media: mtk-vcodec: potential null pointer deference in SCP Greg Kroah-Hartman
2026-08-20 14:53 ` [PATCH 5.10 002/235] media: mediatek: vcodec: Fix a resource leak related to the scp device in FW initialization Greg Kroah-Hartman
2026-08-20 14:53 ` [PATCH 5.10 003/235] ipvs: separate destination availability state Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 004/235] selinux: require every boolean value to be defined Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 005/235] selinux: reject a class permission count below its inherited common Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 006/235] selinux: do not cancel a policy conversion that never started Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 007/235] mptcp: options: reset DSS fields in case of unexpected size Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 008/235] s390/qeth: validate user buffer length in SNMP and ARP query ioctls Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 009/235] ASoC: cs4265: sort the register default table Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 010/235] powerpc/pseries: pci - logic bug Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 011/235] Input: synaptics-rmi4 - fix F55 transmitter electrode count typo Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 012/235] Input: focaltech - fix array out-of-bounds in focaltech_process_rel_packet Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 013/235] Input: psxpad-spi - set driver data before use Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 014/235] Input: atkbd - skip deactivate for Xiaomi Book Pro 14s internal keyboard Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 015/235] Input: iforce - validate input packet lengths Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 016/235] powerpc/pseries: lparcfg - fix kbuf[] underflow Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 017/235] Input: synaptics-rmi4 - zero report size on F54 work error Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 018/235] Input: synaptics-rmi4 - bound the F54 report size to the allocated buffer Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 019/235] Input: synaptics-rmi4 - block s_input when F54 queue is busy Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 020/235] Input: synaptics-rmi4 - propagate F54 worker errors to V4L2 queue Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 021/235] crypto: qce - fix error path in devm_qce_register_algs Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 022/235] libceph: fix multiple unsafe decodes in decode_locker() Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 023/235] ftrace: Fix off-by-one fentry site disable in ftrace_free_mem() Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 024/235] openrisc: signal: do not restore privileged SR bits on sigreturn Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 025/235] Input: sur40 - fix input device registration ordering Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 026/235] Input: sur40 - fix V4L error path cleanup Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 027/235] libceph: Avoid using invalid osd indices from primary_temp Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 028/235] ceph: fix MDS random selection readiness predicate Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 029/235] mmc: omap_hsmmc: fix busy_timeout overflow in ns conversion on 32-bit Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 030/235] mmc: sdhci: unmap the bounce buffer before device release Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 031/235] mmc: sdhci: make tuning_err a signed int Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 032/235] mmc: atmel-mci: Fix use-after-free in atmci_remove due to race condition Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 033/235] drm/radeon: fix autosuspend cleanup during teardown Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 034/235] s390/vfio_ccw: Fix out of bounds check on CCW array Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 035/235] drm/amdgpu: Reject UVD message with invalid number of h265 refs Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 036/235] drm/amdgpu: validate GEM_CREATE domain combinations Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 037/235] drm/amdgpu: Reject UVD message with dimensions above 4096 Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 038/235] drm/amdgpu: Implement insert_end for VCE 3 Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 039/235] drm/amdgpu: Fix UVD decode image min size calculation Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 040/235] xfs: check v5 superblock features early Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 041/235] net/smc: reject CHID-0 ACCEPT that matches an empty ism_dev slot Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 042/235] f2fs: fix UAF issue in f2fs_merge_page_bio() Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 043/235] bpf: Reject BPF_MAP_TYPE_INODE_STORAGE creation if BPF LSM is uninitialized Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 044/235] udmabuf: Do not create malformed scatterlists Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 045/235] dma-buf/udmabuf: skip redundant cpu sync to fix cacheline EEXIST warning Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 046/235] fpga: dfl-afu: validate DMA mapping length in afu_dma_map_region() Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 047/235] i2c: davinci: Unregister cpufreq notifier on probe failure Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 048/235] device property: Add fwnode_irq_get_byname Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 049/235] i2c: smbus: Use device_*() functions instead of of_*() Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 050/235] RDMA/rtrs-srv: Bound RDMA-Write length to chunk size in rdma_write_sg Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 051/235] Input: mms114 - reject an oversized device packet size Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 052/235] VFS/audit: introduce kern_path_parent() for audit Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 053/235] audit: widen ino fields to u64 Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 054/235] audit: use unsigned int instead of unsigned Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 055/235] audit: fix recursive locking deadlock in audit_dupe_exe() Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 056/235] ALSA: hda: Fix cached processing coefficient verbs Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 057/235] serial: max310x: replace bare use of unsigned with unsigned int (checkpatch) Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 058/235] serial: max310x: implement gpio_chip::get_direction() Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 059/235] rxrpc: serialize kernel accept preallocation with socket teardown Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 060/235] tipc: restrict socket queue dumps in enqueue tracepoints Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 061/235] rxrpc: Fix recv-recv race of completed call Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 062/235] rxrpc: Fix notification vs call-release vs recvmsg Greg Kroah-Hartman
2026-08-20 14:54 ` [PATCH 5.10 063/235] rxrpc: Fix socket notification race Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 064/235] mlxsw: spectrum: Apply RIF configuration when joining a LAG Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 065/235] mlxsw: spectrum: On port enslavement to a LAG, join uppers bridges Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 066/235] mlxsw: fix refcount leak in mlxsw_sp_port_lag_join() Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 067/235] octeontx2: Annotate mmio regions as __iomem Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 068/235] octeontx2-pf: clear stale mailbox IRQ state before request_irq() Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 069/235] ASoC: mediatek: mt8183: Check runtime resume during probe Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 070/235] octeontx2-vf: clear stale mailbox IRQ state before request_irq() Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 071/235] netfilter: nf_conntrack_sip: remove net variable shadowing Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 072/235] netfilter: nf_conntrack_sip: validate skb_dst() before accessing it Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 073/235] jbd2: add a helper to find out number of fast commit blocks Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 074/235] jbd2: fix integer underflow in jbd2_journal_initialize_fast_commit() Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 075/235] netfilter: nft_set_pipapo: use GFP_KERNEL for insertions Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 076/235] netfilter: nft_set_pipapo: make pipapo_clone helper return NULL Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 077/235] netfilter: nft_set_pipapo: prepare walk function for on-demand clone Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 078/235] netfilter: nft_set_pipapo: merge deactivate helper into caller Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 079/235] netfilter: nft_set_pipapo: prepare pipapo_get helper for on-demand clone Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 080/235] netfilter: nft_set_pipapo: move cloning of match info to insert/removal path Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 081/235] netfilter: nft_set_pipapo: dont leak bad clone into future transaction Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 082/235] lsm: use default hook return value in call_int_hook() Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 083/235] lsm: infrastructure management of the sock security Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 084/235] selinux: avoid sk_socket dereference in selinux_sctp_bind_connect() Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 085/235] net/9p: fix infinite loop in p9_client_rpc on fatal signal Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 086/235] 9p: skip nlink update in cacheless mode to fix WARN_ON Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 087/235] mtd: maps: vmu-flash: fix fault in unaligned fixup Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 088/235] net: thunderbolt: Fix frags[] overflow by bounding frame_count Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 089/235] taskstats: fill_stats_for_tgid: use for_each_thread() Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 090/235] taskstats: retain dead thread stats in TGID queries Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 091/235] mtd: spi-nor: sst: remove global protection flag Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 092/235] mtd: spi-nor: intel: " Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 093/235] mtd: spi-nor: Move Software Write Protection logic out of the core Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 094/235] mtd: spi-nor: Fix spi_nor_try_unlock_all() Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 095/235] mtd: spi-nor: swp: Improve locking user experience Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 096/235] smb: client: use kvzalloc() for megabyte buffer in simple fallocate Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 097/235] tpm: tpm_tis_spi: Use wait_woken() in wait_for_tmp_stat() Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 098/235] PCI: Add pci_find_vsec_capability() to find a specific VSEC Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 099/235] dmaengine: dw-edma: Improve the linked list and data blocks definition Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 100/235] dmaengine: dw-edma: Remove unused irq field in struct dw_edma_chip Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 101/235] dmaengine: dw-edma: Add spinlock to protect DONE_INT_MASK and ABORT_INT_MASK Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 102/235] i2c: imx: separate atomic, dma and non-dma use case Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 103/235] i2c: imx: fix locked bus on SMBus block-read of 0 (atomic) Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 104/235] thunderbolt: Keep XDomain reference during the lifetime of a service Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 105/235] thunderbolt: Remove XDomain from the bus without holding tb->lock Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 106/235] thunderbolt: Prevent XDomain delayed work use-after-free on disconnect Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 107/235] scsi: lpfc: Fix memory leak in lpfc_sli4_driver_resource_setup() Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 108/235] ovl: use linked upper dentry in copy-up tmpfile Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 109/235] scsi: target: core: pr: Initialize arrays at declaration time Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 110/235] scsi: target: core: Generate correct identifiers for PR OUT transport IDs Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 111/235] scsi: target: Bound PR-OUT TransportID parsing to the received buffer Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 112/235] dm-integrity: dont increment hash_offset twice Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 113/235] dm-verity: make error counter atomic Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 114/235] Input: ims-pcu - fix race condition in reset_device sysfs callback Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 115/235] wifi: libertas_tf: fix use-after-free in lbtf_free_adapter() Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 116/235] mmc: vub300: fix use-after-free on disconnect Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 117/235] mmc: vub300: rename probe error labels Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 118/235] mmc: vub300: fix use-after-free on probe failure Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 119/235] firmware_loader: introduce __free() cleanup hanler Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 120/235] Input: ims-pcu - fix firmware leak in async update Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 121/235] net: Add helper function to parse netlink msg of ip_tunnel_encap Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 122/235] net: ipip: require CAP_NET_ADMIN in the device netns for changelink Greg Kroah-Hartman
2026-08-20 14:55 ` [PATCH 5.10 123/235] net: ip6_tunnel: " Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 124/235] net/sched: taprio: avoid calling child->ops->dequeue(child) twice Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 125/235] net/sched: sch_taprio: Replace direct dequeue call with peek and qdisc_dequeue_peeked Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 126/235] gpio: tegra: do not call pinctrl for GPIO direction Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 127/235] bootconfig: do not put quotes on cmdline items unless necessary Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 128/235] bootconfig: move xbc_snprint_cmdline() to lib/bootconfig.c Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 129/235] bootconfig: fix NULL-pointer arithmetic in xbc_snprint_cmdline() Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 130/235] espintcp: use sk_msg_free_partial to fix partial send Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 131/235] net: ipa: fix SMEM state handle leaks in SMP2P init Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 132/235] octeontx2-pf: fix SQB pointer leak on init failure Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 133/235] fs/resctrl: Fix double-add of pseudo-locked regions RMID to free list Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 134/235] usb: gadget: bdc: fix checkpatch.pl spacing error Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 135/235] usb: gadget: udc: bdc: free IRQ and drain func_wake_notify before teardown Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 136/235] USB: serial: keyspan_pda: refactor write-room handling Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 137/235] USB: serial: keyspan_pda: fix write implementation Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 138/235] USB: serial: keyspan_pda: add write-fifo support Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 139/235] USB: serial: keyspan_pda: clean up comments and whitespace Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 140/235] USB: serial: keyspan_pda: fix data loss on receive throttling Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 141/235] KVM: x86: Drop @vcpu parameter from kvm_x86_ops.hwapic_isr_update() Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 142/235] KVM: x86: Check for in-kernel xAPIC when querying APICv for directed yield Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 143/235] KVM: x86: Move "apicv_active" into "struct kvm_lapic" Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 144/235] KVM: Introduce vcpu->wants_to_run Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 145/235] KVM: x86: Only reset TSC Deadline Timer in apic_timer_expired on KVM_RUN Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 146/235] drm/dp/mst: fix buffer overflows in sideband chunk accumulation Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 147/235] usb: gadget: f_tcm: synchronize delayed set_alt with teardown Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 148/235] drm/dp/mst: fix OOB reads on 2-byte fields in sideband reply parsers Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 149/235] drm/dp/mst: fix OOB reads in remote DPCD/I2C " Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 150/235] dma-buf/drivers: make reserving a shared slot mandatory v4 Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 151/235] drm/virtio: use uninterruptible resv lock for plane updates Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 152/235] drm/displayid: fix Tiled Display Topology ID size Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 153/235] drm/tegra: fbdev: Remove offset into framebuffer memory Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 154/235] drm/virtio: Return proper error codes instead of -1 Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 155/235] drm/virtio: bound EDID block reads to the response buffer Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 156/235] media: aspeed: fix missing of_reserved_mem_device_release() on probe failure Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 157/235] drm/i915/hdcp: require monotonically increasing seq_num_v Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 158/235] media: marvell-cam: fix missing pci_disable_device() on remove Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 159/235] media: i2c: imx219: Drop IMX219_VTS_* macros Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 160/235] media: i2c: imx219: Correct the minimum vblanking value Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 161/235] media: i2c: imx219: Rename VTS to FRM_LENGTH Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 162/235] media: imx219: Fix maximum frame length in lines Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 163/235] wifi: ath6kl: fix use-after-free in aggr_reset_state() Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 164/235] media: v4l: async: Set owner for async sub-devices Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 165/235] media: v4l2-fwnode: Fix subdev owner overwritten in v4l2_async_register_subdev_sensor() Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 166/235] wifi: brcmfmac: drain bus_reset work on device removal Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 167/235] ALSA: seq: close a re-opened queue timer in the destructor Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 168/235] serial: 8250_mid: Remove unneeded test for ->setup() presence Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 169/235] serial: 8250_mid: Fix NULL function pointer dereference on DNV/ICX-D/SNR platforms Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 170/235] mptcp: only set DATA_FIN when a mapping is present Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 171/235] sc16is7xx: Properly resume TX after stop Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 172/235] serial: sc16is7xx: Fill in rs485_supported Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 173/235] serial: sc16is7xx: remove obsolete out_thread label Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 174/235] serial: sc16is7xx: fix regression with GPIO configuration Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 175/235] serial: sc16is7xx: implement gpio get_direction() callback Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 176/235] mptcp: fix subflow accounting on close Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 177/235] mptcp: decrement subflows counter on failed passive join Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 178/235] sctp: avoid auth_enable sysctl UAF during netns teardown Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 179/235] ceph: avoid fs reclaim while using current->journal_info Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 180/235] libceph: Amend checking to fix `make W=1` build breakage Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 181/235] libceph: bound pg_{temp,upmap,upmap_items} length to CEPH_PG_MAX_SIZE Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 182/235] libceph: fix two unsafe bare decodes in decode_lockers() Greg Kroah-Hartman
2026-08-20 14:56 ` [PATCH 5.10 183/235] libceph: add doutc and *_client debug macros support Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 184/235] ceph: rename _to_client() to _to_fs_client() Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 185/235] ceph: fix hanging __ceph_get_caps() with stale mds_wanted Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 186/235] net/sched: serialize qdisc_rtab_list against concurrent get/put Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 187/235] net: gro: fix double aggregation of flush-marked skbs Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 188/235] super: fix emergency thaw deadlock on frozen block devices Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 189/235] ftrace: Add global mutex to serialize trace_parser access Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 190/235] skbuff: introduce skb_pull_data Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 191/235] Bluetooth: HIDP: reject frames without a transaction header Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 192/235] mm/vmstat: fold stranded per-cpu node stats when a node comes online Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 193/235] net: pktgen: fix code style (WARNING: Block comments) Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 194/235] net: pktgen: fix proc entry use-after-free Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 195/235] scsi: sd: sd_zbc: Improve source code documentation Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 196/235] scsi: sd: sd_zbc: Use logical blocks as unit when querying zones Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 197/235] scsi: sd: sd_zbc: Return early in sd_zbc_check_zoned_characteristics() Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 198/235] scsi: scsi_debug: Rename zone type constants Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 199/235] scsi: scsi_debug: Fix REPORT ZONES alloc_len underflow OOB write Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 200/235] ice: fix VF interrupts cleanup Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 201/235] ice: fix memory leak in ice_lbtest_prepare_rings() Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 202/235] i2c: bcm-iproc: remove printout on handled timeouts Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 203/235] i2c: iproc: reset bus after timeout if START_BUSY is stuck Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 204/235] fsnotify: opt-in for permission events at file open time Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 205/235] fs: dont block write during exec on pre-content watched files Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 206/235] binfmt_misc: restore write access when removing an entry Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 207/235] can: gs_usb: gs_usb_receive_bulk_callback(): resubmit URB on skb allocation failure Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 208/235] hwmon: (npcm750-pwm-fan): stop fan timer on device detach Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 209/235] drm/amd/pm: fix torn gpu metrics reads Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 210/235] ALSA: usx2y: Fix potential leaks of uninitialized memory Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 211/235] ALSA: usx2y: bound the hwdep mmap fault offset Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 212/235] sched/psi: Shut down rtpoll_timer in psi_cgroup_free() Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 213/235] net/sched: act_gact, act_police: range check the fallback control action Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 214/235] mm/ptdump: always stabilise against page table freeing using init_mm Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 215/235] net: atlantic: free stranded TX buffers on ring deinit Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 216/235] arm64: tegra: Add EL2 virtual timer interrupt for Tegra194 Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 217/235] crypto: ccm - Set rfc4309 maxauthsize from child Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 218/235] netfilter: ipset: fix refcount race between list:set GC and swap Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 219/235] netfilter: nf_tables_offload: suppress WARN_ON_ONCE for ENOMEM in abort path Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 220/235] netfilter: flowtable: publish GC-visible tuple last Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 221/235] netfilter: ipset: fix list type element drift bug Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 222/235] net: packet: fix wrong transport_header when sending VLAN-tagged frame Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 223/235] ASoC: xilinx: formatter_pcm: pass aud_drv_data to irq handlers Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 224/235] af_packet: Dont send zero-byte data in tpacket_snd() Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 225/235] net: ethernet: ti: am65-cpsw: move ale selection in pdata Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 226/235] net: ethernet: ti: am65-cpsw: move free desc queue mode " Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 227/235] net: ethernet: ti: am65-cpsw: add multi port support in mac-only mode Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 228/235] net: ethernet: ti: am65-cpsw-nuss: Fix port_id extraction from SRC TAG Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 229/235] net/smc: rdma write inline if qp has sufficient inline space Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 230/235] net: smc: fix splice entry lifetime imbalance in smc_rx_splice Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 231/235] binfmt_misc: use exe_file_deny_write_access() for the interpreter clone Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 232/235] udmabuf: Ensure to perform cache synchronisation in begin_cpu_udmabuf() Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 233/235] i2c: smbus: Check for parent device before dereference Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 234/235] net: ethernet: ti: am65-cpsw: fix error handling in am65_cpsw_nuss_probe() Greg Kroah-Hartman
2026-08-20 14:57 ` [PATCH 5.10 235/235] USB: serial: keyspan_pda: fix information leak Greg Kroah-Hartman
2026-08-20 17:46 ` [PATCH 5.10 000/235] 5.10.266-rc1 review Florian Fainelli
2026-08-20 18:27 ` Pavel Machek
2026-08-20 20:24 ` Brett A C Sheffield
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.