Skip to contentSkip to conversation

6.12.83-rc1 review

PATCH In review Greg Kroah-Hartman 14 participants 176 messages Apr 20 – Apr 21 Page 1 of 2

Subsystems (6)
lore
Share & tools
lore

Greg Kroah-Hartman

author maintainer
#0 lore raw

cover 6.12.83-rc1 review

This is the start of the stable review cycle for the 6.12.83 release. There are 162 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 Wed, 22 Apr 2026 15:38:55 +0000. Anything received after that time might be too late.

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

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

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

thanks,

greg k-h

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

Greg Kroah-Hartman <[email protected]>

    Linux 6.12.83-rc1

John Hancock <[email protected]>
PCI: Revert "Enable ACS after configuring IOMMU for OF platforms"

Minhong He <[email protected]>
ipv6: add NULL checks for idev in SRv6 paths

Lukas Wunner <[email protected]>
PCI: Fix placement of pci_save_state() in pci_bus_add_device()

David Howells <[email protected]>
rxrpc: Fix key quota calculation for multitoken keys

Joseph Qi <[email protected]>
ocfs2: fix out-of-bounds write in ocfs2_write_end_inline

Deepanshu Kartikey <[email protected]>
ocfs2: validate inline data i_size during inode read

Dmitry Antipov <[email protected]>
ocfs2: add inline inode consistency check to ocfs2_validate_inode_block()

Jeongjun Park <[email protected]>
media: hackrf: fix to not free memory after the device is registered in hackrf_probe()

Abd-Alrhman Masalkhi <[email protected]>
media: vidtv: fix pass-by-value structs causing MSAN warnings

Deepanshu Kartikey <[email protected]>
nilfs2: fix NULL i_assoc_inode dereference in nilfs_mdt_save_to_shadow_map

Jeongjun Park <[email protected]>
media: as102: fix to not free memory after the device is registered in as102_usb_probe()

Mingzhe Zou <[email protected]>
bcache: fix cached_dev.sb_bio use-after-free and crash

Berk Cem Goksel <[email protected]>
ALSA: 6fire: fix use-after-free on disconnect

Sanman Pradhan <[email protected]>
hwmon: (powerz) Fix use-after-free on USB disconnect

Abhishek Kumar <[email protected]>

    media: em28xx: fix use-after-free in em28xx_v4l2_open()

Fan Wu <[email protected]>
media: mediatek: vcodec: fix use-after-free in encoder release path

Ruslan Valiyev <[email protected]>
media: vidtv: fix nfeeds state corruption on start_streaming failure

Breno Leitao <[email protected]>
mm: blk-cgroup: fix use-after-free in cgwb_release_workfn()

Ritesh Harjani (IBM) <[email protected]>
mm/kasan: fix double free for kasan pXds

Srinivas Kandagatla <[email protected]>
ASoC: qcom: q6apm: move component registration to unmanaged version

Sean Christopherson <[email protected]>
KVM: x86: Use scratch field in MMIO fragment to hold small write values

Linus Torvalds <[email protected]>
x86-64/arm64/powerpc: clean up and rename __copy_from_user_flushcache

Linus Torvalds <[email protected]>
x86: rename and clean up __copy_from_user_inatomic_nocache()

Linus Torvalds <[email protected]>
x86-64: rename misleadingly named '__copy_user_nocache()' function

Sasha Levin <[email protected]>
checkpatch: add support for Assisted-by tag

David Woodhouse <[email protected]>
KVM: x86: Use __DECLARE_FLEX_ARRAY() for UAPI structures with VLAs

Sean Christopherson <[email protected]>
KVM: Remove subtle "struct kvm_stats_desc" pseudo-overlay

Liam R. Howlett <[email protected]>
kernel: be more careful about dup_mmap() failures and uprobe registering

Eric Dumazet <[email protected]>
net: sched: fix TCF_LAYER_TRANSPORT handling in tcf_get_base_ptr()

Paweł Narewski <[email protected]>

    gpiolib: fix race condition for gdev->srcu

Bartosz Golaszewski <[email protected]>
gpiolib: unify two loops initializing GPIO descriptors

Sean Christopherson <[email protected]>
KVM: SEV: Drop WARN on large size for KVM_MEMORY_ENCRYPT_REG_REGION

Sean Christopherson <[email protected]>
KVM: SEV: Disallow LAUNCH_FINISH if vCPUs are actively being created

Sean Christopherson <[email protected]>
KVM: SEV: Reject attempts to sync VMSA of an already-launched/encrypted vCPU

Koichiro Den <[email protected]>
PCI: endpoint: pci-epf-vntb: Stop cmd_handler work in epf_ntb_epc_cleanup

ZhengYuan Huang <[email protected]>
ocfs2: handle invalid dinode in ocfs2_group_extend

Tejas Bharambe <[email protected]>
ocfs2: fix use-after-free in ocfs2_fault() when VM_FAULT_RETRY

Joseph Qi <[email protected]>
ocfs2: fix possible deadlock between unlink and dio_end_io_write

Ruslan Valiyev <[email protected]>
media: vidtv: fix NULL pointer dereference in vidtv_channel_pmt_match_sections

Zhihao Cheng <[email protected]>
dcache: Limit the minimal number of bucket to two

Harin Lee <[email protected]>
ALSA: ctxfi: Limit PTP to a single page

SeongJae Park <[email protected]>
Docs/admin-guide/mm/damon/reclaim: warn commit_inputs vs param updates race

Fabio Porcedda <[email protected]>
USB: serial: option: add Telit Cinterion FN990A MBIM composition

Junrui Luo <[email protected]>
staging: sm750fb: fix division by zero in ps_to_hz()

Johan Hovold <[email protected]>
wifi: rtw88: fix device leak on probe failure

Tamir Duberstein <[email protected]>
scripts: generate_rust_analyzer.py: avoid FD leak

Greg Kroah-Hartman <[email protected]>
fbdev: udlfb: avoid divide-by-zero on FBIOPUT_VSCREENINFO

Xu Yang <[email protected]>
usb: port: add delay after usb_hub_set_port_power()

Michael Zimmermann <[email protected]>
usb: gadget: f_hid: don't call cdev_init while cdev in use

Dave Carey <[email protected]>
USB: cdc-acm: Add quirks for Yoga Book 9 14IAH10 INGENIC touchscreen

Daniel Brát <[email protected]>
usb: storage: Expand range of matched versions for VL817 quirks entry

Nathan Rebello <[email protected]>
usbip: validate number_of_packets in usbip_pack_ret_submit()

Greg Kroah-Hartman <[email protected]>
ksmbd: fix mechToken leak when SPNEGO decode fails after token alloc

Greg Kroah-Hartman <[email protected]>
ksmbd: require 3 sub-authorities before reading sub_auth[2]

Greg Kroah-Hartman <[email protected]>
ksmbd: validate EaNameLength in smb2_get_ea()

Greg Kroah-Hartman <[email protected]>
smb: client: fix off-by-8 bounds check in check_wsl_eas()

Greg Kroah-Hartman <[email protected]>
usb: gadget: renesas_usb3: validate endpoint index in standard request handlers

Greg Kroah-Hartman <[email protected]>

    usb: gadget: f_phonet: fix skb frags[] overflow in pn_rx_complete()

Greg Kroah-Hartman <[email protected]>
usb: gadget: f_ncm: validate minimum block_len in ncm_unwrap_ntb()

Greg Kroah-Hartman <[email protected]>
fbdev: tdfxfb: avoid divide-by-zero on FBIOPUT_VSCREENINFO

Greg Kroah-Hartman <[email protected]>
ALSA: fireworks: bound device-supplied status before string array lookup

Greg Kroah-Hartman <[email protected]>
drm/vc4: platform_get_irq_byname() returns an int

Greg Kroah-Hartman <[email protected]>
NFC: digital: Bounds check NFC-A cascade depth in SDD response handler

Greg Kroah-Hartman <[email protected]>

    net: usb: cdc-phonet: fix skb frags[] overflow in rx_complete()

Greg Kroah-Hartman <[email protected]>
HID: core: clamp report_size in s32ton() to avoid undefined shift

Greg Kroah-Hartman <[email protected]>
HID: alps: fix NULL pointer dereference in alps_raw_event()

Lin YuChen <[email protected]>
staging: rtl8723bs: initialize le_tmp64 in rtw_BIP_verify()

Greg Kroah-Hartman <[email protected]>
i2c: s3c24xx: check the size of the SMBUS message before using it

Samuel Page <[email protected]>

    can: raw: fix ro->uniq use-after-free in raw_rcv()

Junxi Qian <[email protected]>
nfc: llcp: add missing return after LLCP_CLOSED checks

Emil Tantilov <[email protected]>
idpf: fix PREEMPT_RT raw/bh spinlock nesting for async VC handling

Geoffrey D. Bennett <[email protected]>
ALSA: usb-audio: Improve Focusrite sample rate filtering

Rafael J. Wysocki <[email protected]>
thermal: core: Address thermal zone removal races with resume

Rafael J. Wysocki <[email protected]>
thermal: core: Mark thermal zones as exiting before unregistration

Sasha Levin <[email protected]>
Revert "drm/xe: Switch MMIO interface to take xe_mmio instead of xe_gt"

Sasha Levin <[email protected]>
Revert "drm/xe/mmio: Avoid double-adjust in 64-bit reads"

Florian Westphal <[email protected]>
netfilter: conntrack: add missing netlink policy validations

Herbert Xu <[email protected]>
crypto: algif_aead - Fix minimum RX size check for decryption

Thomas Gleixner <[email protected]>
clockevents: Prevent timer interrupt starvation

Peter Zijlstra <[email protected]>
sched/deadline: Use revised wakeup rule for dl_server

Zide Chen <[email protected]>
perf/x86/intel/uncore: Skip discovery table for offline dies

Douya Le <[email protected]>
crypto: af_alg - limit RX SG extraction by receive buffer budget

Samasth Norway Ananda <[email protected]>
gpio: tegra: fix irq_release_resources calling enable instead of disable

Alice Mikityanska <[email protected]>
l2tp: Drop large packets with UDP encap

Alexander Koskovich <[email protected]>
net: ipa: fix event ring index not programmed for IPA v5.0+

Alexander Koskovich <[email protected]>
net: ipa: fix GENERIC_CMD register field masks for IPA v5.0+

Jiexun Wang <[email protected]>
af_unix: read UNIX_DIAG_VFS data under unix_state_lock

Fabio Baltieri <[email protected]>
net: txgbe: leave space for null terminators on property_entry

Florian Westphal <[email protected]>
netfilter: nfnetlink_queue: make hash table per queue

Scott Mitchell <[email protected]>

    netfilter: nfnetlink_queue: nfqnl_instance GFP_ATOMIC -> GFP_KERNEL_ACCOUNT allocation

Zhengchuan Liang <[email protected]>
netfilter: ip6t_eui64: reject invalid MAC header for all packets

Ren Wei <[email protected]>
netfilter: xt_multiport: validate range encoding in checkentry

Xiang Mei <[email protected]>
netfilter: nfnetlink_log: initialize nfgenmsg in NLMSG_DONE terminator

Weiming Shi <[email protected]>
ipvs: fix NULL deref in ip_vs_add_service error path

Daniel Golle <[email protected]>
selftests: net: bridge_vlan_mcast: wait for h1 before querier check

Greg Kroah-Hartman <[email protected]>
xfrm_user: fix info leak in build_mapping()

Kotlyarov Mihail <[email protected]>
xfrm: fix refcount leak in xfrm_migrate_policy_find

Steffen Klassert <[email protected]>
xfrm: Wait for RCU readers during policy netns exit

Maciej Fijalkowski <[email protected]>
xsk: validate MTU against usable frame size on bind

Maciej Fijalkowski <[email protected]>
xsk: fix XDP_UMEM_SG_FLAG issues

Maciej Fijalkowski <[email protected]>
xsk: respect tailroom for ZC setups

Maciej Fijalkowski <[email protected]>
xsk: tighten UMEM headroom validation to account for tailroom and min frame

Agalakov Daniil <[email protected]>
e1000: check return value of e1000_read_eeprom

Michal Schmidt <[email protected]>
ixgbevf: add missing negotiate_features op to Hyper-V ops table

Pengpeng Hou <[email protected]>
tracing/probe: reject non-closed empty immediate strings

Jon Hunter <[email protected]>
dt-bindings: net: Fix Tegra234 MGBE PTP clock

Jon Hunter <[email protected]>
net: stmmac: Fix PTP ref clock for Tegra234

Pengpeng Hou <[email protected]>
nfc: s3fwrn5: allocate rx skb before consuming bytes

Chris J Arges <[email protected]>
net: increase IP_TUNNEL_RECURSION_LIMIT to 5

Yiqi Sun <[email protected]>
ipv4: icmp: fix null-ptr-deref in icmp_build_probe()

Fernando Fernandez Mancera <[email protected]>
ipv4: nexthop: allocate skb dynamically in rtm_get_nexthop()

Fernando Fernandez Mancera <[email protected]>
ipv4: nexthop: avoid duplicate NHA_HW_STATS_ENABLE on nexthop group dump

Eric Dumazet <[email protected]>
net: lapbether: handle NETDEV_PRE_TYPE_CHANGE

Ruide Cao <[email protected]>
net: sched: act_csum: validate nested VLAN headers

Nicholas Carlini <[email protected]>
eventpoll: defer struct eventpoll free to RCU grace period

Maíra Canal <[email protected]>
drm/vc4: Protect madv read in vc4_gem_object_mmap() with madv_lock

Maíra Canal <[email protected]>
drm/vc4: Fix a memory leak in hang state error path

Maíra Canal <[email protected]>
drm/vc4: Fix memory leak of BO array in hang state

Maíra Canal <[email protected]>
drm/vc4: Release runtime PM reference after binding V3D

Keenan Dong <[email protected]>
xfrm: account XFRMA_IF_ID in aevent size calculation

Maximilian Pezzullo <[email protected]>
HID: amd_sfh: don't log error when device discovery fails with -EOPNOTSUPP

Long Li <[email protected]>
PCI: hv: Set default NUMA node to 0 for devices without affinity info

Serhii Pievniev <[email protected]>
tools/power/turbostat: Fix microcode patch level output for AMD/Hygon

Mukesh Ojha <[email protected]>
soc: qcom: pd-mapper: Fix element length in servreg_loc_pfr_req_ei

Markus Niebel <[email protected]>
arm64: dts: imx93-tqma9352: improve eMMC pad configuration

Luke Wang <[email protected]>
arm64: dts: imx93-9x9-qsb: change usdhc tuning step for eMMC and SD

Sebastian Krzyszkowiak <[email protected]>
arm64: dts: imx8mq: Set the correct gpu_ahb clock frequency

Daniel J Blueman <[email protected]>
arm64: dts: qcom: hamoa/x1: fix idle exit latency

Potin Lai <[email protected]>
soc: aspeed: socinfo: Mask table entries for accurate SoC ID matching

Tomasz Merta <[email protected]>
ASoC: stm32_sai: fix incorrect BCLK polarity for DSP_A/B, LEFT_J

John Pavlick <[email protected]>
net: sfp: add quirks for Hisense and HSGQ GPON ONT SFP modules

Pengpeng Hou <[email protected]>
wifi: brcmfmac: validate bsscfg indices in IF events

Arthur Husband <[email protected]>
ata: ahci: force 32-bit DMA for JMicron JMB582/JMB585

Benoît Sevens <[email protected]>
HID: roccat: fix use-after-free in roccat_report_event

songxiebing <[email protected]>
ALSA: hda/realtek: Add quirk for Lenovo Yoga Pro 7 14IAH10

leo vriska <[email protected]>
HID: quirks: add HID_QUIRK_ALWAYS_POLL for 8BitDo Pro 3

Mario Limonciello <[email protected]>
platform/x86/amd: pmc: Add Thinkpad L14 Gen3 to quirk_s2idle_bug

Andy Shevchenko <[email protected]>
pinctrl: intel: Fix the revision for new features (1kOhm PD, HW debouncer)

Alexander Savenko <[email protected]>
ALSA: hda/realtek: Add quirk for Lenovo Yoga Pro 7 14IMH9

Gilson Marquato Júnior <[email protected]>

    ASoC: amd: yc: Add DMI entry for HP Laptop 15-fc0xxx

Fredric Cover <[email protected]>
fs/smb/client: fix out-of-bounds read in cifs_sanitize_prepath

Phil Willoughby <[email protected]>
ALSA: usb-audio: Fix quirk flags for NeuralDSP Quad Cortex

Takashi Iwai <[email protected]>
ALSA: hda/realtek: Add quirk for Samsung Book2 Pro 360 (NP950QED)

Kuninori Morimoto <[email protected]>
ASoC: soc-core: call missing INIT_LIST_HEAD() for card_aux_list

Pengpeng Hou <[email protected]>
wifi: wl1251: validate packet IDs before indexing tx_frames

Dustin L. Howett <[email protected]>
ALSA: hda/realtek: add quirk for Framework F111:000F

Florian Westphal <[email protected]>
netfilter: nft_set_pipapo_avx2: don't return non-matching entry on expiry

Joel Fernandes <[email protected]>
srcu: Use irq_work to start GP in tiny SRCU

Donet Tom <[email protected]>
drm/amdgpu: Handle GPU page faults correctly on non-4K page systems

César Montoya <[email protected]>

    ALSA: hda/realtek: Add mute LED quirk for HP Pavilion 15-eg0xxx

Goldwyn Rodrigues <[email protected]>
btrfs: tracepoints: get correct superblock from dentry in event btrfs_sync_file()

Matthew Schwartz <[email protected]>
platform/x86: asus-nb-wmi: add DMI quirk for ASUS ROG Flow Z13-KJP GZ302EAC

Wenyuan Li <[email protected]>
can: mcp251x: add error handling for power enable in open and resume

Cássio Gabriel <[email protected]>
ASoC: SOF: topology: reject invalid vendor array size in token parser

Zhang Heng <[email protected]>
ASoC: amd: yc: Add DMI quirk for Thin A15 B7VF

Cen Zhang <[email protected]>

    Bluetooth: hci_sync: annotate data-races around hdev->req_status

Arnd Bergmann <[email protected]>
ALSA: asihpi: avoid write overflow check warning

Arnd Bergmann <[email protected]>
media: rkvdec: reduce stack usage in rkvdec_init_v4l2_vp9_count_tbl()

Matthew Schwartz <[email protected]>
ALSA: hda/realtek: Add quirk for ASUS ROG Flow Z13-KJP GZ302EAC

Andrii Kovalchuk <[email protected]>

    ALSA: hda/realtek: Add HP ENVY Laptop 13-ba0xxx quirk

Vee Satayamas <[email protected]>
ASoC: amd: yc: Add DMI quirk for ASUS EXPERTBOOK BM1403CDA

Jacob Moroni <[email protected]>
RDMA/irdma: Fix double free related to rereg_user_mr

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

Diffstat:

 Documentation/admin-guide/mm/damon/reclaim.rst     |   4 +
 .../bindings/net/nvidia,tegra234-mgbe.yaml         |   4 +-
 Makefile                                           |   4 +-
 arch/arm64/boot/dts/freescale/imx8mq.dtsi          |   2 +-
 arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts    |   2 +
 arch/arm64/boot/dts/freescale/imx93-tqma9352.dtsi  |  26 +--
 arch/arm64/boot/dts/qcom/x1e80100.dtsi             |   2 +-
 arch/arm64/include/asm/uaccess.h                   |   2 +-
 arch/arm64/kvm/guest.c                             |   4 +-
 arch/loongarch/kvm/vcpu.c                          |   2 +-
 arch/loongarch/kvm/vm.c                            |   2 +-
 arch/mips/kvm/mips.c                               |   4 +-
 arch/powerpc/include/asm/uaccess.h                 |   3 +-
 arch/powerpc/kvm/book3s.c                          |   4 +-
 arch/powerpc/kvm/booke.c                           |   4 +-
 arch/powerpc/lib/pmem.c                            |  11 +-
 arch/riscv/kvm/vcpu.c                              |   2 +-
 arch/riscv/kvm/vm.c                                |   2 +-
 arch/s390/kvm/kvm-s390.c                           |   4 +-
 arch/x86/events/intel/uncore_discovery.c           |   2 +-
 arch/x86/include/asm/uaccess.h                     |   2 +-
 arch/x86/include/asm/uaccess_32.h                  |   8 +-
 arch/x86/include/asm/uaccess_64.h                  |  16 +-
 arch/x86/include/uapi/asm/kvm.h                    |  12 +-
 arch/x86/kvm/svm/sev.c                             |  24 ++-
 arch/x86/kvm/x86.c                                 |  18 +-
 arch/x86/lib/copy_user_uncached_64.S               |   6 +-
 arch/x86/lib/usercopy_32.c                         |   9 +-
 arch/x86/lib/usercopy_64.c                         |  12 +-
 crypto/af_alg.c                                    |   2 +
 crypto/algif_aead.c                                |   2 +-
 crypto/algif_skcipher.c                            |   5 +
 drivers/ata/ahci.c                                 |  14 ++
 drivers/gpio/gpio-tegra.c                          |   2 +-
 drivers/gpio/gpiolib.c                             |  43 ++---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c             |   6 +-
 drivers/gpu/drm/i915/i915_gem.c                    |   2 +-
 drivers/gpu/drm/qxl/qxl_ioctl.c                    |   2 +-
 drivers/gpu/drm/vc4/vc4_bo.c                       |   3 +
 drivers/gpu/drm/vc4/vc4_gem.c                      |  19 +-
 drivers/gpu/drm/vc4/vc4_hdmi.c                     |  14 +-
 drivers/gpu/drm/vc4/vc4_v3d.c                      |   1 +
 drivers/gpu/drm/xe/xe_mmio.c                       | 135 ++++++-------
 drivers/gpu/drm/xe/xe_mmio.h                       |  72 ++-----
 drivers/gpu/drm/xe/xe_trace.h                      |   7 +-
 drivers/hid/amd-sfh-hid/amd_sfh_pcie.c             |   3 +-
 drivers/hid/hid-alps.c                             |   3 +
 drivers/hid/hid-core.c                             |   3 +
 drivers/hid/hid-ids.h                              |   3 +
 drivers/hid/hid-quirks.c                           |   1 +
 drivers/hid/hid-roccat.c                           |   2 +
 drivers/hwmon/powerz.c                             |   8 +-
 drivers/i2c/busses/i2c-s3c2410.c                   |   7 +-
 drivers/infiniband/hw/irdma/verbs.c                |   1 +
 drivers/infiniband/sw/rdmavt/qp.c                  |   8 +-
 drivers/md/bcache/super.c                          |   7 +
 .../mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c   |   9 +
 drivers/media/test-drivers/vidtv/vidtv_bridge.c    |   4 +-
 drivers/media/test-drivers/vidtv/vidtv_channel.c   |   4 +
 drivers/media/test-drivers/vidtv/vidtv_mux.c       |   4 +-
 drivers/media/test-drivers/vidtv/vidtv_ts.c        |  48 ++---
 drivers/media/test-drivers/vidtv/vidtv_ts.h        |   4 +-
 drivers/media/usb/as102/as102_usb_drv.c            |   2 +
 drivers/media/usb/em28xx/em28xx-video.c            |  14 +-
 drivers/media/usb/hackrf/hackrf.c                  |   7 +-
 drivers/net/can/spi/mcp251x.c                      |  29 ++-
 drivers/net/ethernet/intel/e1000/e1000_ethtool.c   |   8 +-
 drivers/net/ethernet/intel/idpf/idpf_virtchnl.c    |  15 +-
 drivers/net/ethernet/intel/ixgbevf/vf.c            |   7 +
 drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c  |  19 +-
 drivers/net/ethernet/wangxun/txgbe/txgbe_type.h    |   8 +-
 drivers/net/ipa/reg/gsi_reg-v5.0.c                 |   9 +-
 drivers/net/phy/sfp.c                              |  16 ++
 drivers/net/usb/cdc-phonet.c                       |   7 +-
 drivers/net/wan/lapbether.c                        |  13 +-
 .../wireless/broadcom/brcm80211/brcmfmac/fweh.c    |   5 +
 drivers/net/wireless/realtek/rtw88/usb.c           |   3 +-
 drivers/net/wireless/ti/wl1251/tx.c                |   8 +-
 drivers/nfc/s3fwrn5/uart.c                         |  10 +-
 drivers/ntb/ntb_transport.c                        |   7 +-
 drivers/pci/bus.c                                  |   6 +-
 drivers/pci/controller/pci-hyperv.c                |   8 +
 drivers/pci/endpoint/functions/pci-epf-vntb.c      |   1 +
 drivers/pci/pci-driver.c                           |   8 -
 drivers/pci/pci.c                                  |  10 +-
 drivers/pci/pci.h                                  |   1 -
 drivers/pinctrl/intel/pinctrl-intel.c              |   2 +-
 drivers/platform/x86/amd/pmc/pmc-quirks.c          |   9 +
 drivers/platform/x86/asus-nb-wmi.c                 |   2 +-
 drivers/soc/aspeed/aspeed-socinfo.c                |   2 +-
 drivers/soc/qcom/pdr_internal.h                    |   2 +-
 drivers/soc/qcom/qcom_pdr_msg.c                    |   2 +-
 drivers/staging/media/rkvdec/rkvdec-vp9.c          |   3 +-
 drivers/staging/rtl8723bs/core/rtw_security.c      |   2 +-
 drivers/staging/sm750fb/sm750.c                    |   3 +
 drivers/thermal/thermal_core.c                     |  36 +++-
 drivers/thermal/thermal_core.h                     |   1 +
 drivers/usb/class/cdc-acm.c                        |  53 ++++-
 drivers/usb/core/port.c                            |   1 +
 drivers/usb/gadget/function/f_hid.c                |  15 +-
 drivers/usb/gadget/function/f_ncm.c                |   4 +-
 drivers/usb/gadget/function/f_phonet.c             |   9 +
 drivers/usb/gadget/udc/renesas_usb3.c              |   7 +-
 drivers/usb/serial/option.c                        |   2 +
 drivers/usb/storage/unusual_devs.h                 |   7 +-
 drivers/usb/usbip/usbip_common.c                   |  12 ++
 drivers/video/fbdev/tdfxfb.c                       |   3 +
 drivers/video/fbdev/udlfb.c                        |   3 +
 fs/dcache.c                                        |   4 +-
 fs/eventpoll.c                                     |   6 +-
 fs/nilfs2/dat.c                                    |   3 +
 fs/ocfs2/aops.c                                    |   3 +-
 fs/ocfs2/inode.c                                   |  31 +++
 fs/ocfs2/mmap.c                                    |   7 +-
 fs/ocfs2/ocfs2_trace.h                             |  10 +-
 fs/ocfs2/resize.c                                  |  10 +-
 fs/smb/client/fs_context.c                         |   4 +
 fs/smb/client/smb2inode.c                          |   2 +-
 fs/smb/server/connection.c                         |   1 +
 fs/smb/server/smb2pdu.c                            |   7 +-
 fs/smb/server/smbacl.c                             |   3 +-
 include/linux/clockchips.h                         |   2 +
 include/linux/kvm_host.h                           |  93 +++++----
 include/linux/soc/qcom/pdr.h                       |   1 +
 include/linux/srcutiny.h                           |   4 +
 include/linux/uaccess.h                            |  11 +-
 include/net/ip_tunnels.h                           |   2 +-
 include/net/netfilter/nf_queue.h                   |   1 -
 include/net/pkt_cls.h                              |   2 +
 include/net/xdp_sock.h                             |   2 +-
 include/net/xdp_sock_drv.h                         |  23 ++-
 include/trace/events/btrfs.h                       |  11 +-
 include/uapi/linux/kvm.h                           |  19 +-
 kernel/events/uprobes.c                            |   4 +
 kernel/fork.c                                      |  17 +-
 kernel/rcu/srcutiny.c                              |  19 +-
 kernel/sched/deadline.c                            |   2 +-
 kernel/time/clockevents.c                          |  27 ++-
 kernel/time/hrtimer.c                              |   1 +
 kernel/time/tick-broadcast.c                       |   8 +-
 kernel/time/tick-common.c                          |   1 +
 kernel/time/tick-sched.c                           |   1 +
 kernel/trace/trace_probe.c                         |   2 +-
 lib/iov_iter.c                                     |   4 +-
 mm/backing-dev.c                                   |   5 +-
 mm/kasan/init.c                                    |   8 +-
 net/bluetooth/hci_conn.c                           |   2 +-
 net/bluetooth/hci_core.c                           |   2 +-
 net/bluetooth/hci_sync.c                           |  20 +-
 net/can/raw.c                                      |  11 +-
 net/ipv4/icmp.c                                    |   7 +
 net/ipv4/nexthop.c                                 |  41 ++--
 net/ipv6/exthdrs.c                                 |   4 +
 net/ipv6/netfilter/ip6t_eui64.c                    |   3 +-
 net/ipv6/seg6_hmac.c                               |   2 +
 net/l2tp/l2tp_core.c                               |   5 +
 net/netfilter/ipvs/ip_vs_ctl.c                     |   1 -
 net/netfilter/nf_conntrack_netlink.c               |   2 +-
 net/netfilter/nf_conntrack_proto_sctp.c            |   3 +-
 net/netfilter/nfnetlink_log.c                      |   8 +-
 net/netfilter/nfnetlink_queue.c                    | 214 ++++++++-------------
 net/netfilter/nft_set_pipapo_avx2.c                |  20 +-
 net/netfilter/xt_multiport.c                       |  34 +++-
 net/nfc/digital_technology.c                       |   6 +
 net/nfc/llcp_core.c                                |   2 +
 net/rxrpc/key.c                                    |   5 +-
 net/sched/act_csum.c                               |   6 +-
 net/sched/em_cmp.c                                 |   5 +-
 net/sched/em_nbyte.c                               |   2 +
 net/sched/em_text.c                                |  11 +-
 net/unix/diag.c                                    |  21 +-
 net/xdp/xdp_umem.c                                 |   3 +-
 net/xdp/xsk.c                                      |   4 +-
 net/xdp/xsk_buff_pool.c                            |  32 ++-
 net/xfrm/xfrm_policy.c                             |   5 +-
 net/xfrm/xfrm_user.c                               |  11 +-
 scripts/checkpatch.pl                              |  10 +
 scripts/generate_rust_analyzer.py                  |   3 +-
 sound/firewire/fireworks/fireworks_command.c       |   5 +-
 sound/pci/asihpi/hpimsgx.c                         |   6 +-
 sound/pci/ctxfi/ctvmem.h                           |   2 +-
 sound/pci/hda/patch_realtek.c                      |  10 +
 sound/soc/amd/yc/acp6x-mach.c                      |  21 ++
 sound/soc/qcom/qdsp6/q6apm.c                       |  14 +-
 sound/soc/soc-core.c                               |   1 +
 sound/soc/sof/topology.c                           |   2 +-
 sound/soc/stm/stm32_sai_sub.c                      |   3 +
 sound/usb/6fire/chip.c                             |  17 +-
 sound/usb/format.c                                 |  86 +++++++--
 sound/usb/quirks.c                                 |   2 +
 tools/objtool/check.c                              |   2 +-
 tools/power/x86/turbostat/turbostat.c              |   9 +-
 .../selftests/net/forwarding/bridge_vlan_mcast.sh  |   1 +
 virt/kvm/binary_stats.c                            |   2 +-
 virt/kvm/kvm_main.c                                |  20 +-
 195 files changed, 1379 insertions(+), 736 deletions(-)
author maintainer
#1 lore raw

PATCH 1/162 RDMA/irdma: Fix double free related to rereg_user_mr

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

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

From: Jacob Moroni <[email protected]>

[ Upstream commit 29a3edd7004bb635d299fb9bc6f0ea4ef13ed5a2 ]

If IB_MR_REREG_TRANS is set during rereg_user_mr, the umem will be released and a new one will be allocated in irdma_rereg_mr_trans. If any step of irdma_rereg_mr_trans fails after the new umem is allocated, it releases the umem, but does not set iwmr->region to NULL. The problem is that this failure is propagated to the user, who will then call ibv_dereg_mr (as they should). Then, the dereg_mr path will see a non-NULL umem and attempt to call ib_umem_release again.

Fix this by setting iwmr->region to NULL after ib_umem_release.

Fixed: 5ac388db27c4 ("RDMA/irdma: Add support to re-register a memory region")

---
 drivers/infiniband/hw/irdma/verbs.c | 1 +
 1 file changed, 1 insertion(+)
drivers/infiniband/hw/irdma/verbs.c +1 -0
index 1f267dea6460e..0b9cf175ed73b 100644
@@ -3210,6 +3210,7 @@ static int irdma_rereg_mr_trans(struct irdma_mr *iwmr, u64 start, u64 len,
 
 err:
 	ib_umem_release(region);
+	iwmr->region = NULL;
 	return err;
 }
 
Signature · 1 line
2.53.0
author maintainer
#2 lore raw

PATCH 2/162 ASoC: amd: yc: Add DMI quirk for ASUS EXPERTBOOK BM1403CDA

In reply to Greg Kroah-Hartman

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

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

From: Vee Satayamas <[email protected]>

[ Upstream commit f200b2f9a810c440c6750b56fc647b73337749a1 ]

Add a DMI quirk for the Asus Expertbook BM1403CDA to resolve the issue of the internal microphone not being detected.

---
 sound/soc/amd/yc/acp6x-mach.c | 7 +++++++
 1 file changed, 7 insertions(+)
sound/soc/amd/yc/acp6x-mach.c +7 -0
index 51a0de248497e..b8a957602b0a0 100644
@@ -710,6 +710,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
 			DMI_MATCH(DMI_BOARD_NAME, "PM1503CDA"),
 		}
 	},
+	{
+		.driver_data = &acp6x_card,
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_BOARD_NAME, "BM1403CDA"),
+		}
+	},
 	{}
 };
 
Signature · 1 line
2.53.0
author maintainer
#3 lore raw

PATCH 3/162 ALSA: hda/realtek: Add HP ENVY Laptop 13-ba0xxx quirk

In reply to Greg Kroah-Hartman

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

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

From: Andrii Kovalchuk <[email protected]>

[ Upstream commit 793b008cd39516385791a1d1d223d817e947a471 ]

Add a PCI quirk for HP ENVY Laptop 13-ba0xxx (PCI device ID 0x8756) to enable proper mute LED and mic mute behavior using the ALC245_FIXUP_HP_X360_MUTE_LEDS fixup.

---
 sound/pci/hda/patch_realtek.c | 1 +
 1 file changed, 1 insertion(+)
sound/pci/hda/patch_realtek.c +1 -0
index fad159187f445..0dd789119f96b 100644
@@ -10895,6 +10895,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x103c, 0x8730, "HP ProBook 445 G7", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
 	SND_PCI_QUIRK(0x103c, 0x8735, "HP ProBook 435 G7", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
 	SND_PCI_QUIRK(0x103c, 0x8736, "HP", ALC285_FIXUP_HP_GPIO_AMP_INIT),
+	SND_PCI_QUIRK(0x103c, 0x8756, "HP ENVY Laptop 13-ba0xxx", ALC245_FIXUP_HP_X360_MUTE_LEDS),
 	SND_PCI_QUIRK(0x103c, 0x8760, "HP EliteBook 8{4,5}5 G7", ALC285_FIXUP_HP_BEEP_MICMUTE_LED),
 	SND_PCI_QUIRK(0x103c, 0x876e, "HP ENVY x360 Convertible 13-ay0xxx", ALC245_FIXUP_HP_X360_MUTE_LEDS),
 	SND_PCI_QUIRK(0x103c, 0x877a, "HP", ALC285_FIXUP_HP_MUTE_LED),
Signature · 1 line
2.53.0
author maintainer
#4 lore raw

PATCH 4/162 ALSA: hda/realtek: Add quirk for ASUS ROG Flow Z13-KJP GZ302EAC

In reply to Greg Kroah-Hartman

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

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

From: Matthew Schwartz <[email protected]>

[ Upstream commit 59f68dc1d8df3142cb58fd2568966a9bb7b0ed8a ]

Fixes lack of audio output on the ASUS ROG Flow Z13-KJP GZ302EAC model, similar to the ASUS ROG Flow Z13 GZ302EA.

---
 sound/pci/hda/patch_realtek.c | 1 +
 1 file changed, 1 insertion(+)
sound/pci/hda/patch_realtek.c +1 -0
index 0dd789119f96b..96df0d12b68dc 100644
@@ -11197,6 +11197,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS G513PI/PU/PV", ALC287_FIXUP_CS35L41_I2C_2),
 	SND_PCI_QUIRK(0x1043, 0x14f2, "ASUS VivoBook X515JA", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1043, 0x1503, "ASUS G733PY/PZ/PZV/PYV", ALC287_FIXUP_CS35L41_I2C_2),
+	SND_PCI_QUIRK(0x1043, 0x1514, "ASUS ROG Flow Z13 GZ302EAC", ALC287_FIXUP_CS35L41_I2C_2),
 	SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A),
 	SND_PCI_QUIRK(0x1043, 0x1533, "ASUS GV302XA/XJ/XQ/XU/XV/XI", ALC287_FIXUP_CS35L41_I2C_2),
 	SND_PCI_QUIRK(0x1043, 0x1573, "ASUS GZ301VV/VQ/VU/VJ/VA/VC/VE/VVC/VQC/VUC/VJC/VEC/VCC", ALC285_FIXUP_ASUS_HEADSET_MIC),
Signature · 1 line
2.53.0
author maintainer
#5 lore raw

PATCH 5/162 media: rkvdec: reduce stack usage in rkvdec_init_v4l2_vp9_count_tbl()

In reply to Greg Kroah-Hartman

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

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

From: Arnd Bergmann <[email protected]>

[ Upstream commit c03b7dec3c4ddc97872fa12bfca75bae9cb46510 ]

The deeply nested loop in rkvdec_init_v4l2_vp9_count_tbl() needs a lot of registers, so when the clang register allocator runs out, it ends up spilling countless temporaries to the stack:

drivers/media/platform/rockchip/rkvdec/rkvdec-vp9.c:966:12: error: stack frame size (1472) exceeds limit (1280) in 'rkvdec_vp9_start' [-Werror,-Wframe-larger-than]

Marking this function as noinline_for_stack keeps it out of rkvdec_vp9_start(), giving the compiler more room for optimization.

The resulting code is good enough that both the total stack usage and the loop get enough better to stay under the warning limit, though it's still slow, and would need a larger rework if this function ends up being called in a fast path.

---
 drivers/staging/media/rkvdec/rkvdec-vp9.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/staging/media/rkvdec/rkvdec-vp9.c +2 -1
index 0e7e16f20eeb0..bc74d2d824ef2 100644
@@ -923,7 +923,8 @@ static void rkvdec_vp9_done(struct rkvdec_ctx *ctx,
 	update_ctx_last_info(vp9_ctx);
 }
 
-static void rkvdec_init_v4l2_vp9_count_tbl(struct rkvdec_ctx *ctx)
+static noinline_for_stack void
+rkvdec_init_v4l2_vp9_count_tbl(struct rkvdec_ctx *ctx)
 {
 	struct rkvdec_vp9_ctx *vp9_ctx = ctx->priv;
 	struct rkvdec_vp9_intra_frame_symbol_counts *intra_cnts = vp9_ctx->count_tbl.cpu;
Signature · 1 line
2.53.0
author maintainer
#6 lore raw

PATCH 6/162 ALSA: asihpi: avoid write overflow check warning

In reply to Greg Kroah-Hartman

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

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

From: Arnd Bergmann <[email protected]>

[ Upstream commit 591721223be9e28f83489a59289579493b8e3d83 ]

clang-22 rightfully warns that the memcpy() in adapter_prepare() copies between different structures, crossing the boundary of nested structures inside it:

In file included from sound/pci/asihpi/hpimsgx.c:13:
In file included from include/linux/string.h:386:
include/linux/fortify-string.h:569:4: error: call to '__write_overflow_field' declared with 'warning' attribute: detected write beyond size of field (1st parameter); maybe use struct_group()? [-Werror,-Wattribute-warning]
569 | __write_overflow_field(p_size_field, size);

The two structures seem to refer to the same layout, despite the separate definitions, so the code is in fact correct.

Avoid the warning by copying the two inner structures separately. I see the same pattern happens in other functions in the same file, so there is a chance that this may come back in the future, but this instance is the only one that I saw in practice, hitting it multiple times per day in randconfig build.

---
 sound/pci/asihpi/hpimsgx.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
sound/pci/asihpi/hpimsgx.c +4 -2
index b68e6bfbbfbab..ed1c7b7744361 100644
@@ -581,8 +581,10 @@ static u16 adapter_prepare(u16 adapter)
 		HPI_ADAPTER_OPEN);
 	hm.adapter_index = adapter;
 	hw_entry_point(&hm, &hr);
-	memcpy(&rESP_HPI_ADAPTER_OPEN[adapter], &hr,
-		sizeof(rESP_HPI_ADAPTER_OPEN[0]));
+	memcpy(&rESP_HPI_ADAPTER_OPEN[adapter].h, &hr,
+		sizeof(rESP_HPI_ADAPTER_OPEN[adapter].h));
+	memcpy(&rESP_HPI_ADAPTER_OPEN[adapter].a, &hr.u.ax.info,
+		sizeof(rESP_HPI_ADAPTER_OPEN[adapter].a));
 	if (hr.error)
 		return hr.error;
 
Signature · 1 line
2.53.0
author maintainer
#7 lore raw

PATCH 7/162 Bluetooth: hci_sync: annotate data-races around hdev->req_status

In reply to Greg Kroah-Hartman

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

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

From: Cen Zhang <[email protected]>

[ Upstream commit b6807cfc195ef99e1ac37b2e1e60df40295daa8c ]

__hci_cmd_sync_sk() sets hdev->req_status under hdev->req_lock:

    hdev->req_status = HCI_REQ_PEND;

However, several other functions read or write hdev->req_status without holding any lock:

- hci_send_cmd_sync() reads req_status in hci_cmd_work (workqueue)
- hci_cmd_sync_complete() reads/writes from HCI event completion
- hci_cmd_sync_cancel() / hci_cmd_sync_cancel_sync() read/write
- hci_abort_conn() reads in connection abort path

Since __hci_cmd_sync_sk() runs on hdev->req_workqueue while hci_send_cmd_sync() runs on hdev->workqueue, these are different workqueues that can execute concurrently on different CPUs. The plain C accesses constitute a data race.

Add READ_ONCE()/WRITE_ONCE() annotations on all concurrent accesses to hdev->req_status to prevent potential compiler optimizations that could affect correctness (e.g., load fusing in the wait_event condition or store reordering).

---
 net/bluetooth/hci_conn.c |  2 +-
 net/bluetooth/hci_core.c |  2 +-
 net/bluetooth/hci_sync.c | 20 ++++++++++----------
 3 files changed, 12 insertions(+), 12 deletions(-)
net/bluetooth/hci_conn.c +1 -1
index b36fa056e8796..bf1c39be05211 100644
@@ -2887,7 +2887,7 @@ int hci_abort_conn(struct hci_conn *conn, u8 reason)
 	 * hci_connect_le serializes the connection attempts so only one
 	 * connection can be in BT_CONNECT at time.
 	 */
-	if (conn->state == BT_CONNECT && hdev->req_status == HCI_REQ_PEND) {
+	if (conn->state == BT_CONNECT && READ_ONCE(hdev->req_status) == HCI_REQ_PEND) {
 		switch (hci_skb_event(hdev->sent_cmd)) {
 		case HCI_EV_CONN_COMPLETE:
 		case HCI_EV_LE_CONN_COMPLETE:
net/bluetooth/hci_core.c +1 -1
index ba01d0fa07193..677f51edb2775 100644
@@ -4103,7 +4103,7 @@ static int hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb)
 		kfree_skb(skb);
 	}
 
-	if (hdev->req_status == HCI_REQ_PEND &&
+	if (READ_ONCE(hdev->req_status) == HCI_REQ_PEND &&
 	    !hci_dev_test_and_set_flag(hdev, HCI_CMD_PENDING)) {
 		kfree_skb(hdev->req_skb);
 		hdev->req_skb = skb_clone(hdev->sent_cmd, GFP_KERNEL);
net/bluetooth/hci_sync.c +10 -10
index 7339c36d58582..fbcb3bbfef4fd 100644
@@ -25,11 +25,11 @@ static void hci_cmd_sync_complete(struct hci_dev *hdev, u8 result, u16 opcode,
 {
 	bt_dev_dbg(hdev, "result 0x%2.2x", result);
 
-	if (hdev->req_status != HCI_REQ_PEND)
+	if (READ_ONCE(hdev->req_status) != HCI_REQ_PEND)
 		return;
 
 	hdev->req_result = result;
-	hdev->req_status = HCI_REQ_DONE;
+	WRITE_ONCE(hdev->req_status, HCI_REQ_DONE);
 
 	/* Free the request command so it is not used as response */
 	kfree_skb(hdev->req_skb);
@@ -167,20 +167,20 @@ struct sk_buff *__hci_cmd_sync_sk(struct hci_dev *hdev, u16 opcode, u32 plen,
 
 	hci_cmd_sync_add(&req, opcode, plen, param, event, sk);
 
-	hdev->req_status = HCI_REQ_PEND;
+	WRITE_ONCE(hdev->req_status, HCI_REQ_PEND);
 
 	err = hci_req_sync_run(&req);
 	if (err < 0)
 		return ERR_PTR(err);
 
 	err = wait_event_interruptible_timeout(hdev->req_wait_q,
-					       hdev->req_status != HCI_REQ_PEND,
+					       READ_ONCE(hdev->req_status) != HCI_REQ_PEND,
 					       timeout);
 
 	if (err == -ERESTARTSYS)
 		return ERR_PTR(-EINTR);
 
-	switch (hdev->req_status) {
+	switch (READ_ONCE(hdev->req_status)) {
 	case HCI_REQ_DONE:
 		err = -bt_to_errno(hdev->req_result);
 		break;
@@ -194,7 +194,7 @@ struct sk_buff *__hci_cmd_sync_sk(struct hci_dev *hdev, u16 opcode, u32 plen,
 		break;
 	}
 
-	hdev->req_status = 0;
+	WRITE_ONCE(hdev->req_status, 0);
 	hdev->req_result = 0;
 	skb = hdev->req_rsp;
 	hdev->req_rsp = NULL;
@@ -665,9 +665,9 @@ void hci_cmd_sync_cancel(struct hci_dev *hdev, int err)
 {
 	bt_dev_dbg(hdev, "err 0x%2.2x", err);
 
-	if (hdev->req_status == HCI_REQ_PEND) {
+	if (READ_ONCE(hdev->req_status) == HCI_REQ_PEND) {
 		hdev->req_result = err;
-		hdev->req_status = HCI_REQ_CANCELED;
+		WRITE_ONCE(hdev->req_status, HCI_REQ_CANCELED);
 
 		queue_work(hdev->workqueue, &hdev->cmd_sync_cancel_work);
 	}
@@ -683,12 +683,12 @@ void hci_cmd_sync_cancel_sync(struct hci_dev *hdev, int err)
 {
 	bt_dev_dbg(hdev, "err 0x%2.2x", err);
 
-	if (hdev->req_status == HCI_REQ_PEND) {
+	if (READ_ONCE(hdev->req_status) == HCI_REQ_PEND) {
 		/* req_result is __u32 so error must be positive to be properly
 		 * propagated.
 		 */
 		hdev->req_result = err < 0 ? -err : err;
-		hdev->req_status = HCI_REQ_CANCELED;
+		WRITE_ONCE(hdev->req_status, HCI_REQ_CANCELED);
 
 		wake_up_interruptible(&hdev->req_wait_q);
 	}
Signature · 1 line
2.53.0
author maintainer
#8 lore raw

PATCH 8/162 ASoC: amd: yc: Add DMI quirk for Thin A15 B7VF

In reply to Greg Kroah-Hartman

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

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

From: Zhang Heng <[email protected]>

[ Upstream commit 1f182ec9d7084db7dfdb2372d453c28f0e5c3f0a ]

Add a DMI quirk for the Thin A15 B7VF fixing the issue where the internal microphone was not detected.

---
 sound/soc/amd/yc/acp6x-mach.c | 7 +++++++
 1 file changed, 7 insertions(+)
sound/soc/amd/yc/acp6x-mach.c +7 -0
index b8a957602b0a0..2414c1bba0789 100644
@@ -717,6 +717,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
 			DMI_MATCH(DMI_BOARD_NAME, "BM1403CDA"),
 		}
 	},
+	{
+		.driver_data = &acp6x_card,
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "Thin A15 B7VE"),
+		}
+	},
 	{}
 };
 
Signature · 1 line
2.53.0
author maintainer
#9 lore raw

PATCH 9/162 ASoC: SOF: topology: reject invalid vendor array size in token parser

In reply to Greg Kroah-Hartman

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

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

From: Cássio Gabriel <[email protected]>

[ Upstream commit 215e5fe75881a7e2425df04aeeed47a903d5cd5d ]

sof_parse_token_sets() accepts array->size values that can be invalid for a vendor tuple array header. In particular, a zero size does not advance the parser state and can lead to non-progress parsing on malformed topology data.

Validate array->size against the minimum header size and reject values smaller than sizeof(*array) before parsing. This preserves behavior for valid topologies and hardens malformed-input handling.

---
 sound/soc/sof/topology.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/sof/topology.c +1 -1
index 0104257df930e..cdf8e56fd8a02 100644
@@ -724,7 +724,7 @@ static int sof_parse_token_sets(struct snd_soc_component *scomp,
 		asize = le32_to_cpu(array->size);
 
 		/* validate asize */
-		if (asize < 0) { /* FIXME: A zero-size array makes no sense */
+		if (asize < sizeof(*array)) {
 			dev_err(scomp->dev, "error: invalid array size 0x%x\n",
 				asize);
 			return -EINVAL;
Signature · 1 line
2.53.0
author maintainer
#10 lore raw

PATCH 10/162 can: mcp251x: add error handling for power enable in open and resume

In reply to Greg Kroah-Hartman

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

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

From: Wenyuan Li <[email protected]>

[ Upstream commit 7a57354756c7df223abe2c33774235ad70cb4231 ]

Add missing error handling for mcp251x_power_enable() calls in both mcp251x_open() and mcp251x_can_resume() functions.

In mcp251x_open(), if power enable fails, jump to error path to close candev without attempting to disable power again.

In mcp251x_can_resume(), properly check return values of power enable calls for both power and transceiver regulators. If any fails, return the error code to the PM framework and log the failure.

This ensures the driver properly handles power control failures and maintains correct device state.

[mkl: fix patch description]
[mkl: mcp251x_can_resume(): replace goto by return]
---
 drivers/net/can/spi/mcp251x.c | 29 ++++++++++++++++++++++++-----
 1 file changed, 24 insertions(+), 5 deletions(-)
drivers/net/can/spi/mcp251x.c +24 -5
index 74906aa98be3e..b241953d2ef61 100644
@@ -1212,7 +1212,11 @@ static int mcp251x_open(struct net_device *net)
 	}
 
 	mutex_lock(&priv->mcp_lock);
-	mcp251x_power_enable(priv->transceiver, 1);
+	ret = mcp251x_power_enable(priv->transceiver, 1);
+	if (ret) {
+		dev_err(&spi->dev, "failed to enable transceiver power: %pe\n", ERR_PTR(ret));
+		goto out_close_candev;
+	}
 
 	priv->force_quit = 0;
 	priv->tx_skb = NULL;
@@ -1259,6 +1263,7 @@ static int mcp251x_open(struct net_device *net)
 	mcp251x_hw_sleep(spi);
 out_close:
 	mcp251x_power_enable(priv->transceiver, 0);
+out_close_candev:
 	close_candev(net);
 	mutex_unlock(&priv->mcp_lock);
 	if (release_irq)
@@ -1494,11 +1499,25 @@ static int __maybe_unused mcp251x_can_resume(struct device *dev)
 {
 	struct spi_device *spi = to_spi_device(dev);
 	struct mcp251x_priv *priv = spi_get_drvdata(spi);
+	int ret = 0;
 
-	if (priv->after_suspend & AFTER_SUSPEND_POWER)
-		mcp251x_power_enable(priv->power, 1);
-	if (priv->after_suspend & AFTER_SUSPEND_UP)
-		mcp251x_power_enable(priv->transceiver, 1);
+	if (priv->after_suspend & AFTER_SUSPEND_POWER) {
+		ret = mcp251x_power_enable(priv->power, 1);
+		if (ret) {
+			dev_err(dev, "failed to restore power: %pe\n", ERR_PTR(ret));
+			return ret;
+		}
+	}
+
+	if (priv->after_suspend & AFTER_SUSPEND_UP) {
+		ret = mcp251x_power_enable(priv->transceiver, 1);
+		if (ret) {
+			dev_err(dev, "failed to restore transceiver power: %pe\n", ERR_PTR(ret));
+			if (priv->after_suspend & AFTER_SUSPEND_POWER)
+				mcp251x_power_enable(priv->power, 0);
+			return ret;
+		}
+	}
 
 	if (priv->after_suspend & (AFTER_SUSPEND_POWER | AFTER_SUSPEND_UP))
 		queue_work(priv->wq, &priv->restart_work);
Signature · 1 line
2.53.0
author maintainer
#11 lore raw

PATCH 11/162 platform/x86: asus-nb-wmi: add DMI quirk for ASUS ROG Flow Z13-KJP GZ302EAC

In reply to Greg Kroah-Hartman

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

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

From: Matthew Schwartz <[email protected]>

[ Upstream commit 0198d2743207d67f995cd6df89e267e1b9f5e1f1 ]

The ASUS ROG Flow Z13-KJP GZ302EAC model uses sys_vendor name ASUS rather than ASUSTeK COMPUTER INC., but it needs the same folio quirk as the other ROG Flow Z13. To keep things simple, just match on sys_vendor ASUS since it covers both.

---
 drivers/platform/x86/asus-nb-wmi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/platform/x86/asus-nb-wmi.c +1 -1
index 1955495ea95f4..10bdb1a431819 100644
@@ -547,7 +547,7 @@ static const struct dmi_system_id asus_quirks[] = {
 		.callback = dmi_matched,
 		.ident = "ASUS ROG Z13",
 		.matches = {
-			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+			DMI_MATCH(DMI_SYS_VENDOR, "ASUS"),
 			DMI_MATCH(DMI_PRODUCT_NAME, "ROG Flow Z13"),
 		},
 		.driver_data = &quirk_asus_z13,
Signature · 1 line
2.53.0
author maintainer
#12 lore raw

PATCH 12/162 btrfs: tracepoints: get correct superblock from dentry in event btrfs_sync_file()

In reply to Greg Kroah-Hartman

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

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

From: Goldwyn Rodrigues <[email protected]>

[ Upstream commit a85b46db143fda5869e7d8df8f258ccef5fa1719 ]

If overlay is used on top of btrfs, dentry->d_sb translates to overlay's super block and fsid assignment will lead to a crash.

Use file_inode(file)->i_sb to always get btrfs_sb.

---
 include/trace/events/btrfs.h | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
include/trace/events/btrfs.h +7 -4
index 0ca86909ce5bd..b964cba4169c2 100644
@@ -771,12 +771,15 @@ TRACE_EVENT(btrfs_sync_file,
 	),
 
 	TP_fast_assign(
-		const struct dentry *dentry = file->f_path.dentry;
-		const struct inode *inode = d_inode(dentry);
+		struct dentry *dentry = file_dentry(file);
+		struct inode *inode = file_inode(file);
+		struct dentry *parent = dget_parent(dentry);
+		struct inode *parent_inode = d_inode(parent);
 
-		TP_fast_assign_fsid(btrfs_sb(file->f_path.dentry->d_sb));
+		dput(parent);
+		TP_fast_assign_fsid(btrfs_sb(inode->i_sb));
 		__entry->ino		= btrfs_ino(BTRFS_I(inode));
-		__entry->parent		= btrfs_ino(BTRFS_I(d_inode(dentry->d_parent)));
+		__entry->parent		= btrfs_ino(BTRFS_I(parent_inode));
 		__entry->datasync	= datasync;
 		__entry->root_objectid	= btrfs_root_id(BTRFS_I(inode)->root);
 	),
Signature · 1 line
2.53.0
author maintainer
#13 lore raw

PATCH 13/162 ALSA: hda/realtek: Add mute LED quirk for HP Pavilion 15-eg0xxx

In reply to Greg Kroah-Hartman

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

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

From: César Montoya <[email protected]>

[ Upstream commit 2f388b4e8fdd6b0f27cafd281658daacfd85807e ]

The HP Pavilion 15-eg0xxx with subsystem ID 0x103c87cb uses a Realtek ALC287 codec with a mute LED wired to GPIO pin 4 (mask 0x10). The existing ALC287_FIXUP_HP_GPIO_LED fixup already handles this correctly, but the subsystem ID was missing from the quirk table.

GPIO pin confirmed via manual hda-verb testing:
hda-verb SET_GPIO_MASK 0x10
hda-verb SET_GPIO_DIRECTION 0x10
hda-verb SET_GPIO_DATA 0x10

---
 sound/pci/hda/patch_realtek.c | 1 +
 1 file changed, 1 insertion(+)
sound/pci/hda/patch_realtek.c +1 -0
index 96df0d12b68dc..440ec4e1528ae 100644
@@ -10909,6 +10909,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x103c, 0x8788, "HP OMEN 15", ALC285_FIXUP_HP_MUTE_LED),
 	SND_PCI_QUIRK(0x103c, 0x87b7, "HP Laptop 14-fq0xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
 	SND_PCI_QUIRK(0x103c, 0x87c8, "HP", ALC287_FIXUP_HP_GPIO_LED),
+	SND_PCI_QUIRK(0x103c, 0x87cb, "HP Pavilion 15-eg0xxx", ALC287_FIXUP_HP_GPIO_LED),
 	SND_PCI_QUIRK(0x103c, 0x87cc, "HP Pavilion 15-eg0xxx", ALC287_FIXUP_HP_GPIO_LED),
 	SND_PCI_QUIRK(0x103c, 0x87d3, "HP Laptop 15-gw0xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
 	SND_PCI_QUIRK(0x103c, 0x87df, "HP ProBook 430 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
Signature · 1 line
2.53.0
author maintainer
#14 lore raw

PATCH 14/162 drm/amdgpu: Handle GPU page faults correctly on non-4K page systems

In reply to Greg Kroah-Hartman

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

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

From: Donet Tom <[email protected]>

[ Upstream commit 4e9597f22a3cb8600c72fc266eaac57981d834c8 ]

During a GPU page fault, the driver restores the SVM range and then maps it into the GPU page tables. The current implementation passes a GPU-page-size (4K-based) PFN to svm_range_restore_pages() to restore the range.

SVM ranges are tracked using system-page-size PFNs. On systems where the system page size is larger than 4K, using GPU-page-size PFNs to restore the range causes two problems:

Range lookup fails:
Because the restore function receives PFNs in GPU (4K) units, the SVM range lookup does not find the existing range. This will result in a duplicate SVM range being created.

VMA lookup failure:
The restore function also tries to locate the VMA for the faulting address. It converts the GPU-page-size PFN into an address using the system page size, which results in an incorrect address on non-4K page-size systems. As a result, the VMA lookup fails with the message: "address 0xxxx VMA is removed".

This patch passes the system-page-size PFN to svm_range_restore_pages() so that the SVM range is restored correctly on non-4K page systems.

(cherry picked from commit 074fe395fb13247b057f60004c7ebcca9f38ef46)
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +3 -3
index 13252c27cf55e..a29d01202b5b3 100644
@@ -2806,14 +2806,14 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid,
 	if (!root)
 		return false;
 
-	addr /= AMDGPU_GPU_PAGE_SIZE;
-
 	if (is_compute_context && !svm_range_restore_pages(adev, pasid, vmid,
-	    node_id, addr, ts, write_fault)) {
+	    node_id, addr >> PAGE_SHIFT, ts, write_fault)) {
 		amdgpu_bo_unref(&root);
 		return true;
 	}
 
+	addr /= AMDGPU_GPU_PAGE_SIZE;
+
 	r = amdgpu_bo_reserve(root, true);
 	if (r)
 		goto error_unref;
Signature · 1 line
2.53.0
author maintainer
#15 lore raw

PATCH 15/162 srcu: Use irq_work to start GP in tiny SRCU

In reply to Greg Kroah-Hartman

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

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

From: Joel Fernandes <[email protected]>

[ Upstream commit a6fc88b22bc8d12ad52e8412c667ec0f5bf055af ]

Tiny SRCU's srcu_gp_start_if_needed() directly calls schedule_work(), which acquires the workqueue pool->lock.

This causes a lockdep splat when call_srcu() is called with a scheduler lock held, due to:

call_srcu() [holding pi_lock]

    srcu_gp_start_if_needed()
      schedule_work() -> pool->lock

workqueue_init() / create_worker() [holding pool->lock]

    wake_up_process() -> try_to_wake_up() -> pi_lock

Also add irq_work_sync() to cleanup_srcu_struct() to prevent a use-after-free if a queued irq_work fires after cleanup begins.

Tested with rcutorture SRCU-T and no lockdep warnings.

[ Thanks to Boqun for similar fix in patch "rcu: Use an intermediate irq_work to start process_srcu()" ]

---
 include/linux/srcutiny.h |  4 ++++
 kernel/rcu/srcutiny.c    | 19 ++++++++++++++++++-
 2 files changed, 22 insertions(+), 1 deletion(-)
include/linux/srcutiny.h +4 -0
index 4d96bbdb45f08..6f39d3d8ef879 100644
@@ -11,6 +11,7 @@
 #ifndef _LINUX_SRCU_TINY_H
 #define _LINUX_SRCU_TINY_H
 
+#include <linux/irq_work_types.h>
 #include <linux/swait.h>
 
 struct srcu_struct {
@@ -24,18 +25,21 @@ struct srcu_struct {
 	struct rcu_head *srcu_cb_head;	/* Pending callbacks: Head. */
 	struct rcu_head **srcu_cb_tail;	/* Pending callbacks: Tail. */
 	struct work_struct srcu_work;	/* For driving grace periods. */
+	struct irq_work srcu_irq_work;	/* Defer schedule_work() to irq work. */
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 	struct lockdep_map dep_map;
 #endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 };
 
 void srcu_drive_gp(struct work_struct *wp);
+void srcu_tiny_irq_work(struct irq_work *irq_work);
 
 #define __SRCU_STRUCT_INIT(name, __ignored, ___ignored)			\
 {									\
 	.srcu_wq = __SWAIT_QUEUE_HEAD_INITIALIZER(name.srcu_wq),	\
 	.srcu_cb_tail = &name.srcu_cb_head,				\
 	.srcu_work = __WORK_INITIALIZER(name.srcu_work, srcu_drive_gp),	\
+	.srcu_irq_work = { .func = srcu_tiny_irq_work },		\
 	__SRCU_DEP_MAP_INIT(name)					\
 }
 
kernel/rcu/srcutiny.c +18 -1
index 4dcbf8aa80ff7..ddea40b68e5f6 100644
@@ -9,6 +9,7 @@
  */
 
 #include <linux/export.h>
+#include <linux/irq_work.h>
 #include <linux/mutex.h>
 #include <linux/preempt.h>
 #include <linux/rcupdate_wait.h>
@@ -37,6 +38,7 @@ static int init_srcu_struct_fields(struct srcu_struct *ssp)
 	ssp->srcu_idx_max = 0;
 	INIT_WORK(&ssp->srcu_work, srcu_drive_gp);
 	INIT_LIST_HEAD(&ssp->srcu_work.entry);
+	init_irq_work(&ssp->srcu_irq_work, srcu_tiny_irq_work);
 	return 0;
 }
 
@@ -80,6 +82,7 @@ EXPORT_SYMBOL_GPL(init_srcu_struct);
 void cleanup_srcu_struct(struct srcu_struct *ssp)
 {
 	WARN_ON(ssp->srcu_lock_nesting[0] || ssp->srcu_lock_nesting[1]);
+	irq_work_sync(&ssp->srcu_irq_work);
 	flush_work(&ssp->srcu_work);
 	WARN_ON(ssp->srcu_gp_running);
 	WARN_ON(ssp->srcu_gp_waiting);
@@ -168,6 +171,20 @@ void srcu_drive_gp(struct work_struct *wp)
 }
 EXPORT_SYMBOL_GPL(srcu_drive_gp);
 
+/*
+ * Use an irq_work to defer schedule_work() to avoid acquiring the workqueue
+ * pool->lock while the caller might hold scheduler locks, causing lockdep
+ * splats due to workqueue_init() doing a wakeup.
+ */
+void srcu_tiny_irq_work(struct irq_work *irq_work)
+{
+	struct srcu_struct *ssp;
+
+	ssp = container_of(irq_work, struct srcu_struct, srcu_irq_work);
+	schedule_work(&ssp->srcu_work);
+}
+EXPORT_SYMBOL_GPL(srcu_tiny_irq_work);
+
 static void srcu_gp_start_if_needed(struct srcu_struct *ssp)
 {
 	unsigned long cookie;
@@ -181,7 +198,7 @@ static void srcu_gp_start_if_needed(struct srcu_struct *ssp)
 	WRITE_ONCE(ssp->srcu_idx_max, cookie);
 	if (!READ_ONCE(ssp->srcu_gp_running)) {
 		if (likely(srcu_init_done))
-			schedule_work(&ssp->srcu_work);
+			irq_work_queue(&ssp->srcu_irq_work);
 		else if (list_empty(&ssp->srcu_work.entry))
 			list_add(&ssp->srcu_work.entry, &srcu_boot_list);
 	}
Signature · 1 line
2.53.0
author maintainer
#16 lore raw

PATCH 16/162 netfilter: nft_set_pipapo_avx2: dont return non-matching entry on expiry

In reply to Greg Kroah-Hartman

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

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

From: Florian Westphal <[email protected]>

[ Upstream commit d3c0037ffe1273fa1961e779ff6906234d6cf53c ]

New test case fails unexpectedly when avx2 matching functions are used.

The test first loads a ranomly generated pipapo set with 'ipv4 . port' key, i.e. nft -f foo.

This works. Then, it reloads the set after a flush:
(echo flush set t s; cat foo) | nft -f -

This is expected to work, because its the same set after all and it was already loaded once.

But with avx2, this fails: nft reports a clashing element.

The reported clash is of following form:

We successfully re-inserted
a . b
c . d

Then we try to insert a . d

avx2 finds the already existing a . d, which (due to 'flush set') is marked as invalid in the new generation. It skips the element and moves to next.

Due to incorrect masking, the skip-step finds the next matching element *only considering the first field*,

i.e. we return the already reinserted "a . b", even though the last field is different and the entry should not have been matched.

No such error is reported for the generic c implementation (no avx2) or when the last field has to use the 'nft_pipapo_avx2_lookup_slow' fallback.

Bisection points to
7711f4bb4b36 ("netfilter: nft_set_pipapo: fix range overlap detection") but that fix merely uncovers this bug.

Before this commit, the wrong element is returned, but erronously reported as a full, identical duplicate.

The root-cause is too early return in the avx2 match functions. When we process the last field, we should continue to process data until the entire input size has been consumed to make sure no stale bits remain in the map.

---
 net/netfilter/nft_set_pipapo_avx2.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)
net/netfilter/nft_set_pipapo_avx2.c +10 -10
index 39e356c9687a9..9d5ada57aa6fe 100644
@@ -242,7 +242,7 @@ static int nft_pipapo_avx2_lookup_4b_2(unsigned long *map, unsigned long *fill,
 
 		b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
 		if (last)
-			return b;
+			ret = b;
 
 		if (unlikely(ret == -1))
 			ret = b / XSAVE_YMM_SIZE;
@@ -319,7 +319,7 @@ static int nft_pipapo_avx2_lookup_4b_4(unsigned long *map, unsigned long *fill,
 
 		b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
 		if (last)
-			return b;
+			ret = b;
 
 		if (unlikely(ret == -1))
 			ret = b / XSAVE_YMM_SIZE;
@@ -414,7 +414,7 @@ static int nft_pipapo_avx2_lookup_4b_8(unsigned long *map, unsigned long *fill,
 
 		b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
 		if (last)
-			return b;
+			ret = b;
 
 		if (unlikely(ret == -1))
 			ret = b / XSAVE_YMM_SIZE;
@@ -505,7 +505,7 @@ static int nft_pipapo_avx2_lookup_4b_12(unsigned long *map, unsigned long *fill,
 
 		b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
 		if (last)
-			return b;
+			ret = b;
 
 		if (unlikely(ret == -1))
 			ret = b / XSAVE_YMM_SIZE;
@@ -641,7 +641,7 @@ static int nft_pipapo_avx2_lookup_4b_32(unsigned long *map, unsigned long *fill,
 
 		b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
 		if (last)
-			return b;
+			ret = b;
 
 		if (unlikely(ret == -1))
 			ret = b / XSAVE_YMM_SIZE;
@@ -699,7 +699,7 @@ static int nft_pipapo_avx2_lookup_8b_1(unsigned long *map, unsigned long *fill,
 
 		b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
 		if (last)
-			return b;
+			ret = b;
 
 		if (unlikely(ret == -1))
 			ret = b / XSAVE_YMM_SIZE;
@@ -764,7 +764,7 @@ static int nft_pipapo_avx2_lookup_8b_2(unsigned long *map, unsigned long *fill,
 
 		b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
 		if (last)
-			return b;
+			ret = b;
 
 		if (unlikely(ret == -1))
 			ret = b / XSAVE_YMM_SIZE;
@@ -839,7 +839,7 @@ static int nft_pipapo_avx2_lookup_8b_4(unsigned long *map, unsigned long *fill,
 
 		b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
 		if (last)
-			return b;
+			ret = b;
 
 		if (unlikely(ret == -1))
 			ret = b / XSAVE_YMM_SIZE;
@@ -925,7 +925,7 @@ static int nft_pipapo_avx2_lookup_8b_6(unsigned long *map, unsigned long *fill,
 
 		b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
 		if (last)
-			return b;
+			ret = b;
 
 		if (unlikely(ret == -1))
 			ret = b / XSAVE_YMM_SIZE;
@@ -1019,7 +1019,7 @@ static int nft_pipapo_avx2_lookup_8b_16(unsigned long *map, unsigned long *fill,
 
 		b = nft_pipapo_avx2_refill(i_ul, &map[i_ul], fill, f->mt, last);
 		if (last)
-			return b;
+			ret = b;
 
 		if (unlikely(ret == -1))
 			ret = b / XSAVE_YMM_SIZE;
Signature · 1 line
2.53.0
author maintainer
#17 lore raw

PATCH 17/162 ALSA: hda/realtek: add quirk for Framework F111:000F

In reply to Greg Kroah-Hartman

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

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

From: Dustin L. Howett <[email protected]>

[ Upstream commit bac1e57adf08c9ee33e95fb09cd032f330294e70 ]

Similar to commit 7b509910b3ad ("ALSA hda/realtek: Add quirk for Framework F111:000C") and previous quirks for Framework systems with Realtek codecs.

000F is another new platform with an ALC285 which needs the same quirk.

---
 sound/pci/hda/patch_realtek.c | 1 +
 1 file changed, 1 insertion(+)
sound/pci/hda/patch_realtek.c +1 -0
index 440ec4e1528ae..2a32e1ead5e86 100644
@@ -11671,6 +11671,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0xf111, 0x0009, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0xf111, 0x000b, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0xf111, 0x000c, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
+	SND_PCI_QUIRK(0xf111, 0x000f, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
 
 #if 0
 	/* Below is a quirk table taken from the old code.
Signature · 1 line
2.53.0
author maintainer
#18 lore raw

PATCH 18/162 wifi: wl1251: validate packet IDs before indexing tx_frames

In reply to Greg Kroah-Hartman

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

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

From: Pengpeng Hou <[email protected]>

[ Upstream commit 0fd56fad9c56356e7fa7a7c52e7ecbf807a44eb0 ]

wl1251_tx_packet_cb() uses the firmware completion ID directly to index the fixed 16-entry wl->tx_frames[] array. The ID is a raw u8 from the completion block, and the callback does not currently verify that it fits the array before dereferencing it.

Reject completion IDs that fall outside wl->tx_frames[] and keep the existing NULL check in the same guard. This keeps the fix local to the trust boundary and avoids touching the rest of the completion flow.

---
 drivers/net/wireless/ti/wl1251/tx.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/net/wireless/ti/wl1251/tx.c +5 -3
index adb4840b04893..c264d83e71d9c 100644
@@ -402,12 +402,14 @@ static void wl1251_tx_packet_cb(struct wl1251 *wl,
 	int hdrlen;
 	u8 *frame;
 
-	skb = wl->tx_frames[result->id];
-	if (skb == NULL) {
-		wl1251_error("SKB for packet %d is NULL", result->id);
+	if (unlikely(result->id >= ARRAY_SIZE(wl->tx_frames) ||
+		     wl->tx_frames[result->id] == NULL)) {
+		wl1251_error("invalid packet id %u", result->id);
 		return;
 	}
 
+	skb = wl->tx_frames[result->id];
+
 	info = IEEE80211_SKB_CB(skb);
 
 	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
Signature · 1 line
2.53.0
author maintainer
#19 lore raw

PATCH 19/162 ASoC: soc-core: call missing INIT_LIST_HEAD() for card_aux_list

In reply to Greg Kroah-Hartman

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

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

From: Kuninori Morimoto <[email protected]>

[ Upstream commit b9eff9732cb0f86a68c9d1592a98ceab47c01e95 ]

Component has "card_aux_list" which is added/deled in bind/unbind aux dev function (A), and used in for_each_card_auxs() loop (B).

	static void soc_unbind_aux_dev(...)
	{
		...
		for_each_card_auxs_safe(...) {
			...
(A)			list_del(&component->card_aux_list);
		}			     ^^^^^^^^^^^^^
	}

	static int soc_bind_aux_dev(...)
	{
		...
		for_each_card_pre_auxs(...) {
			...
(A)			list_add(&component->card_aux_list, ...);
		}			     ^^^^^^^^^^^^^
		...
	}

	#define for_each_card_auxs(card, component)	\
(B)		list_for_each_entry(component, ..., card_aux_list)
						    ^^^^^^^^^^^^^

But it has been used without calling INIT_LIST_HEAD().

	> git grep card_aux_list sound/soc
	sound/soc/soc-core.c:           list_del(&component->card_aux_list);
	sound/soc/soc-core.c:           list_add(&component->card_aux_list, ...);

call missing INIT_LIST_HEAD() for it.

---
 sound/soc/soc-core.c | 1 +
 1 file changed, 1 insertion(+)
sound/soc/soc-core.c +1 -0
index a1e3829914268..5097b287b889a 100644
@@ -2801,6 +2801,7 @@ int snd_soc_component_initialize(struct snd_soc_component *component,
 	INIT_LIST_HEAD(&component->dobj_list);
 	INIT_LIST_HEAD(&component->card_list);
 	INIT_LIST_HEAD(&component->list);
+	INIT_LIST_HEAD(&component->card_aux_list);
 	mutex_init(&component->io_mutex);
 
 	if (!component->name) {
Signature · 1 line
2.53.0
author maintainer
#20 lore raw

PATCH 20/162 ALSA: hda/realtek: Add quirk for Samsung Book2 Pro 360 (NP950QED)

In reply to Greg Kroah-Hartman

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

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

From: Takashi Iwai <[email protected]>

[ Upstream commit ea31be8a2c8c99eac198f3b7f2dc770111f2b182 ]

There is another Book2 Pro model (NP950QED) that seems equipped with the same speaker module as the non-360 model, which requires ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS quirk.

---
 sound/pci/hda/patch_realtek.c | 1 +
 1 file changed, 1 insertion(+)
sound/pci/hda/patch_realtek.c +1 -0
index 2a32e1ead5e86..04e10da997b53 100644
@@ -11335,6 +11335,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x144d, 0xc176, "Samsung Notebook 9 Pro (NP930MBE-K04US)", ALC298_FIXUP_SAMSUNG_AMP),
 	SND_PCI_QUIRK(0x144d, 0xc189, "Samsung Galaxy Flex Book (NT950QCG-X716)", ALC298_FIXUP_SAMSUNG_AMP),
 	SND_PCI_QUIRK(0x144d, 0xc18a, "Samsung Galaxy Book Ion (NP930XCJ-K01US)", ALC298_FIXUP_SAMSUNG_AMP),
+	SND_PCI_QUIRK(0x144d, 0xc1ac, "Samsung Galaxy Book2 Pro 360 (NP950QED)", ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS),
 	SND_PCI_QUIRK(0x144d, 0xc1a3, "Samsung Galaxy Book Pro (NP935XDB-KC1SE)", ALC298_FIXUP_SAMSUNG_AMP),
 	SND_PCI_QUIRK(0x144d, 0xc1a4, "Samsung Galaxy Book Pro 360 (NT935QBD)", ALC298_FIXUP_SAMSUNG_AMP),
 	SND_PCI_QUIRK(0x144d, 0xc1a6, "Samsung Galaxy Book Pro 360 (NP930QBD)", ALC298_FIXUP_SAMSUNG_AMP),
Signature · 1 line
2.53.0
author maintainer
#21 lore raw

PATCH 21/162 ALSA: usb-audio: Fix quirk flags for NeuralDSP Quad Cortex

In reply to Greg Kroah-Hartman

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

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

From: Phil Willoughby <[email protected]>

[ Upstream commit bc5b4e5ae1a67700a618328217b6a3bd0f296e97 ]

The NeuralDSP Quad Cortex does not support DSD playback. We need this product-specific entry with zero quirks because otherwise it falls through to the vendor-specific entry which marks it as supporting DSD playback.

---
 sound/usb/quirks.c | 2 ++
 1 file changed, 2 insertions(+)
sound/usb/quirks.c +2 -0
index 5c3a97ea46e04..fb81dcd6ca2ac 100644
@@ -2285,6 +2285,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
 		   QUIRK_FLAG_PLAYBACK_FIRST | QUIRK_FLAG_GENERIC_IMPLICIT_FB),
 	DEVICE_FLG(0x13e5, 0x0001, /* Serato Phono */
 		   QUIRK_FLAG_IGNORE_CTL_ERROR),
+	DEVICE_FLG(0x152a, 0x880a, /* NeuralDSP Quad Cortex */
+		   0), /* Doesn't have the vendor quirk which would otherwise apply */
 	DEVICE_FLG(0x154e, 0x1002, /* Denon DCD-1500RE */
 		   QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
 	DEVICE_FLG(0x154e, 0x1003, /* Denon DA-300USB */
Signature · 1 line
2.53.0
author maintainer
#22 lore raw

PATCH 22/162 fs/smb/client: fix out-of-bounds read in cifs_sanitize_prepath

In reply to Greg Kroah-Hartman

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

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

From: Fredric Cover <[email protected]>

[ Upstream commit 78ec5bf2f589ec7fd8f169394bfeca541b077317 ]

When cifs_sanitize_prepath is called with an empty string or a string containing only delimiters (e.g., "/"), the current logic attempts to check *(cursor2 - 1) before cursor2 has advanced. This results in an out-of-bounds read.

This patch adds an early exit check after stripping prepended delimiters. If no path content remains, the function returns NULL.

The bug was identified via manual audit and verified using a standalone test case compiled with AddressSanitizer, which triggered a SEGV on affected inputs.

---
 fs/smb/client/fs_context.c | 4 ++++
 1 file changed, 4 insertions(+)
fs/smb/client/fs_context.c +4 -0
index 39e48e86b9b4f..769380020d41a 100644
@@ -527,6 +527,10 @@ char *cifs_sanitize_prepath(char *prepath, gfp_t gfp)
 	while (IS_DELIM(*cursor1))
 		cursor1++;
 
+	/* exit in case of only delimiters */
+	if (!*cursor1)
+		return NULL;
+
 	/* copy the first letter */
 	*cursor2 = *cursor1;
 
Signature · 1 line
2.53.0
author maintainer
#23 lore raw

PATCH 23/162 ASoC: amd: yc: Add DMI entry for HP Laptop 15-fc0xxx

In reply to Greg Kroah-Hartman

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

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

From: Gilson Marquato Júnior <[email protected]>

[ Upstream commit 8ec017cf31299c4b6287ebe27afe81c986aeef88 ]

The HP Laptop 15-fc0xxx (subsystem ID 0x103c8dc9) has an internal DMIC connected to the AMD ACP6x audio coprocessor. Add a DMI quirk entry so the internal microphone is properly detected on this model.

Tested on HP Laptop 15-fc0237ns with Fedora 43 (kernel 6.19.9).

---
 sound/soc/amd/yc/acp6x-mach.c | 7 +++++++
 1 file changed, 7 insertions(+)
sound/soc/amd/yc/acp6x-mach.c +7 -0
index 2414c1bba0789..6e41d14e5f3af 100644
@@ -45,6 +45,13 @@ static struct snd_soc_card acp6x_card = {
 };
 
 static const struct dmi_system_id yc_acp_quirk_table[] = {
+	{
+		.driver_data = &acp6x_card,
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "HP"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "HP Laptop 15-fc0xxx"),
+		}
+	},
 	{
 		.driver_data = &acp6x_card,
 		.matches = {
Signature · 1 line
2.53.0
author maintainer
#24 lore raw

PATCH 24/162 ALSA: hda/realtek: Add quirk for Lenovo Yoga Pro 7 14IMH9

In reply to Greg Kroah-Hartman

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

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

From: Alexander Savenko <[email protected]>

[ Upstream commit 217d5bc9f96272316ac5a3215c7cc32a5127bbf3 ]

The Lenovo Yoga Pro 7 14IMH9 (DMI: 83E2) shares PCI SSID 17aa:3847 with the Legion 7 16ACHG6, but has a different codec subsystem ID (17aa:38cf). The existing SND_PCI_QUIRK for 17aa:3847 applies ALC287_FIXUP_LEGION_16ACHG6, which attempts to initialize an external I2C amplifier (CLSA0100) that is not present on the Yoga Pro 7 14IMH9.

As a result, pin 0x17 (bass speakers) is connected to DAC 0x06 which has no volume control, making hardware volume adjustment completely non-functional. Audio is either silent or at maximum volume regardless of the slider position.

Add a HDA_CODEC_QUIRK entry using the codec subsystem ID (17aa:38cf) to correctly identify the Yoga Pro 7 14IMH9 and apply ALC287_FIXUP_YOGA9_14IMH9_BASS_SPK_PIN, which redirects pin 0x17 to DAC 0x02 and restores proper volume control. The existing Legion entry is preserved unchanged.

This follows the same pattern used for 17aa:386e, where Legion Y9000X and Yoga Pro 7 14ARP8 share a PCI SSID but are distinguished via HDA_CODEC_QUIRK.

---
 sound/pci/hda/patch_realtek.c | 4 ++++
 1 file changed, 4 insertions(+)
sound/pci/hda/patch_realtek.c +4 -0
index 04e10da997b53..b73c2741f8ae7 100644
@@ -11524,6 +11524,10 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x17aa, 0x3834, "Lenovo IdeaPad Slim 9i 14ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
 	SND_PCI_QUIRK(0x17aa, 0x383d, "Legion Y9000X 2019", ALC285_FIXUP_LEGION_Y9000X_SPEAKERS),
 	SND_PCI_QUIRK(0x17aa, 0x3843, "Lenovo Yoga 9i / Yoga Book 9i", ALC287_FIXUP_LENOVO_YOGA_BOOK_9I),
+	/* Yoga Pro 7 14IMH9 shares PCI SSID 17aa:3847 with Legion 7 16ACHG6;
+	 * use codec SSID to distinguish them
+	 */
+	HDA_CODEC_QUIRK(0x17aa, 0x38cf, "Lenovo Yoga Pro 7 14IMH9", ALC287_FIXUP_YOGA9_14IMH9_BASS_SPK_PIN),
 	SND_PCI_QUIRK(0x17aa, 0x3847, "Legion 7 16ACHG6", ALC287_FIXUP_LEGION_16ACHG6),
 	SND_PCI_QUIRK(0x17aa, 0x384a, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
 	SND_PCI_QUIRK(0x17aa, 0x3852, "Lenovo Yoga 7 14ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
Signature · 1 line
2.53.0
author maintainer
#25 lore raw

PATCH 25/162 pinctrl: intel: Fix the revision for new features (1kOhm PD, HW debouncer)

In reply to Greg Kroah-Hartman

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

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

From: Andy Shevchenko <[email protected]>

[ Upstream commit a4337a24d13e9e3b98a113e71d6b80dc5ed5f8c4 ]

The 1kOhm pull down and hardware debouncer are features of the revision 0.92 of the Chassis specification. Fix that in the code accordingly.

---
 drivers/pinctrl/intel/pinctrl-intel.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pinctrl/intel/pinctrl-intel.c +1 -1
index f8abc69a39d16..5d147a3a49389 100644
@@ -1588,7 +1588,7 @@ int intel_pinctrl_probe(struct platform_device *pdev,
 		value = readl(regs + REVID);
 		if (value == ~0u)
 			return -ENODEV;
-		if (((value & REVID_MASK) >> REVID_SHIFT) >= 0x94) {
+		if (((value & REVID_MASK) >> REVID_SHIFT) >= 0x92) {
 			community->features |= PINCTRL_FEATURE_DEBOUNCE;
 			community->features |= PINCTRL_FEATURE_1K_PD;
 		}
Signature · 1 line
2.53.0
author maintainer
#26 lore raw

PATCH 26/162 platform/x86/amd: pmc: Add Thinkpad L14 Gen3 to quirk_s2idle_bug

In reply to Greg Kroah-Hartman

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

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

From: Mario Limonciello <[email protected]>

[ Upstream commit 1a9452c428a6b76f0b797bae21daa454fccef1a2 ]

This platform is a similar vintage of platforms that had a BIOS bug leading to a 10s delay at resume from s0i3.

Add a quirk for it.

---
 drivers/platform/x86/amd/pmc/pmc-quirks.c | 9 +++++++++
 1 file changed, 9 insertions(+)
drivers/platform/x86/amd/pmc/pmc-quirks.c +9 -0
index a6006b4ec2cc0..a3921f8106c12 100644
@@ -197,6 +197,15 @@ static const struct dmi_system_id fwbug_list[] = {
 			DMI_MATCH(DMI_PRODUCT_NAME, "82XQ"),
 		}
 	},
+	/* https://bugzilla.kernel.org/show_bug.cgi?id=221273 */
+	{
+		.ident = "Thinkpad L14 Gen3",
+		.driver_data = &quirk_s2idle_bug,
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "21C6"),
+		}
+	},
 	/* https://gitlab.freedesktop.org/drm/amd/-/issues/4434 */
 	{
 		.ident = "Lenovo Yoga 6 13ALC6",
Signature · 1 line
2.53.0
author maintainer
#27 lore raw

PATCH 27/162 HID: quirks: add HID_QUIRK_ALWAYS_POLL for 8BitDo Pro 3

In reply to Greg Kroah-Hartman

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

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

From: leo vriska <[email protected]>

[ Upstream commit 532743944324a873bbaf8620fcabcd0e69e30c36 ]

According to a mailing list report [1], this controller's predecessor has the same issue. However, it uses the xpad driver instead of HID, so this quirk wouldn't apply.

[1]: https://lore.kernel.org/linux-input/[email protected]/

---
 drivers/hid/hid-ids.h    | 3 +++
 drivers/hid/hid-quirks.c | 1 +
 2 files changed, 4 insertions(+)
drivers/hid/hid-ids.h +3 -0
index 25eb5cc7de70e..475e6eb4702af 100644
@@ -22,6 +22,9 @@
 #define USB_DEVICE_ID_3M2256		0x0502
 #define USB_DEVICE_ID_3M3266		0x0506
 
+#define USB_VENDOR_ID_8BITDO		0x2dc8
+#define USB_DEVICE_ID_8BITDO_PRO_3	0x6009
+
 #define USB_VENDOR_ID_A4TECH		0x09da
 #define USB_DEVICE_ID_A4TECH_WCP32PU	0x0006
 #define USB_DEVICE_ID_A4TECH_X5_005D	0x000a
drivers/hid/hid-quirks.c +1 -0
index 7a3e0675d9ba2..d9e33dde89899 100644
@@ -25,6 +25,7 @@
  */
 
 static const struct hid_device_id hid_quirks[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_8BITDO, USB_DEVICE_ID_8BITDO_PRO_3), HID_QUIRK_ALWAYS_POLL },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_GAMEPAD), HID_QUIRK_BADPAD },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR), HID_QUIRK_BADPAD },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ADATA_XPG, USB_VENDOR_ID_ADATA_XPG_WL_GAMING_MOUSE), HID_QUIRK_ALWAYS_POLL },
Signature · 1 line
2.53.0
author maintainer
#28 lore raw

PATCH 28/162 ALSA: hda/realtek: Add quirk for Lenovo Yoga Pro 7 14IAH10

In reply to Greg Kroah-Hartman

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

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

From: songxiebing <[email protected]>

[ Upstream commit f0541edb2e7333f320642c7b491a67912c1f65db ]

The bass speakers are not working, and add the following entry in /etc/modprobe.d/snd.conf:
options snd-sof-intel-hda-generic hda_model=alc287-yoga9-bass-spk-pin Fixes the bass speakers.

So add the quick ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN here.

---
 sound/pci/hda/patch_realtek.c | 1 +
 1 file changed, 1 insertion(+)
sound/pci/hda/patch_realtek.c +1 -0
index b73c2741f8ae7..4cab9696fdab0 100644
@@ -11587,6 +11587,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x17aa, 0x38fd, "ThinkBook plus Gen5 Hybrid", ALC287_FIXUP_TAS2781_I2C),
 	SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
 	SND_PCI_QUIRK(0x17aa, 0x390d, "Lenovo Yoga Pro 7 14ASP10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
+	SND_PCI_QUIRK(0x17aa, 0x3911, "Lenovo Yoga Pro 7 14IAH10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
 	SND_PCI_QUIRK(0x17aa, 0x3913, "Lenovo 145", ALC236_FIXUP_LENOVO_INV_DMIC),
 	SND_PCI_QUIRK(0x17aa, 0x391f, "Yoga S990-16 pro Quad YC Quad", ALC287_FIXUP_TAS2781_I2C),
 	SND_PCI_QUIRK(0x17aa, 0x3920, "Yoga S990-16 pro Quad VECO Quad", ALC287_FIXUP_TAS2781_I2C),
Signature · 1 line
2.53.0
author maintainer
#29 lore raw

PATCH 29/162 HID: roccat: fix use-after-free in roccat_report_event

In reply to Greg Kroah-Hartman

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

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

From: Benoît Sevens <[email protected]>

[ Upstream commit d802d848308b35220f21a8025352f0c0aba15c12 ]

roccat_report_event() iterates over the device->readers list without holding the readers_lock. This allows a concurrent roccat_release() to remove and free a reader while it's still being accessed, leading to a use-after-free.

Protect the readers list traversal with the readers_lock mutex.

---
 drivers/hid/hid-roccat.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/hid/hid-roccat.c +2 -0
index c7f7562e22e56..e413662f75082 100644
@@ -257,6 +257,7 @@ int roccat_report_event(int minor, u8 const *data)
 	if (!new_value)
 		return -ENOMEM;
 
+	mutex_lock(&device->readers_lock);
 	mutex_lock(&device->cbuf_lock);
 
 	report = &device->cbuf[device->cbuf_end];
@@ -279,6 +280,7 @@ int roccat_report_event(int minor, u8 const *data)
 	}
 
 	mutex_unlock(&device->cbuf_lock);
+	mutex_unlock(&device->readers_lock);
 
 	wake_up_interruptible(&device->wait);
 	return 0;
Signature · 1 line
2.53.0
author maintainer
#30 lore raw

PATCH 30/162 ata: ahci: force 32-bit DMA for JMicron JMB582/JMB585

In reply to Greg Kroah-Hartman

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

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

From: Arthur Husband <[email protected]>

[ Upstream commit 105c42566a550e2d05fc14f763216a8765ee5d0e ]

The JMicron JMB585 (and JMB582) SATA controllers advertise 64-bit DMA support via the S64A bit in the AHCI CAP register, but their 64-bit DMA implementation is defective. Under sustained I/O, DMA transfers targeting addresses above 4GB silently corrupt data -- writes land at incorrect memory addresses with no errors logged.

The failure pattern is similar to the ASMedia ASM1061 (commit 20730e9b2778 ("ahci: add 43-bit DMA address quirk for ASMedia ASM1061 controllers")), which also falsely advertised full 64-bit DMA support. However, the JMB585 requires a stricter 32-bit DMA mask rather than 43-bit, as corruption occurs with any address above 4GB.

On the Minisforum N5 Pro specifically, the combination of the JMB585's broken 64-bit DMA with the AMD Family 1Ah (Strix Point) IOMMU causes silent data corruption that is only detectable via checksumming filesystems (BTRFS/ZFS scrub). The corruption occurs when 32-bit IOVA space is exhausted and the kernel transparently switches to 64-bit DMA addresses.

Add device-specific PCI ID entries for the JMB582 (0x0582) and JMB585 (0x0585) before the generic JMicron class match, using a new board type that combines AHCI_HFLAG_IGN_IRQ_IF_ERR (preserving existing behavior) with AHCI_HFLAG_32BIT_ONLY to force 32-bit DMA masks.

---
 drivers/ata/ahci.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)
drivers/ata/ahci.c +14 -0
index e78b97fe81708..57a7a2b68aaab 100644
@@ -68,6 +68,7 @@ enum board_ids {
 	/* board IDs for specific chipsets in alphabetical order */
 	board_ahci_al,
 	board_ahci_avn,
+	board_ahci_jmb585,
 	board_ahci_mcp65,
 	board_ahci_mcp77,
 	board_ahci_mcp89,
@@ -212,6 +213,15 @@ static const struct ata_port_info ahci_port_info[] = {
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_avn_ops,
 	},
+	/* JMicron JMB582/585: 64-bit DMA is broken, force 32-bit */
+	[board_ahci_jmb585] = {
+		AHCI_HFLAGS	(AHCI_HFLAG_IGN_IRQ_IF_ERR |
+				 AHCI_HFLAG_32BIT_ONLY),
+		.flags		= AHCI_FLAG_COMMON,
+		.pio_mask	= ATA_PIO4,
+		.udma_mask	= ATA_UDMA6,
+		.port_ops	= &ahci_ops,
+	},
 	[board_ahci_mcp65] = {
 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP |
 				 AHCI_HFLAG_YES_NCQ),
@@ -439,6 +449,10 @@ static const struct pci_device_id ahci_pci_tbl[] = {
 	/* Elkhart Lake IDs 0x4b60 & 0x4b62 https://sata-io.org/product/8803 not tested yet */
 	{ PCI_VDEVICE(INTEL, 0x4b63), board_ahci_pcs_quirk }, /* Elkhart Lake AHCI */
 
+	/* JMicron JMB582/585: force 32-bit DMA (broken 64-bit implementation) */
+	{ PCI_VDEVICE(JMICRON, 0x0582), board_ahci_jmb585 },
+	{ PCI_VDEVICE(JMICRON, 0x0585), board_ahci_jmb585 },
+
 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },
Signature · 1 line
2.53.0
author maintainer
#31 lore raw

PATCH 31/162 wifi: brcmfmac: validate bsscfg indices in IF events

In reply to Greg Kroah-Hartman

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

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

From: Pengpeng Hou <[email protected]>

[ Upstream commit 304950a467d83678bd0b0f46331882e2ac23b12d ]

brcmf_fweh_handle_if_event() validates the firmware-provided interface index before it touches drvr->iflist[], but it still uses the raw bsscfgidx field as an array index without a matching range check.

Reject IF events whose bsscfg index does not fit in drvr->iflist[] before indexing the interface array.

---
 drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c | 5 +++++
 1 file changed, 5 insertions(+)
drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c +5 -0
index f0b6a7607f160..0e44615964669 100644
@@ -152,6 +152,11 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
 		bphy_err(drvr, "invalid interface index: %u\n", ifevent->ifidx);
 		return;
 	}
+	if (ifevent->bsscfgidx >= BRCMF_MAX_IFS) {
+		bphy_err(drvr, "invalid bsscfg index: %u\n",
+			 ifevent->bsscfgidx);
+		return;
+	}
 
 	ifp = drvr->iflist[ifevent->bsscfgidx];
 
Signature · 1 line
2.53.0
author maintainer
#32 lore raw

PATCH 32/162 net: sfp: add quirks for Hisense and HSGQ GPON ONT SFP modules

In reply to Greg Kroah-Hartman

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

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

From: John Pavlick <[email protected]>

[ Upstream commit 95aca8602ef70ffd3d971675751c81826e124f90 ]

Several GPON ONT SFP sticks based on Realtek RTL960x report 1000BASE-LX at 1300MBd in their EEPROM but can operate at 2500base-X. On hosts capable of 2500base-X (e.g. Banana Pi R3 / MT7986), the kernel negotiates only 1G because it trusts the incorrect EEPROM data.

Add quirks for:
- Hisense-Leox LXT-010S-H
- Hisense ZNID-GPON-2311NA
- HSGQ HSGQ-XPON-Stick

Each quirk advertises 2500base-X and ignores TX_FAULT during the module's ~40s Linux boot time.

Tested on Banana Pi R3 (MT7986) with OpenWrt 25.12.1, confirmed 2.5Gbps link and full throughput with flow offloading.

---
 drivers/net/phy/sfp.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
drivers/net/phy/sfp.c +16 -0
index 9d9c1779da900..90ffba8f79520 100644
@@ -536,6 +536,22 @@ static const struct sfp_quirk sfp_quirks[] = {
 	SFP_QUIRK("HUAWEI", "MA5671A", sfp_quirk_2500basex,
 		  sfp_fixup_ignore_tx_fault_and_los),
 
+	// Hisense LXT-010S-H is a GPON ONT SFP (sold as LEOX LXT-010S-H) that
+	// can operate at 2500base-X, but reports 1000BASE-LX / 1300MBd in its
+	// EEPROM
+	SFP_QUIRK("Hisense-Leox", "LXT-010S-H", sfp_quirk_2500basex,
+		  sfp_fixup_ignore_tx_fault),
+
+	// Hisense ZNID-GPON-2311NA can operate at 2500base-X, but reports
+	// 1000BASE-LX / 1300MBd in its EEPROM
+	SFP_QUIRK("Hisense", "ZNID-GPON-2311NA", sfp_quirk_2500basex,
+		  sfp_fixup_ignore_tx_fault),
+
+	// HSGQ HSGQ-XPON-Stick can operate at 2500base-X, but reports
+	// 1000BASE-LX / 1300MBd in its EEPROM
+	SFP_QUIRK("HSGQ", "HSGQ-XPON-Stick", sfp_quirk_2500basex,
+		  sfp_fixup_ignore_tx_fault),
+
 	// Lantech 8330-262D-E and 8330-265D can operate at 2500base-X, but
 	// incorrectly report 2500MBd NRZ in their EEPROM.
 	// Some 8330-265D modules have inverted LOS, while all of them report
Signature · 1 line
2.53.0
author maintainer
#33 lore raw

PATCH 33/162 ASoC: stm32_sai: fix incorrect BCLK polarity for DSP_A/B, LEFT_J

In reply to Greg Kroah-Hartman

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

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

From: Tomasz Merta <[email protected]>

[ Upstream commit 0669631dbccd41cf3ca7aa70213fcd8bb41c4b38 ]

The STM32 SAI driver do not set the clock strobing bit (CKSTR) for DSP_A, DSP_B and LEFT_J formats, causing data to be sampled on the wrong BCLK edge when SND_SOC_DAIFMT_NB_NF is used.

Per ALSA convention, NB_NF requires sampling on the rising BCLK edge. The STM32MP25 SAI reference manual states that CKSTR=1 is required for signals received by the SAI to be sampled on the SCK rising edge. Without setting CKSTR=1, the SAI samples on the falling edge, violating the NB_NF convention. For comparison, the NXP FSL SAI driver correctly sets FSL_SAI_CR2_BCP for DSP_A, DSP_B and LEFT_J, consistent with its I2S handling.

This patch adds SAI_XCR1_CKSTR for DSP_A, DSP_B and LEFT_J in stm32_sai_set_dai_fmt which was verified empirically with a cs47l35 codec. RIGHT_J (LSB) is not investigated and addressed by this patch.

Note: the STM32 I2S driver (stm32_i2s_set_dai_fmt) may have the same issue for DSP_A mode, as I2S_CGFR_CKPOL is not set. This has not been verified and is left for a separate investigation.

---
 sound/soc/stm/stm32_sai_sub.c | 3 +++
 1 file changed, 3 insertions(+)
sound/soc/stm/stm32_sai_sub.c +3 -0
index fb1bd9844b550..f4f751b19429a 100644
@@ -677,6 +677,7 @@ static int stm32_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
 		break;
 	/* Left justified */
 	case SND_SOC_DAIFMT_MSB:
+		cr1 |= SAI_XCR1_CKSTR;
 		frcr |= SAI_XFRCR_FSPOL | SAI_XFRCR_FSDEF;
 		break;
 	/* Right justified */
@@ -684,9 +685,11 @@ static int stm32_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
 		frcr |= SAI_XFRCR_FSPOL | SAI_XFRCR_FSDEF;
 		break;
 	case SND_SOC_DAIFMT_DSP_A:
+		cr1 |= SAI_XCR1_CKSTR;
 		frcr |= SAI_XFRCR_FSPOL | SAI_XFRCR_FSOFF;
 		break;
 	case SND_SOC_DAIFMT_DSP_B:
+		cr1 |= SAI_XCR1_CKSTR;
 		frcr |= SAI_XFRCR_FSPOL;
 		break;
 	default:
Signature · 1 line
2.53.0
author maintainer
#34 lore raw

PATCH 34/162 soc: aspeed: socinfo: Mask table entries for accurate SoC ID matching

In reply to Greg Kroah-Hartman

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

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

From: Potin Lai <[email protected]>

[ Upstream commit 7ec1bd3d9be671d04325b9e06149b8813f6a4836 ]

The siliconid_to_name() function currently masks the input silicon ID with 0xff00ffff, but compares it against unmasked table entries. This causes matching to fail if the table entries contain non-zero values in the bits covered by the mask (bits 16-23).

Update the logic to apply the 0xff00ffff mask to the table entries during comparison. This ensures that only the relevant model and revision bits are considered, providing a consistent match across different manufacturing batches.

[arj: Add Fixes: tag, fix 'soninfo' typo, clarify function reference]

Fixes e0218dca5787 ("soc: aspeed: Add soc info driver")
---
 drivers/soc/aspeed/aspeed-socinfo.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/soc/aspeed/aspeed-socinfo.c +1 -1
index 67e9ac3d08ecc..a90b100f4d101 100644
@@ -39,7 +39,7 @@ static const char *siliconid_to_name(u32 siliconid)
 	unsigned int i;
 
 	for (i = 0 ; i < ARRAY_SIZE(rev_table) ; ++i) {
-		if (rev_table[i].id == id)
+		if ((rev_table[i].id & 0xff00ffff) == id)
 			return rev_table[i].name;
 	}
 
Signature · 1 line
2.53.0
author maintainer
#35 lore raw

PATCH 35/162 arm64: dts: qcom: hamoa/x1: fix idle exit latency

In reply to Greg Kroah-Hartman

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

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

From: Daniel J Blueman <[email protected]>

[ Upstream commit 3ecea84d2b90bbf934d5ca75514fa902fd71e03f ]

Designs based on the Qualcomm X1 Hamoa reference platform report:
driver: Idle state 1 target residency too low

This is because the declared X1 idle entry plus exit latency of 680us exceeds the declared minimum 600us residency time:
entry-latency-us = <180>;
exit-latency-us = <500>;
min-residency-us = <600>;

Fix this to be 320us so the sum of the entry and exit latencies matches the downstream 500us exit latency, as directed by Maulik.

Tested on a Lenovo Yoga Slim 7x with Qualcomm X1E-80-100.

Fixes 2e65616ef07f ("arm64: dts: qcom: x1e80100: Update C4/C5 residency/exit numbers")
---
 arch/arm64/boot/dts/qcom/x1e80100.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/boot/dts/qcom/x1e80100.dtsi +1 -1
index 6eef89ccdd121..8843dac449000 100644
@@ -280,7 +280,7 @@ CLUSTER_C4: cpu-sleep-0 {
 				idle-state-name = "ret";
 				arm,psci-suspend-param = <0x00000004>;
 				entry-latency-us = <180>;
-				exit-latency-us = <500>;
+				exit-latency-us = <320>;
 				min-residency-us = <600>;
 			};
 		};
Signature · 1 line
2.53.0
author maintainer
#36 lore raw

PATCH 36/162 arm64: dts: imx8mq: Set the correct gpu_ahb clock frequency

In reply to Greg Kroah-Hartman

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

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

From: Sebastian Krzyszkowiak <[email protected]>

[ Upstream commit 1f99b5d93d99ca17d50b386a674d0ce1f20932d8 ]

According to i.MX 8M Quad Reference Manual, GPU_AHB_CLK_ROOT's maximum frequency is 400MHz.

Fixes 45d2c84eb3a2 ("arm64: dts: imx8mq: add GPU node")
---
 arch/arm64/boot/dts/freescale/imx8mq.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/boot/dts/freescale/imx8mq.dtsi +1 -1
index e03186bbc4152..c4395de0df762 100644
@@ -1636,7 +1636,7 @@ gpu: gpu@38000000 {
 			                         <&clk IMX8MQ_GPU_PLL_OUT>,
 			                         <&clk IMX8MQ_GPU_PLL>;
 			assigned-clock-rates = <800000000>, <800000000>,
-			                       <800000000>, <800000000>, <0>;
+			                       <800000000>, <400000000>, <0>;
 			power-domains = <&pgc_gpu>;
 		};
 
Signature · 1 line
2.53.0
author maintainer
#37 lore raw

PATCH 37/162 arm64: dts: imx93-9x9-qsb: change usdhc tuning step for eMMC and SD

In reply to Greg Kroah-Hartman

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

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

From: Luke Wang <[email protected]>

[ Upstream commit 08903184553def7ba1ad6ba4fa8afe1ba2ee0a21 ]

During system resume, the following errors occurred:

  [  430.638625] mmc1: error -84 writing Cache Enable bit
  [  430.643618] mmc1: error -84 doing runtime resume

For eMMC and SD, there are two tuning pass windows and the gap between those two windows may only have one cell. If tuning step > 1, the gap may just be skipped and host assumes those two windows as a continuous windows. This will cause a wrong delay cell near the gap to be selected.

Set the tuning step to 1 to avoid selecting the wrong delay cell.

For SDIO, the gap is sufficiently large, so the default tuning step does not cause this issue.

Fixes 0565d20cd8c2 ("arm64: dts: freescale: Support i.MX93 9x9 Quick Start Board")
---
 arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts | 2 ++
 1 file changed, 2 insertions(+)
arch/arm64/boot/dts/freescale/imx93-9x9-qsb.dts +2 -0
index f8a73612fa051..8856835834a04 100644
@@ -311,6 +311,7 @@ &usdhc1 {
 	pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
 	bus-width = <8>;
 	non-removable;
+	fsl,tuning-step = <1>;
 	status = "okay";
 };
 
@@ -323,6 +324,7 @@ &usdhc2 {
 	vmmc-supply = <&reg_usdhc2_vmmc>;
 	bus-width = <4>;
 	no-mmc;
+	fsl,tuning-step = <1>;
 	status = "okay";
 };
 
Signature · 1 line
2.53.0
author maintainer
#38 lore raw

PATCH 38/162 arm64: dts: imx93-tqma9352: improve eMMC pad configuration

In reply to Greg Kroah-Hartman

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

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

From: Markus Niebel <[email protected]>

[ Upstream commit b6c94c71f349479b76fcc0ef0dc7147f3f326dff ]

Use DSE x4 an PullUp for CMD an DAT, DSE x4 and PullDown for CLK to improve stability and detection at low temperatures under -25°C.

Fixes 0b5fdfaa8e45 ("arm64: dts: freescale: imx93-tqma9352: set SION for cmd and data pad of USDHC")
---
 .../boot/dts/freescale/imx93-tqma9352.dtsi    | 26 +++++++++----------
 1 file changed, 13 insertions(+), 13 deletions(-)
arch/arm64/boot/dts/freescale/imx93-tqma9352.dtsi +13 -13
index 09385b058664c..f189685370cc8 100644
@@ -273,21 +273,21 @@ MX93_PAD_SD2_RESET_B__GPIO3_IO07	0x106
 	/* enable SION for data and cmd pad due to ERR052021 */
 	pinctrl_usdhc1: usdhc1grp {
 		fsl,pins = <
-			/* PD | FSEL 3 | DSE X5 */
-			MX93_PAD_SD1_CLK__USDHC1_CLK		0x5be
+			/* PD | FSEL 3 | DSE X4 */
+			MX93_PAD_SD1_CLK__USDHC1_CLK		0x59e
 			/* HYS | FSEL 0 | no drive */
 			MX93_PAD_SD1_STROBE__USDHC1_STROBE	0x1000
-			/* HYS | FSEL 3 | X5 */
-			MX93_PAD_SD1_CMD__USDHC1_CMD		0x400011be
-			/* HYS | FSEL 3 | X4 */
-			MX93_PAD_SD1_DATA0__USDHC1_DATA0	0x4000119e
-			MX93_PAD_SD1_DATA1__USDHC1_DATA1	0x4000119e
-			MX93_PAD_SD1_DATA2__USDHC1_DATA2	0x4000119e
-			MX93_PAD_SD1_DATA3__USDHC1_DATA3	0x4000119e
-			MX93_PAD_SD1_DATA4__USDHC1_DATA4	0x4000119e
-			MX93_PAD_SD1_DATA5__USDHC1_DATA5	0x4000119e
-			MX93_PAD_SD1_DATA6__USDHC1_DATA6	0x4000119e
-			MX93_PAD_SD1_DATA7__USDHC1_DATA7	0x4000119e
+			/* HYS | PU | FSEL 3 | DSE X4 */
+			MX93_PAD_SD1_CMD__USDHC1_CMD		0x4000139e
+			/* HYS | PU | FSEL 3 | DSE X4 */
+			MX93_PAD_SD1_DATA0__USDHC1_DATA0	0x4000139e
+			MX93_PAD_SD1_DATA1__USDHC1_DATA1	0x4000139e
+			MX93_PAD_SD1_DATA2__USDHC1_DATA2	0x4000139e
+			MX93_PAD_SD1_DATA3__USDHC1_DATA3	0x4000139e
+			MX93_PAD_SD1_DATA4__USDHC1_DATA4	0x4000139e
+			MX93_PAD_SD1_DATA5__USDHC1_DATA5	0x4000139e
+			MX93_PAD_SD1_DATA6__USDHC1_DATA6	0x4000139e
+			MX93_PAD_SD1_DATA7__USDHC1_DATA7	0x4000139e
 		>;
 	};
 
Signature · 1 line
2.53.0
author maintainer
#39 lore raw

PATCH 39/162 soc: qcom: pd-mapper: Fix element length in servreg_loc_pfr_req_ei

In reply to Greg Kroah-Hartman

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

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

From: Mukesh Ojha <[email protected]>

[ Upstream commit 641f6fda143b879da1515f821ee475073678cf2a ]

It looks element length declared in servreg_loc_pfr_req_ei for reason not matching servreg_loc_pfr_req's reason field due which we could observe decoding error on PD crash.

qmi_decode_string_elem: String len 81 >= Max Len 65

Fix this by matching with servreg_loc_pfr_req's reason field.

---
 drivers/soc/qcom/pdr_internal.h | 2 +-
 drivers/soc/qcom/qcom_pdr_msg.c | 2 +-
 include/linux/soc/qcom/pdr.h    | 1 +
 3 files changed, 3 insertions(+), 2 deletions(-)
drivers/soc/qcom/pdr_internal.h +1 -1
index 8d17f7fb79e78..f5499663e5887 100644
@@ -84,7 +84,7 @@ struct servreg_set_ack_resp {
 
 struct servreg_loc_pfr_req {
 	char service[SERVREG_NAME_LENGTH + 1];
-	char reason[257];
+	char reason[SERVREG_PFR_LENGTH + 1];
 };
 
 struct servreg_loc_pfr_resp {
drivers/soc/qcom/qcom_pdr_msg.c +1 -1
index bf3e4a47165e3..6e65f1e9f5ec9 100644
@@ -326,7 +326,7 @@ const struct qmi_elem_info servreg_loc_pfr_req_ei[] = {
 	},
 	{
 		.data_type = QMI_STRING,
-		.elem_len = SERVREG_NAME_LENGTH + 1,
+		.elem_len = SERVREG_PFR_LENGTH + 1,
 		.elem_size = sizeof(char),
 		.array_type = VAR_LEN_ARRAY,
 		.tlv_type = 0x02,
include/linux/soc/qcom/pdr.h +1 -0
index 83a8ea612e69a..2b7691e47c2a9 100644
@@ -5,6 +5,7 @@
 #include <linux/soc/qcom/qmi.h>
 
 #define SERVREG_NAME_LENGTH	64
+#define SERVREG_PFR_LENGTH	256
 
 struct pdr_service;
 struct pdr_handle;
Signature · 1 line
2.53.0
author maintainer
#40 lore raw

PATCH 40/162 tools/power/turbostat: Fix microcode patch level output for AMD/Hygon

In reply to Greg Kroah-Hartman

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

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

From: Serhii Pievniev <[email protected]>

[ Upstream commit a444083286434ec1fd127c5da11a3091e6013008 ]

turbostat always used the same logic to read the microcode patch level, which is correct for Intel but not for AMD/Hygon.
While Intel stores the patch level in the upper 32 bits of MSR, AMD stores it in the lower 32 bits, which causes turbostat to report the microcode version as 0x0 on AMD/Hygon.

Fix by shifting right by 32 for non-AMD/Hygon, preserving the existing behavior for Intel and unknown vendors.

Fixes 3e4048466c39 ("tools/power turbostat: Add --no-msr option")
---
 tools/power/x86/turbostat/turbostat.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
tools/power/x86/turbostat/turbostat.c +6 -3
index 86ffe7e06a146..fb1c65f6ff9de 100644
@@ -8058,10 +8058,13 @@ void process_cpuid()
 	edx_flags = edx;
 
 	if (!no_msr) {
-		if (get_msr(sched_getcpu(), MSR_IA32_UCODE_REV, &ucode_patch))
+		if (get_msr(sched_getcpu(), MSR_IA32_UCODE_REV, &ucode_patch)) {
 			warnx("get_msr(UCODE)");
-		else
+		} else {
 			ucode_patch_valid = true;
+			if (!authentic_amd && !hygon_genuine)
+				ucode_patch >>= 32;
+		}
 	}
 
 	/*
@@ -8076,7 +8079,7 @@ void process_cpuid()
 		fprintf(outf, "CPUID(1): family:model:stepping 0x%x:%x:%x (%d:%d:%d)",
 			family, model, stepping, family, model, stepping);
 		if (ucode_patch_valid)
-			fprintf(outf, " microcode 0x%x", (unsigned int)((ucode_patch >> 32) & 0xFFFFFFFF));
+			fprintf(outf, " microcode 0x%x", (unsigned int)ucode_patch);
 		fputc('\n', outf);
 
 		fprintf(outf, "CPUID(0x80000000): max_extended_levels: 0x%x\n", max_extended_level);
Signature · 1 line
2.53.0
author maintainer
#41 lore raw

PATCH 41/162 PCI: hv: Set default NUMA node to 0 for devices without affinity info

In reply to Greg Kroah-Hartman

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

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

From: Long Li <[email protected]>

[ Upstream commit 7b3b1e5a87b2f5e35c52b5386d7c327be869454f ]

When hv_pci_assign_numa_node() processes a device that does not have HV_PCI_DEVICE_FLAG_NUMA_AFFINITY set or has an out-of-range virtual_numa_node, the device NUMA node is left unset. On x86_64, the uninitialized default happens to be 0, but on ARM64 it is NUMA_NO_NODE (-1).

Tests show that when no NUMA information is available from the Hyper-V host, devices perform best when assigned to node 0. With NUMA_NO_NODE the kernel may spread work across NUMA nodes, which degrades performance on Hyper-V, particularly for high-throughput devices like MANA.

Always set the device NUMA node to 0 before the conditional NUMA affinity check, so that devices get a performant default when the host provides no NUMA information, and behavior is consistent on both x86_64 and ARM64.

Fixes 999dd956d838 ("PCI: hv: Add support for protocol 1.3 and support PCI_BUS_RELATIONS2")
---
 drivers/pci/controller/pci-hyperv.c | 8 ++++++++
 1 file changed, 8 insertions(+)
drivers/pci/controller/pci-hyperv.c +8 -0
index cdd5be16021dd..e87e54acff4b0 100644
@@ -2364,6 +2364,14 @@ static void hv_pci_assign_numa_node(struct hv_pcibus_device *hbus)
 		if (!hv_dev)
 			continue;
 
+		/*
+		 * If the Hyper-V host doesn't provide a NUMA node for the
+		 * device, default to node 0. With NUMA_NO_NODE the kernel
+		 * may spread work across NUMA nodes, which degrades
+		 * performance on Hyper-V.
+		 */
+		set_dev_node(&dev->dev, 0);
+
 		if (hv_dev->desc.flags & HV_PCI_DEVICE_FLAG_NUMA_AFFINITY &&
 		    hv_dev->desc.virtual_numa_node < num_possible_nodes())
 			/*
Signature · 1 line
2.53.0
author maintainer
#42 lore raw

PATCH 42/162 HID: amd_sfh: dont log error when device discovery fails with -EOPNOTSUPP

In reply to Greg Kroah-Hartman

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

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

From: Maximilian Pezzullo <[email protected]>

[ Upstream commit 743677a8cb30b09f16a7f167f497c2c927891b5a ]

When sensor discovery fails on systems without AMD SFH sensors, the code already emits a warning via dev_warn() in amd_sfh_hid_client_init(). The subsequent dev_err() in sfh_init_work() for the same -EOPNOTSUPP return value is redundant and causes unnecessary alarm.

Suppress the dev_err() for -EOPNOTSUPP to avoid confusing users who have no AMD SFH sensors.

---
 drivers/hid/amd-sfh-hid/amd_sfh_pcie.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/hid/amd-sfh-hid/amd_sfh_pcie.c +2 -1
index 9739f66e925c0..33ba9af1a249f 100644
@@ -352,7 +352,8 @@ static void sfh_init_work(struct work_struct *work)
 	rc = amd_sfh_hid_client_init(mp2);
 	if (rc) {
 		amd_sfh_clear_intr(mp2);
-		dev_err(&pdev->dev, "amd_sfh_hid_client_init failed err %d\n", rc);
+		if (rc != -EOPNOTSUPP)
+			dev_err(&pdev->dev, "amd_sfh_hid_client_init failed err %d\n", rc);
 		return;
 	}
 
Signature · 1 line
2.53.0
author maintainer
#43 lore raw

PATCH 43/162 xfrm: account XFRMA_IF_ID in aevent size calculation

In reply to Greg Kroah-Hartman

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

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

From: Keenan Dong <[email protected]>

[ Upstream commit 7081d46d32312f1a31f0e0e99c6835a394037599 ]

xfrm_get_ae() allocates the reply skb with xfrm_aevent_msgsize(), then build_aevent() appends attributes including XFRMA_IF_ID when x->if_id is set.

xfrm_aevent_msgsize() does not include space for XFRMA_IF_ID. For states with if_id, build_aevent() can fail with -EMSGSIZE and hit BUG_ON(err < 0) in xfrm_get_ae(), turning a malformed netlink interaction into a kernel panic.

Account XFRMA_IF_ID in the size calculation unconditionally and replace the BUG_ON with normal error unwinding.

Fixes 7e6526404ade ("xfrm: Add a new lookup key to match xfrm interfaces.")
---
 net/xfrm/xfrm_user.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)
net/xfrm/xfrm_user.c +8 -2
index 6aed7ae900130..9516655e92f19 100644
@@ -2601,7 +2601,8 @@ static inline unsigned int xfrm_aevent_msgsize(struct xfrm_state *x)
 	       + nla_total_size(4) /* XFRM_AE_RTHR */
 	       + nla_total_size(4) /* XFRM_AE_ETHR */
 	       + nla_total_size(sizeof(x->dir)) /* XFRMA_SA_DIR */
-	       + nla_total_size(4); /* XFRMA_SA_PCPU */
+	       + nla_total_size(4) /* XFRMA_SA_PCPU */
+	       + nla_total_size(sizeof(x->if_id)); /* XFRMA_IF_ID */
 }
 
 static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, const struct km_event *c)
@@ -2713,7 +2714,12 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
 	c.portid = nlh->nlmsg_pid;
 
 	err = build_aevent(r_skb, x, &c);
-	BUG_ON(err < 0);
+	if (err < 0) {
+		spin_unlock_bh(&x->lock);
+		xfrm_state_put(x);
+		kfree_skb(r_skb);
+		return err;
+	}
 
 	err = nlmsg_unicast(net->xfrm.nlsk, r_skb, NETLINK_CB(skb).portid);
 	spin_unlock_bh(&x->lock);
Signature · 1 line
2.53.0
author maintainer
#44 lore raw

PATCH 44/162 drm/vc4: Release runtime PM reference after binding V3D

In reply to Greg Kroah-Hartman

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

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

From: Maíra Canal <[email protected]>

[ Upstream commit aaefbdde9abdc43699e110679c0e10972a5e1c59 ]

The vc4_v3d_bind() function acquires a runtime PM reference via pm_runtime_resume_and_get() to access V3D registers during setup. However, this reference is never released after a successful bind. This prevents the device from ever runtime suspending, since the reference count never reaches zero.

Release the runtime PM reference by adding pm_runtime_put_autosuspend() after autosuspend is configured, allowing the device to runtime suspend after the delay.

Fixes 266cff37d7fc ("drm/vc4: v3d: Rework the runtime_pm setup")
---
 drivers/gpu/drm/vc4/vc4_v3d.c | 1 +
 1 file changed, 1 insertion(+)
drivers/gpu/drm/vc4/vc4_v3d.c +1 -0
index 43f69d74e8761..334d2cfe3433b 100644
@@ -479,6 +479,7 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)
 
 	pm_runtime_use_autosuspend(dev);
 	pm_runtime_set_autosuspend_delay(dev, 40); /* a little over 2 frames. */
+	pm_runtime_put_autosuspend(dev);
 
 	return 0;
 
Signature · 1 line
2.53.0
author maintainer
#45 lore raw

PATCH 45/162 drm/vc4: Fix memory leak of BO array in hang state

In reply to Greg Kroah-Hartman

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

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

From: Maíra Canal <[email protected]>

[ Upstream commit f4dfd6847b3e5d24e336bca6057485116d17aea4 ]

The hang state's BO array is allocated separately with kzalloc() in vc4_save_hang_state() but never freed in vc4_free_hang_state(). Add the missing kfree() for the BO array before freeing the hang state struct.

Fixes 214613656b51 ("drm/vc4: Add an interface for capturing the GPU state after a hang.")
---
 drivers/gpu/drm/vc4/vc4_gem.c | 1 +
 1 file changed, 1 insertion(+)
drivers/gpu/drm/vc4/vc4_gem.c +1 -0
index be9c0b72ebe86..373d310c7b6a5 100644
@@ -60,6 +60,7 @@ vc4_free_hang_state(struct drm_device *dev, struct vc4_hang_state *state)
 	for (i = 0; i < state->user_state.bo_count; i++)
 		drm_gem_object_put(state->bo[i]);
 
+	kfree(state->bo);
 	kfree(state);
 }
 
Signature · 1 line
2.53.0
author maintainer
#46 lore raw

PATCH 46/162 drm/vc4: Fix a memory leak in hang state error path

In reply to Greg Kroah-Hartman

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

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

From: Maíra Canal <[email protected]>

[ Upstream commit 9525d169e5fd481538cf8c663cc5839e54f2e481 ]

When vc4_save_hang_state() encounters an early return condition, it returns without freeing the previously allocated kernel_state, leaking memory.

Add the missing kfree() calls by consolidating the early return paths into a single place.

Fixes 214613656b51 ("drm/vc4: Add an interface for capturing the GPU state after a hang.")
---
 drivers/gpu/drm/vc4/vc4_gem.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)
drivers/gpu/drm/vc4/vc4_gem.c +10 -8
index 373d310c7b6a5..62d19601ef356 100644
@@ -169,10 +169,8 @@ vc4_save_hang_state(struct drm_device *dev)
 	spin_lock_irqsave(&vc4->job_lock, irqflags);
 	exec[0] = vc4_first_bin_job(vc4);
 	exec[1] = vc4_first_render_job(vc4);
-	if (!exec[0] && !exec[1]) {
-		spin_unlock_irqrestore(&vc4->job_lock, irqflags);
-		return;
-	}
+	if (!exec[0] && !exec[1])
+		goto err_free_state;
 
 	/* Get the bos from both binner and renderer into hang state. */
 	state->bo_count = 0;
@@ -189,10 +187,8 @@ vc4_save_hang_state(struct drm_device *dev)
 	kernel_state->bo = kcalloc(state->bo_count,
 				   sizeof(*kernel_state->bo), GFP_ATOMIC);
 
-	if (!kernel_state->bo) {
-		spin_unlock_irqrestore(&vc4->job_lock, irqflags);
-		return;
-	}
+	if (!kernel_state->bo)
+		goto err_free_state;
 
 	k = 0;
 	for (i = 0; i < 2; i++) {
@@ -284,6 +280,12 @@ vc4_save_hang_state(struct drm_device *dev)
 		vc4->hang_state = kernel_state;
 		spin_unlock_irqrestore(&vc4->job_lock, irqflags);
 	}
+
+	return;
+
+err_free_state:
+	spin_unlock_irqrestore(&vc4->job_lock, irqflags);
+	kfree(kernel_state);
 }
 
 static void
Signature · 1 line
2.53.0
author maintainer
#47 lore raw

PATCH 47/162 drm/vc4: Protect madv read in vc4_gem_object_mmap() with madv_lock

In reply to Greg Kroah-Hartman

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

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

From: Maíra Canal <[email protected]>

[ Upstream commit 338c56050d8e892604da97f67bfa8cc4015a955f ]

The mmap callback reads bo->madv without holding madv_lock, racing with concurrent DRM_IOCTL_VC4_GEM_MADVISE calls that modify the field under the same lock. Add the missing locking to prevent the data race.

Fixes b9f19259b84d ("drm/vc4: Add the DRM_IOCTL_VC4_GEM_MADVISE ioctl")
---
 drivers/gpu/drm/vc4/vc4_bo.c | 3 +++
 1 file changed, 3 insertions(+)
drivers/gpu/drm/vc4/vc4_bo.c +3 -0
index 2a85d08b19852..3740e0552960d 100644
@@ -738,12 +738,15 @@ static int vc4_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct
 		return -EINVAL;
 	}
 
+	mutex_lock(&bo->madv_lock);
 	if (bo->madv != VC4_MADV_WILLNEED) {
 		DRM_DEBUG("mmapping of %s BO not allowed\n",
 			  bo->madv == VC4_MADV_DONTNEED ?
 			  "purgeable" : "purged");
+		mutex_unlock(&bo->madv_lock);
 		return -EINVAL;
 	}
+	mutex_unlock(&bo->madv_lock);
 
 	return drm_gem_dma_mmap(&bo->base, vma);
 }
Signature · 1 line
2.53.0
author maintainer
#48 lore raw

PATCH 48/162 eventpoll: defer struct eventpoll free to RCU grace period

In reply to Greg Kroah-Hartman

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

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

From: Nicholas Carlini <[email protected]>

[ Upstream commit 07712db80857d5d09ae08f3df85a708ecfc3b61f ]

In certain situations, ep_free() in eventpoll.c will kfree the epi->ep eventpoll struct while it still being used by another concurrent thread. Defer the kfree() to an RCU callback to prevent UAF.

Fixes f2e467a48287 ("eventpoll: Fix semi-unbounded recursion")
---
 fs/eventpoll.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
fs/eventpoll.c +5 -1
index aa4318271eee4..075aa8793aaa9 100644
@@ -226,6 +226,9 @@ struct eventpoll {
 	 */
 	refcount_t refcount;
 
+	/* used to defer freeing past ep_get_upwards_depth_proc() RCU walk */
+	struct rcu_head rcu;
+
 #ifdef CONFIG_NET_RX_BUSY_POLL
 	/* used to track busy poll napi_id */
 	unsigned int napi_id;
@@ -790,7 +793,8 @@ static void ep_free(struct eventpoll *ep)
 	mutex_destroy(&ep->mtx);
 	free_uid(ep->user);
 	wakeup_source_unregister(ep->ws);
-	kfree(ep);
+	/* ep_get_upwards_depth_proc() may still hold epi->ep under RCU */
+	kfree_rcu(ep, rcu);
 }
 
 /*
Signature · 1 line
2.53.0
author maintainer
#49 lore raw

PATCH 49/162 net: sched: act_csum: validate nested VLAN headers

In reply to Greg Kroah-Hartman

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

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

From: Ruide Cao <[email protected]>

[ Upstream commit c842743d073bdd683606cb414eb0ca84465dd834 ]

tcf_csum_act() walks nested VLAN headers directly from skb->data when an skb still carries in-payload VLAN tags. The current code reads vlan->h_vlan_encapsulated_proto and then pulls VLAN_HLEN bytes without first ensuring that the full VLAN header is present in the linear area.

If only part of an inner VLAN header is linearized, accessing h_vlan_encapsulated_proto reads past the linear area, and the following skb_pull(VLAN_HLEN) may violate skb invariants.

Fix this by requiring pskb_may_pull(skb, VLAN_HLEN) before accessing and pulling each nested VLAN header. If the header still is not fully available, drop the packet through the existing error path.

---
 net/sched/act_csum.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
net/sched/act_csum.c +5 -1
index 5cc8e407e7911..8ea37c2c3c549 100644
@@ -603,8 +603,12 @@ TC_INDIRECT_SCOPE int tcf_csum_act(struct sk_buff *skb,
 			protocol = skb->protocol;
 			orig_vlan_tag_present = true;
 		} else {
-			struct vlan_hdr *vlan = (struct vlan_hdr *)skb->data;
+			struct vlan_hdr *vlan;
 
+			if (!pskb_may_pull(skb, VLAN_HLEN))
+				goto drop;
+
+			vlan = (struct vlan_hdr *)skb->data;
 			protocol = vlan->h_vlan_encapsulated_proto;
 			skb_pull(skb, VLAN_HLEN);
 			skb_reset_network_header(skb);
Signature · 1 line
2.53.0
author maintainer
#50 lore raw

PATCH 50/162 net: lapbether: handle NETDEV_PRE_TYPE_CHANGE

In reply to Greg Kroah-Hartman

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

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

From: Eric Dumazet <[email protected]>

[ Upstream commit b120e4432f9f56c7103133d6a11245e617695adb ]

lapbeth_data_transmit() expects the underlying device type to be ARPHRD_ETHER.

Returning NOTIFY_BAD from lapbeth_device_event() makes sure bonding driver can not break this expectation.

---
 drivers/net/wan/lapbether.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/net/wan/lapbether.c +8 -5
index 56326f38fe8a3..da61716a66c46 100644
@@ -444,33 +444,36 @@ static void lapbeth_free_device(struct lapbethdev *lapbeth)
 static int lapbeth_device_event(struct notifier_block *this,
 				unsigned long event, void *ptr)
 {
-	struct lapbethdev *lapbeth;
 	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+	struct lapbethdev *lapbeth;
 
 	if (dev_net(dev) != &init_net)
 		return NOTIFY_DONE;
 
-	if (!dev_is_ethdev(dev) && !lapbeth_get_x25_dev(dev))
+	lapbeth = lapbeth_get_x25_dev(dev);
+	if (!dev_is_ethdev(dev) && !lapbeth)
 		return NOTIFY_DONE;
 
 	switch (event) {
 	case NETDEV_UP:
 		/* New ethernet device -> new LAPB interface	 */
-		if (!lapbeth_get_x25_dev(dev))
+		if (!lapbeth)
 			lapbeth_new_device(dev);
 		break;
 	case NETDEV_GOING_DOWN:
 		/* ethernet device closes -> close LAPB interface */
-		lapbeth = lapbeth_get_x25_dev(dev);
 		if (lapbeth)
 			dev_close(lapbeth->axdev);
 		break;
 	case NETDEV_UNREGISTER:
 		/* ethernet device disappears -> remove LAPB interface */
-		lapbeth = lapbeth_get_x25_dev(dev);
 		if (lapbeth)
 			lapbeth_free_device(lapbeth);
 		break;
+	case NETDEV_PRE_TYPE_CHANGE:
+		/* Our underlying device type must not change. */
+		if (lapbeth)
+			return NOTIFY_BAD;
 	}
 
 	return NOTIFY_DONE;
Signature · 1 line
2.53.0
author maintainer
#51 lore raw

PATCH 51/162 ipv4: nexthop: avoid duplicate NHA_HW_STATS_ENABLE on nexthop group dump

In reply to Greg Kroah-Hartman

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

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

From: Fernando Fernandez Mancera <[email protected]>

[ Upstream commit 06aaf04ca815f7a1f17762fd847b7bc14b8833fb ]

Currently NHA_HW_STATS_ENABLE is included twice everytime a dump of nexthop group is performed with NHA_OP_FLAG_DUMP_STATS. As all the stats querying were moved to nla_put_nh_group_stats(), leave only that instance of the attribute querying.

---
 net/ipv4/nexthop.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
net/ipv4/nexthop.c +1 -2
index e3e3f3ee9a5be..fe4ebafb7da14 100644
@@ -904,8 +904,7 @@ static int nla_put_nh_group(struct sk_buff *skb, struct nexthop *nh,
 		goto nla_put_failure;
 
 	if (op_flags & NHA_OP_FLAG_DUMP_STATS &&
-	    (nla_put_u32(skb, NHA_HW_STATS_ENABLE, nhg->hw_stats) ||
-	     nla_put_nh_group_stats(skb, nh, op_flags)))
+	    nla_put_nh_group_stats(skb, nh, op_flags))
 		goto nla_put_failure;
 
 	return 0;
Signature · 1 line
2.53.0
author maintainer
#52 lore raw

PATCH 52/162 ipv4: nexthop: allocate skb dynamically in rtm_get_nexthop()

In reply to Greg Kroah-Hartman

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

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

From: Fernando Fernandez Mancera <[email protected]>

[ Upstream commit 14cf0cd35361f4e94824bf8a42f72713d7702a73 ]

When querying a nexthop object via RTM_GETNEXTHOP, the kernel currently allocates a fixed-size skb using NLMSG_GOODSIZE. While sufficient for single nexthops and small Equal-Cost Multi-Path groups, this fixed allocation fails for large nexthop groups like 512 nexthops.

This results in the following warning splat:

 WARNING: net/ipv4/nexthop.c:3395 at rtm_get_nexthop+0x176/0x1c0, CPU#20: rep/4608
 [...]
 RIP: 0010:rtm_get_nexthop (net/ipv4/nexthop.c:3395)
 [...]
 Call Trace:
  <TASK>
  rtnetlink_rcv_msg (net/core/rtnetlink.c:6989)
  netlink_rcv_skb (net/netlink/af_netlink.c:2550)
  netlink_unicast (net/netlink/af_netlink.c:1319 net/netlink/af_netlink.c:1344)
  netlink_sendmsg (net/netlink/af_netlink.c:1894)
  ____sys_sendmsg (net/socket.c:721 net/socket.c:736 net/socket.c:2585)
  ___sys_sendmsg (net/socket.c:2641)
  __sys_sendmsg (net/socket.c:2671)
  do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94)
  entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130)
  </TASK>

Fix this by allocating the size dynamically using nh_nlmsg_size() and using nlmsg_new(), this is consistent with nexthop_notify() behavior. In addition, adjust nh_nlmsg_size_grp() so it calculates the size needed based on flags passed. While at it, also add the size of NHA_FDB for nexthop group size calculation as it was missing too.

This cannot be reproduced via iproute2 as the group size is currently limited and the command fails as follows:

addattr_l ERROR: message exceeded bound of 1048

---
 net/ipv4/nexthop.c | 38 +++++++++++++++++++++++++++-----------
 1 file changed, 27 insertions(+), 11 deletions(-)
net/ipv4/nexthop.c +27 -11
index fe4ebafb7da14..f1d499a3e2748 100644
@@ -1006,16 +1006,32 @@ static size_t nh_nlmsg_size_grp_res(struct nh_group *nhg)
 		nla_total_size_64bit(8);/* NHA_RES_GROUP_UNBALANCED_TIME */
 }
 
-static size_t nh_nlmsg_size_grp(struct nexthop *nh)
+static size_t nh_nlmsg_size_grp(struct nexthop *nh, u32 op_flags)
 {
 	struct nh_group *nhg = rtnl_dereference(nh->nh_grp);
 	size_t sz = sizeof(struct nexthop_grp) * nhg->num_nh;
 	size_t tot = nla_total_size(sz) +
-		nla_total_size(2); /* NHA_GROUP_TYPE */
+		nla_total_size(2) +	/* NHA_GROUP_TYPE */
+		nla_total_size(0);	/* NHA_FDB */
 
 	if (nhg->resilient)
 		tot += nh_nlmsg_size_grp_res(nhg);
 
+	if (op_flags & NHA_OP_FLAG_DUMP_STATS) {
+		tot += nla_total_size(0) +	  /* NHA_GROUP_STATS */
+		       nla_total_size(4);	  /* NHA_HW_STATS_ENABLE */
+		tot += nhg->num_nh *
+		       (nla_total_size(0) +	  /* NHA_GROUP_STATS_ENTRY */
+			nla_total_size(4) +	  /* NHA_GROUP_STATS_ENTRY_ID */
+			nla_total_size_64bit(8)); /* NHA_GROUP_STATS_ENTRY_PACKETS */
+
+		if (op_flags & NHA_OP_FLAG_DUMP_HW_STATS) {
+			tot += nhg->num_nh *
+			       nla_total_size_64bit(8); /* NHA_GROUP_STATS_ENTRY_PACKETS_HW */
+			tot += nla_total_size(4);	/* NHA_HW_STATS_USED */
+		}
+	}
+
 	return tot;
 }
 
@@ -1050,14 +1066,14 @@ static size_t nh_nlmsg_size_single(struct nexthop *nh)
 	return sz;
 }
 
-static size_t nh_nlmsg_size(struct nexthop *nh)
+static size_t nh_nlmsg_size(struct nexthop *nh, u32 op_flags)
 {
 	size_t sz = NLMSG_ALIGN(sizeof(struct nhmsg));
 
 	sz += nla_total_size(4); /* NHA_ID */
 
 	if (nh->is_group)
-		sz += nh_nlmsg_size_grp(nh) +
+		sz += nh_nlmsg_size_grp(nh, op_flags) +
 		      nla_total_size(4) +	/* NHA_OP_FLAGS */
 		      0;
 	else
@@ -1073,7 +1089,7 @@ static void nexthop_notify(int event, struct nexthop *nh, struct nl_info *info)
 	struct sk_buff *skb;
 	int err = -ENOBUFS;
 
-	skb = nlmsg_new(nh_nlmsg_size(nh), gfp_any());
+	skb = nlmsg_new(nh_nlmsg_size(nh, 0), gfp_any());
 	if (!skb)
 		goto errout;
 
@@ -3333,15 +3349,15 @@ static int rtm_get_nexthop(struct sk_buff *in_skb, struct nlmsghdr *nlh,
 	if (err)
 		return err;
 
-	err = -ENOBUFS;
-	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
-	if (!skb)
-		goto out;
-
 	err = -ENOENT;
 	nh = nexthop_find_by_id(net, id);
 	if (!nh)
-		goto errout_free;
+		goto out;
+
+	err = -ENOBUFS;
+	skb = nlmsg_new(nh_nlmsg_size(nh, op_flags), GFP_KERNEL);
+	if (!skb)
+		goto out;
 
 	err = nh_fill_node(skb, nh, RTM_NEWNEXTHOP, NETLINK_CB(in_skb).portid,
 			   nlh->nlmsg_seq, 0, op_flags);
Signature · 1 line
2.53.0
author maintainer
#53 lore raw

PATCH 53/162 ipv4: icmp: fix null-ptr-deref in icmp_build_probe()

In reply to Greg Kroah-Hartman

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

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

From: Yiqi Sun <[email protected]>

[ Upstream commit fde29fd9349327acc50d19a0b5f3d5a6c964dfd8 ]

ipv6_stub->ipv6_dev_find() may return ERR_PTR(-EAFNOSUPPORT) when the IPv6 stack is not active (CONFIG_IPV6=m and not loaded), and passing this error pointer to dev_hold() will cause a kernel crash with null-ptr-deref.

Instead, silently discard the request. RFC 8335 does not appear to define a specific response for the case where an IPv6 interface identifier is syntactically valid but the implementation cannot perform the lookup at runtime, and silently dropping the request may safer than misreporting "No Such Interface".

Fixes d329ea5bd884 ("icmp: add response to RFC 8335 PROBE messages")
---
 net/ipv4/icmp.c | 7 +++++++
 1 file changed, 7 insertions(+)
net/ipv4/icmp.c +7 -0
index 58feb21ff967d..8e53b595a4194 100644
@@ -1143,6 +1143,13 @@ bool icmp_build_probe(struct sk_buff *skb, struct icmphdr *icmphdr)
 			if (iio->ident.addr.ctype3_hdr.addrlen != sizeof(struct in6_addr))
 				goto send_mal_query;
 			dev = ipv6_stub->ipv6_dev_find(net, &iio->ident.addr.ip_addr.ipv6_addr, dev);
+			/*
+			 * If IPv6 identifier lookup is unavailable, silently
+			 * discard the request instead of misreporting NO_IF.
+			 */
+			if (IS_ERR(dev))
+				return false;
+
 			dev_hold(dev);
 			break;
 #endif
Signature · 1 line
2.53.0
author maintainer
#54 lore raw

PATCH 54/162 net: increase IP_TUNNEL_RECURSION_LIMIT to 5

In reply to Greg Kroah-Hartman

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

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

From: Chris J Arges <[email protected]>

[ Upstream commit 77facb35227c421467cdb49268de433168c2dcef ]

In configurations with multiple tunnel layers and MPLS lwtunnel routing, a single tunnel hop can increment the counter beyond this limit. This causes packets to be dropped with the "Dead loop on virtual device" message even when a routing loop doesn't exist.

Increase IP_TUNNEL_RECURSION_LIMIT from 4 to 5 to handle this use-case.

---
 include/net/ip_tunnels.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
include/net/ip_tunnels.h +1 -1
index 0a5556ef16729..583fd1afd2387 100644
@@ -29,7 +29,7 @@
  * recursion involves route lookups and full IP output, consuming much
  * more stack per level, so a lower limit is needed.
  */
-#define IP_TUNNEL_RECURSION_LIMIT	4
+#define IP_TUNNEL_RECURSION_LIMIT	5
 
 /* Keep error state on tunnel for 30 sec */
 #define IPTUNNEL_ERR_TIMEO	(30*HZ)
Signature · 1 line
2.53.0
author maintainer
#55 lore raw

PATCH 55/162 nfc: s3fwrn5: allocate rx skb before consuming bytes

In reply to Greg Kroah-Hartman

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

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

From: Pengpeng Hou <[email protected]>

[ Upstream commit 5c14a19d5b1645cce1cb1252833d70b23635b632 ]

s3fwrn82_uart_read() reports the number of accepted bytes to the serdev core. The current code consumes bytes into recv_skb and may already deliver a complete frame before allocating a fresh receive buffer.

If that alloc_skb() fails, the callback returns 0 even though it has already consumed bytes, and it leaves recv_skb as NULL for the next receive callback. That breaks the receive_buf() accounting contract and can also lead to a NULL dereference on the next skb_put_u8().

Allocate the receive skb lazily before consuming the next byte instead. If allocation fails, return the number of bytes already accepted.

Fixes 3f52c2cb7e3a ("nfc: s3fwrn5: Support a UART interface")
---
 drivers/nfc/s3fwrn5/uart.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
drivers/nfc/s3fwrn5/uart.c +7 -3
index 9c09c10c2a464..4ee481bd7e965 100644
@@ -58,6 +58,12 @@ static size_t s3fwrn82_uart_read(struct serdev_device *serdev,
 	size_t i;
 
 	for (i = 0; i < count; i++) {
+		if (!phy->recv_skb) {
+			phy->recv_skb = alloc_skb(NCI_SKB_BUFF_LEN, GFP_KERNEL);
+			if (!phy->recv_skb)
+				return i;
+		}
+
 		skb_put_u8(phy->recv_skb, *data++);
 
 		if (phy->recv_skb->len < S3FWRN82_NCI_HEADER)
@@ -69,9 +75,7 @@ static size_t s3fwrn82_uart_read(struct serdev_device *serdev,
 
 		s3fwrn5_recv_frame(phy->common.ndev, phy->recv_skb,
 				   phy->common.mode);
-		phy->recv_skb = alloc_skb(NCI_SKB_BUFF_LEN, GFP_KERNEL);
-		if (!phy->recv_skb)
-			return 0;
+		phy->recv_skb = NULL;
 	}
 
 	return i;
Signature · 1 line
2.53.0
author maintainer
#56 lore raw

PATCH 56/162 net: stmmac: Fix PTP ref clock for Tegra234

In reply to Greg Kroah-Hartman

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

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

From: Jon Hunter <[email protected]>

[ Upstream commit 1345e9f4e3f3bc7d8a0a2138ae29e205a857a555 ]

Since commit 030ce919e114 ("net: stmmac: make sure that ptp_rate is not 0 before configuring timestamping") was added the following error is observed on Tegra234:

ERR KERN tegra-mgbe 6800000.ethernet eth0: Invalid PTP clock rate WARNING KERN tegra-mgbe 6800000.ethernet eth0: PTP init failed

It turns out that the Tegra234 device-tree binding defines the PTP ref clock name as 'ptp-ref' and not 'ptp_ref' and the above commit now exposes this and that the PTP clock is not configured correctly.

In order to update device-tree to use the correct 'ptp_ref' name, update the Tegra MGBE driver to use 'ptp_ref' by default and fallback to using 'ptp-ref' if this clock name is present.

---
 .../net/ethernet/stmicro/stmmac/dwmac-tegra.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)
drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c +17 -2
index 2996bcdea9a28..1e28ac9344771 100644
@@ -9,7 +9,7 @@
 #include "stmmac_platform.h"
 
 static const char *const mgbe_clks[] = {
-	"rx-pcs", "tx", "tx-pcs", "mac-divider", "mac", "mgbe", "ptp-ref", "mac"
+	"rx-pcs", "tx", "tx-pcs", "mac-divider", "mac", "mgbe", "ptp_ref", "mac"
 };
 
 struct tegra_mgbe {
@@ -215,6 +215,7 @@ static int tegra_mgbe_probe(struct platform_device *pdev)
 {
 	struct plat_stmmacenet_data *plat;
 	struct stmmac_resources res;
+	bool use_legacy_ptp = false;
 	struct tegra_mgbe *mgbe;
 	int irq, err, i;
 	u32 value;
@@ -257,9 +258,23 @@ static int tegra_mgbe_probe(struct platform_device *pdev)
 	if (!mgbe->clks)
 		return -ENOMEM;
 
-	for (i = 0; i <  ARRAY_SIZE(mgbe_clks); i++)
+	/* Older device-trees use 'ptp-ref' rather than 'ptp_ref'.
+	 * Fall back when the legacy name is present.
+	 */
+	if (of_property_match_string(pdev->dev.of_node, "clock-names",
+				     "ptp-ref") >= 0)
+		use_legacy_ptp = true;
+
+	for (i = 0; i < ARRAY_SIZE(mgbe_clks); i++) {
 		mgbe->clks[i].id = mgbe_clks[i];
 
+		if (use_legacy_ptp && !strcmp(mgbe_clks[i], "ptp_ref")) {
+			dev_warn(mgbe->dev,
+				 "Device-tree update needed for PTP clock!\n");
+			mgbe->clks[i].id = "ptp-ref";
+		}
+	}
+
 	err = devm_clk_bulk_get(mgbe->dev, ARRAY_SIZE(mgbe_clks), mgbe->clks);
 	if (err < 0)
 		return err;
Signature · 1 line
2.53.0
author maintainer
#57 lore raw

PATCH 57/162 dt-bindings: net: Fix Tegra234 MGBE PTP clock

In reply to Greg Kroah-Hartman

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

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

From: Jon Hunter <[email protected]>

[ Upstream commit fb22b1fc5bca3c0aad95388933497ceb30f1fb26 ]

The PTP clock for the Tegra234 MGBE device is incorrectly named 'ptp-ref' and should be 'ptp_ref'. This is causing the following warning to be observed on Tegra234 platforms that use this device:

ERR KERN tegra-mgbe 6800000.ethernet eth0: Invalid PTP clock rate WARNING KERN tegra-mgbe 6800000.ethernet eth0: PTP init failed

Although this constitutes an ABI breakage in the binding for this device, PTP support has clearly never worked and so fix this now so we can correct the device-tree for this device. Note that the MGBE driver still supports the legacy 'ptp-ref' clock name and so older/existing device-trees will still work, but given that this is not the correct name, there is no point to advertise this in the binding.

---
 .../devicetree/bindings/net/nvidia,tegra234-mgbe.yaml         | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
Documentation/devicetree/bindings/net/nvidia,tegra234-mgbe.yaml +2 -2
index 2bd3efff2485e..215f14d1897d2 100644
@@ -42,7 +42,7 @@ properties:
       - const: mgbe
       - const: mac
       - const: mac-divider
-      - const: ptp-ref
+      - const: ptp_ref
       - const: rx-input-m
       - const: rx-input
       - const: tx
@@ -133,7 +133,7 @@ examples:
                  <&bpmp TEGRA234_CLK_MGBE0_RX_PCS_M>,
                  <&bpmp TEGRA234_CLK_MGBE0_RX_PCS>,
                  <&bpmp TEGRA234_CLK_MGBE0_TX_PCS>;
-        clock-names = "mgbe", "mac", "mac-divider", "ptp-ref", "rx-input-m",
+        clock-names = "mgbe", "mac", "mac-divider", "ptp_ref", "rx-input-m",
                       "rx-input", "tx", "eee-pcs", "rx-pcs-input", "rx-pcs-m",
                       "rx-pcs", "tx-pcs";
         resets = <&bpmp TEGRA234_RESET_MGBE0_MAC>,
Signature · 1 line
2.53.0
author maintainer
#58 lore raw

PATCH 58/162 tracing/probe: reject non-closed empty immediate strings

In reply to Greg Kroah-Hartman

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

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

From: Pengpeng Hou <[email protected]>

[ Upstream commit 4346be6577aaa04586167402ae87bbdbe32484a4 ]

parse_probe_arg() accepts quoted immediate strings and passes the body after the opening quote to __parse_imm_string(). That helper currently computes strlen(str) and immediately dereferences str[len - 1], which underflows when the body is empty and not closed with double-quotation.

Reject empty non-closed immediate strings before checking for the closing quote.

Fixes a42e3c4de964 ("tracing/probe: Add immediate string parameter support")
---
 kernel/trace/trace_probe.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/trace/trace_probe.c +1 -1
index 055f5164bd96f..1b937923d118b 100644
@@ -1040,7 +1040,7 @@ static int __parse_imm_string(char *str, char **pbuf, int offs)
 {
 	size_t len = strlen(str);
 
-	if (str[len - 1] != '"') {
+	if (!len || str[len - 1] != '"') {
 		trace_probe_log_err(offs + len, IMMSTR_NO_CLOSE);
 		return -EINVAL;
 	}
Signature · 1 line
2.53.0
author maintainer
#59 lore raw

PATCH 59/162 ixgbevf: add missing negotiate_features op to Hyper-V ops table

In reply to Greg Kroah-Hartman

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

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

From: Michal Schmidt <[email protected]>

[ Upstream commit 4821d563cd7f251ae728be1a6d04af82a294a5b9 ]

Commit a7075f501bd3 ("ixgbevf: fix mailbox API compatibility by negotiating supported features") added the .negotiate_features callback to ixgbe_mac_operations and populated it in ixgbevf_mac_ops, but forgot to add it to ixgbevf_hv_mac_ops. This leaves the function pointer NULL on Hyper-V VMs.

During probe, ixgbevf_negotiate_api() calls ixgbevf_set_features(), which unconditionally dereferences hw->mac.ops.negotiate_features(). On Hyper-V this results in a NULL pointer dereference:

  BUG: kernel NULL pointer dereference, address: 0000000000000000
  [...]
  Hardware name: Microsoft Corporation Virtual Machine/Virtual Machine [...]
  Workqueue: events work_for_cpu_fn
  RIP: 0010:0x0
  [...]
  Call Trace:
   ixgbevf_negotiate_api+0x66/0x160 [ixgbevf]
   ixgbevf_sw_init+0xe4/0x1f0 [ixgbevf]
   ixgbevf_probe+0x20f/0x4a0 [ixgbevf]
   local_pci_probe+0x50/0xa0
   work_for_cpu_fn+0x1a/0x30
   [...]

Add ixgbevf_hv_negotiate_features_vf() that returns -EOPNOTSUPP and wire it into ixgbevf_hv_mac_ops. The caller already handles -EOPNOTSUPP gracefully.

Fixes a7075f501bd3 ("ixgbevf: fix mailbox API compatibility by negotiating supported features")
Assisted-by Claude:claude-4.6-opus-high Cursor
---
 drivers/net/ethernet/intel/ixgbevf/vf.c | 7 +++++++
 1 file changed, 7 insertions(+)
drivers/net/ethernet/intel/ixgbevf/vf.c +7 -0
index 708d5dd921acc..70dfda13b7885 100644
@@ -709,6 +709,12 @@ static int ixgbevf_negotiate_features_vf(struct ixgbe_hw *hw, u32 *pf_features)
 	return err;
 }
 
+static int ixgbevf_hv_negotiate_features_vf(struct ixgbe_hw *hw,
+					    u32 *pf_features)
+{
+	return -EOPNOTSUPP;
+}
+
 /**
  *  ixgbevf_set_vfta_vf - Set/Unset VLAN filter table address
  *  @hw: pointer to the HW structure
@@ -1142,6 +1148,7 @@ static const struct ixgbe_mac_operations ixgbevf_hv_mac_ops = {
 	.setup_link		= ixgbevf_setup_mac_link_vf,
 	.check_link		= ixgbevf_hv_check_mac_link_vf,
 	.negotiate_api_version	= ixgbevf_hv_negotiate_api_version_vf,
+	.negotiate_features	= ixgbevf_hv_negotiate_features_vf,
 	.set_rar		= ixgbevf_hv_set_rar_vf,
 	.update_mc_addr_list	= ixgbevf_hv_update_mc_addr_list_vf,
 	.update_xcast_mode	= ixgbevf_hv_update_xcast_mode,
Signature · 1 line
2.53.0
author maintainer
#60 lore raw

PATCH 60/162 e1000: check return value of e1000_read_eeprom

In reply to Greg Kroah-Hartman

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

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

From: Agalakov Daniil <[email protected]>

[ Upstream commit d3baa34a470771399c1495bc04b1e26ac15d598e ]

[Why]
e1000_set_eeprom() performs a read-modify-write operation when the write range is not word-aligned. This requires reading the first and last words of the range from the EEPROM to preserve the unmodified bytes.

However, the code does not check the return value of e1000_read_eeprom(). If the read fails, the operation continues using uninitialized data from eeprom_buff. This results in corrupted data being written back to the EEPROM for the boundary words.

Add the missing error checks and abort the operation if reading fails.

Found by Linux Verification Center (linuxtesting.org) with SVACE.

---
 drivers/net/ethernet/intel/e1000/e1000_ethtool.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/net/ethernet/intel/e1000/e1000_ethtool.c +7 -1
index d06d29c6c0370..c7b50059663d9 100644
@@ -496,14 +496,19 @@ static int e1000_set_eeprom(struct net_device *netdev,
 		 */
 		ret_val = e1000_read_eeprom(hw, first_word, 1,
 					    &eeprom_buff[0]);
+		if (ret_val)
+			goto out;
+
 		ptr++;
 	}
-	if (((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) {
+	if ((eeprom->offset + eeprom->len) & 1) {
 		/* need read/modify/write of last changed EEPROM word
 		 * only the first byte of the word is being modified
 		 */
 		ret_val = e1000_read_eeprom(hw, last_word, 1,
 					    &eeprom_buff[last_word - first_word]);
+		if (ret_val)
+			goto out;
 	}
 
 	/* Device's eeprom is always little-endian, word addressable */
@@ -522,6 +527,7 @@ static int e1000_set_eeprom(struct net_device *netdev,
 	if ((ret_val == 0) && (first_word <= EEPROM_CHECKSUM_REG))
 		e1000_update_eeprom_checksum(hw);
 
+out:
 	kfree(eeprom_buff);
 	return ret_val;
 }
Signature · 1 line
2.53.0
author maintainer
#61 lore raw

PATCH 61/162 xsk: tighten UMEM headroom validation to account for tailroom and min frame

In reply to Greg Kroah-Hartman

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

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

From: Maciej Fijalkowski <[email protected]>

[ Upstream commit a315e022a72d95ef5f1d4e58e903cb492b0ad931 ]

The current headroom validation in xdp_umem_reg() could leave us with insufficient space dedicated to even receive minimum-sized ethernet frame. Furthermore if multi-buffer would come to play then skb_shared_info stored at the end of XSK frame would be corrupted.

HW typically works with 128-aligned sizes so let us provide this value as bare minimum.

Multi-buffer setting is known later in the configuration process so besides accounting for 128 bytes, let us also take care of tailroom space upfront.

---
 net/xdp/xdp_umem.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
net/xdp/xdp_umem.c +2 -1
index 9f76ca591d54f..9ec7bd948acc7 100644
@@ -202,7 +202,8 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr)
 	if (!unaligned_chunks && chunks_rem)
 		return -EINVAL;
 
-	if (headroom >= chunk_size - XDP_PACKET_HEADROOM)
+	if (headroom > chunk_size - XDP_PACKET_HEADROOM -
+		       SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) - 128)
 		return -EINVAL;
 
 	if (mr->flags & XDP_UMEM_TX_METADATA_LEN) {
Signature · 1 line
2.53.0
author maintainer
#62 lore raw

PATCH 62/162 xsk: respect tailroom for ZC setups

In reply to Greg Kroah-Hartman

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

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

From: Maciej Fijalkowski <[email protected]>

[ Upstream commit 1ee1605138fc94cc8f8f273321dd2471c64977f9 ]

Multi-buffer XDP stores information about frags in skb_shared_info that sits at the tailroom of a packet. The storage space is reserved via xdp_data_hard_end():

	((xdp)->data_hard_start + (xdp)->frame_sz -	\
	 SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))

and then we refer to it via macro below:

static inline struct skb_shared_info * xdp_get_shared_info_from_buff(const struct xdp_buff *xdp)

{
        return (struct skb_shared_info *)xdp_data_hard_end(xdp);
}

Currently we do not respect this tailroom space in multi-buffer AF_XDP ZC scenario. To address this, introduce xsk_pool_get_tailroom() and use it within xsk_pool_get_rx_frame_size() which is used in ZC drivers to configure length of HW Rx buffer.

Typically drivers on Rx Hw buffers side work on 128 byte alignment so let us align the value returned by xsk_pool_get_rx_frame_size() in order to avoid addressing this on driver's side. This addresses the fact that idpf uses mentioned function *before* pool->dev being set so we were at risk that after subtracting tailroom we would not provide 128-byte aligned value to HW.

Since xsk_pool_get_rx_frame_size() is actively used in xsk_rcv_check() and __xsk_rcv(), add a variant of this routine that will not include 128 byte alignment and therefore old behavior is preserved.

---
 include/net/xdp_sock_drv.h | 23 ++++++++++++++++++++++-
 net/xdp/xsk.c              |  4 ++--
 2 files changed, 24 insertions(+), 3 deletions(-)
include/net/xdp_sock_drv.h +22 -1
index 997e28dd38963..075bc09046463 100644
@@ -37,16 +37,37 @@ static inline u32 xsk_pool_get_headroom(struct xsk_buff_pool *pool)
 	return XDP_PACKET_HEADROOM + pool->headroom;
 }
 
+static inline u32 xsk_pool_get_tailroom(bool mbuf)
+{
+	return mbuf ? SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) : 0;
+}
+
 static inline u32 xsk_pool_get_chunk_size(struct xsk_buff_pool *pool)
 {
 	return pool->chunk_size;
 }
 
-static inline u32 xsk_pool_get_rx_frame_size(struct xsk_buff_pool *pool)
+static inline u32 __xsk_pool_get_rx_frame_size(struct xsk_buff_pool *pool)
 {
 	return xsk_pool_get_chunk_size(pool) - xsk_pool_get_headroom(pool);
 }
 
+static inline u32 xsk_pool_get_rx_frame_size(struct xsk_buff_pool *pool)
+{
+	u32 frame_size =  __xsk_pool_get_rx_frame_size(pool);
+	struct xdp_umem *umem = pool->umem;
+	bool mbuf;
+
+	/* Reserve tailroom only for zero-copy pools that opted into
+	 * multi-buffer. The reserved area is used for skb_shared_info,
+	 * matching the XDP core's xdp_data_hard_end() layout.
+	 */
+	mbuf = pool->dev && (umem->flags & XDP_UMEM_SG_FLAG);
+	frame_size -= xsk_pool_get_tailroom(mbuf);
+
+	return ALIGN_DOWN(frame_size, 128);
+}
+
 static inline u32 xsk_pool_get_rx_frag_step(struct xsk_buff_pool *pool)
 {
 	return pool->unaligned ? 0 : xsk_pool_get_chunk_size(pool);
net/xdp/xsk.c +2 -2
index ed1aeaded9be7..da7e11e3bfad2 100644
@@ -231,7 +231,7 @@ static u32 xsk_copy_xdp(void *to, void **from, u32 to_len,
 
 static int __xsk_rcv(struct xdp_sock *xs, struct xdp_buff *xdp, u32 len)
 {
-	u32 frame_size = xsk_pool_get_rx_frame_size(xs->pool);
+	u32 frame_size = __xsk_pool_get_rx_frame_size(xs->pool);
 	void *copy_from = xsk_copy_xdp_start(xdp), *copy_to;
 	u32 from_len, meta_len, rem, num_desc;
 	struct xdp_buff_xsk *xskb;
@@ -323,7 +323,7 @@ static int xsk_rcv_check(struct xdp_sock *xs, struct xdp_buff *xdp, u32 len)
 	if (xs->dev != xdp->rxq->dev || xs->queue_id != xdp->rxq->queue_index)
 		return -EINVAL;
 
-	if (len > xsk_pool_get_rx_frame_size(xs->pool) && !xs->sg) {
+	if (len > __xsk_pool_get_rx_frame_size(xs->pool) && !xs->sg) {
 		xs->rx_dropped++;
 		return -ENOSPC;
 	}
Signature · 1 line
2.53.0
author maintainer
#63 lore raw

PATCH 63/162 xsk: fix XDP_UMEM_SG_FLAG issues

In reply to Greg Kroah-Hartman

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

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

From: Maciej Fijalkowski <[email protected]>

[ Upstream commit 93e84fe45b752d17a5a46b306ed78f0133bbc719 ]

Currently xp_assign_dev_shared() is missing XDP_USE_SG being propagated to flags so set it in order to preserve mtu check that is supposed to be done only when no multi-buffer setup is in picture.

Also, this flag has the same value as XDP_UMEM_TX_SW_CSUM so we could get unexpected SG setups for software Tx checksums. Since csum flag is UAPI, modify value of XDP_UMEM_SG_FLAG.

Fixes d609f3d228a8 ("xsk: add multi-buffer support for sockets sharing umem")
---
 include/net/xdp_sock.h  | 2 +-
 net/xdp/xsk_buff_pool.c | 4 ++++
 2 files changed, 5 insertions(+), 1 deletion(-)
include/net/xdp_sock.h +1 -1
index df3f5f07bc7c2..98491d774d826 100644
@@ -14,7 +14,7 @@
 #include <linux/mm.h>
 #include <net/sock.h>
 
-#define XDP_UMEM_SG_FLAG (1 << 1)
+#define XDP_UMEM_SG_FLAG BIT(3)
 
 struct net_device;
 struct xsk_queue;
net/xdp/xsk_buff_pool.c +4 -0
index 9db08365fcb00..a9d8aa83f8000 100644
@@ -255,6 +255,10 @@ int xp_assign_dev_shared(struct xsk_buff_pool *pool, struct xdp_sock *umem_xs,
 		return -EINVAL;
 
 	flags = umem->zc ? XDP_ZEROCOPY : XDP_COPY;
+
+	if (umem->flags & XDP_UMEM_SG_FLAG)
+		flags |= XDP_USE_SG;
+
 	if (umem_xs->pool->uses_need_wakeup)
 		flags |= XDP_USE_NEED_WAKEUP;
 
Signature · 1 line
2.53.0
author maintainer
#64 lore raw

PATCH 64/162 xsk: validate MTU against usable frame size on bind

In reply to Greg Kroah-Hartman

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

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

From: Maciej Fijalkowski <[email protected]>

[ Upstream commit 36ee60b569ba0dfb6f961333b90d19ab5b323fa9 ]

AF_XDP bind currently accepts zero-copy pool configurations without verifying that the device MTU fits into the usable frame space provided by the UMEM chunk.

This becomes a problem since we started to respect tailroom which is subtracted from chunk_size (among with headroom). 2k chunk size might not provide enough space for standard 1500 MTU, so let us catch such settings at bind time. Furthermore, validate whether underlying HW will be able to satisfy configured MTU wrt XSK's frame size multiplied by supported Rx buffer chain length (that is exposed via net_device::xdp_zc_max_segs).

---
 net/xdp/xsk_buff_pool.c | 28 +++++++++++++++++++++++++---
 1 file changed, 25 insertions(+), 3 deletions(-)
net/xdp/xsk_buff_pool.c +25 -3
index a9d8aa83f8000..04fe499f76782 100644
@@ -8,6 +8,8 @@
 #include "xdp_umem.h"
 #include "xsk.h"
 
+#define ETH_PAD_LEN (ETH_HLEN + 2 * VLAN_HLEN  + ETH_FCS_LEN)
+
 void xp_add_xsk(struct xsk_buff_pool *pool, struct xdp_sock *xs)
 {
 	unsigned long flags;
@@ -163,8 +165,12 @@ static void xp_disable_drv_zc(struct xsk_buff_pool *pool)
 int xp_assign_dev(struct xsk_buff_pool *pool,
 		  struct net_device *netdev, u16 queue_id, u16 flags)
 {
+	u32 needed = netdev->mtu + ETH_PAD_LEN;
+	u32 segs = netdev->xdp_zc_max_segs;
+	bool mbuf = flags & XDP_USE_SG;
 	bool force_zc, force_copy;
 	struct netdev_bpf bpf;
+	u32 frame_size;
 	int err = 0;
 
 	ASSERT_RTNL();
@@ -184,7 +190,7 @@ int xp_assign_dev(struct xsk_buff_pool *pool,
 	if (err)
 		return err;
 
-	if (flags & XDP_USE_SG)
+	if (mbuf)
 		pool->umem->flags |= XDP_UMEM_SG_FLAG;
 
 	if (flags & XDP_USE_NEED_WAKEUP)
@@ -206,8 +212,24 @@ int xp_assign_dev(struct xsk_buff_pool *pool,
 		goto err_unreg_pool;
 	}
 
-	if (netdev->xdp_zc_max_segs == 1 && (flags & XDP_USE_SG)) {
-		err = -EOPNOTSUPP;
+	if (mbuf) {
+		if (segs == 1) {
+			err = -EOPNOTSUPP;
+			goto err_unreg_pool;
+		}
+	} else {
+		segs = 1;
+	}
+
+	/* open-code xsk_pool_get_rx_frame_size() as pool->dev is not
+	 * set yet at this point; we are before getting down to driver
+	 */
+	frame_size = __xsk_pool_get_rx_frame_size(pool) -
+		     xsk_pool_get_tailroom(mbuf);
+	frame_size = ALIGN_DOWN(frame_size, 128);
+
+	if (needed > frame_size * segs) {
+		err = -EINVAL;
 		goto err_unreg_pool;
 	}
 
Signature · 1 line
2.53.0
author maintainer
#65 lore raw

PATCH 65/162 xfrm: Wait for RCU readers during policy netns exit

In reply to Greg Kroah-Hartman

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

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

From: Steffen Klassert <[email protected]>

[ Upstream commit 069daad4f2ae9c5c108131995529d5f02392c446 ]

xfrm_policy_fini() frees the policy_bydst hash tables after flushing the policy work items and deleting all policies, but it does not wait for concurrent RCU readers to leave their read-side critical sections first.

The policy_bydst tables are published via rcu_assign_pointer() and are looked up through rcu_dereference_check(), so netns teardown must also wait for an RCU grace period before freeing the table memory.

Fix this by adding synchronize_rcu() before freeing the policy hash tables.

Fixes e1e551bc5630 ("xfrm: policy: prepare policy_bydst hash for rcu lookups")
---
 net/xfrm/xfrm_policy.c | 2 ++
 1 file changed, 2 insertions(+)
net/xfrm/xfrm_policy.c +2 -0
index f4713ab7996f2..5fa648a5abe96 100644
@@ -4278,6 +4278,8 @@ static void xfrm_policy_fini(struct net *net)
 #endif
 	xfrm_policy_flush(net, XFRM_POLICY_TYPE_MAIN, false);
 
+	synchronize_rcu();
+
 	WARN_ON(!list_empty(&net->xfrm.policy_all));
 
 	for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
Signature · 1 line
2.53.0
author maintainer
#66 lore raw

PATCH 66/162 xfrm: fix refcount leak in xfrm_migrate_policy_find

In reply to Greg Kroah-Hartman

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

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

From: Kotlyarov Mihail <[email protected]>

[ Upstream commit 83317cce60a032c49480dcdabe146435bd689d03 ]

syzkaller reported a memory leak in xfrm_policy_alloc:

  BUG: memory leak
  unreferenced object 0xffff888114d79000 (size 1024):
    comm "syz.1.17", pid 931
    ...
    xfrm_policy_alloc+0xb3/0x4b0 net/xfrm/xfrm_policy.c:432

The root cause is a double call to xfrm_pol_hold_rcu() in xfrm_migrate_policy_find(). The lookup function already returns a policy with held reference, making the second call redundant.

Remove the redundant xfrm_pol_hold_rcu() call to fix the refcount imbalance and prevent the memory leak.

Found by Linux Verification Center (linuxtesting.org) with Syzkaller.

Fixes 563d5ca93e88 ("xfrm: switch migrate to xfrm_policy_lookup_bytype")
---
 net/xfrm/xfrm_policy.c | 3 ---
 1 file changed, 3 deletions(-)
net/xfrm/xfrm_policy.c +0 -3
index 5fa648a5abe96..fca07f8e60749 100644
@@ -4516,9 +4516,6 @@ static struct xfrm_policy *xfrm_migrate_policy_find(const struct xfrm_selector *
 	pol = xfrm_policy_lookup_bytype(net, type, &fl, sel->family, dir, if_id);
 	if (IS_ERR_OR_NULL(pol))
 		goto out_unlock;
-
-	if (!xfrm_pol_hold_rcu(pol))
-		pol = NULL;
 out_unlock:
 	rcu_read_unlock();
 	return pol;
Signature · 1 line
2.53.0
author maintainer
#67 lore raw

PATCH 67/162 xfrm_user: fix info leak in build_mapping()

In reply to Greg Kroah-Hartman

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

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

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

[ Upstream commit 1beb76b2053b68c491b78370794b8ff63c8f8c02 ]

struct xfrm_usersa_id has a one-byte padding hole after the proto field, which ends up never getting set to zero before copying out to userspace. Fix that up by zeroing out the whole structure before setting individual variables.

Fixes 3a2dfbe8acb1 ("xfrm: Notify changes in UDP encapsulation via netlink")
Cc Steffen Klassert <[email protected]>
Cc Herbert Xu <[email protected]>
Cc "David S. Miller" <[email protected]>
Cc Eric Dumazet <[email protected]>
Cc Jakub Kicinski <[email protected]>
Cc Paolo Abeni <[email protected]>
Cc Simon Horman <[email protected]>
Assisted-by gregkh_clanker_t1000
---
 net/xfrm/xfrm_user.c | 1 +
 1 file changed, 1 insertion(+)
net/xfrm/xfrm_user.c +1 -0
index 9516655e92f19..c00c33c39f20c 100644
@@ -4062,6 +4062,7 @@ static int build_mapping(struct sk_buff *skb, struct xfrm_state *x,
 
 	um = nlmsg_data(nlh);
 
+	memset(&um->id, 0, sizeof(um->id));
 	memcpy(&um->id.daddr, &x->id.daddr, sizeof(um->id.daddr));
 	um->id.spi = x->id.spi;
 	um->id.family = x->props.family;
Signature · 1 line
2.53.0
author maintainer
#68 lore raw

PATCH 68/162 selftests: net: bridge_vlan_mcast: wait for h1 before querier check

In reply to Greg Kroah-Hartman

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

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

From: Daniel Golle <[email protected]>

[ Upstream commit efaa71faf212324ecbf6d5339e9717fe53254f58 ]

The querier-interval test adds h1 (currently a slave of the VRF created by simple_if_init) to a temporary bridge br1 acting as an outside IGMP querier. The kernel VRF driver (drivers/net/vrf.c) calls cycle_netdev() on every slave add and remove, toggling the interface admin-down then up. Phylink takes the PHY down during the admin-down half of that cycle. Since h1 and swp1 are cable-connected, swp1 also loses its link may need several seconds to re-negotiate.

Use setup_wait_dev $h1 0 which waits for h1 to return to UP state, so the test can rely on the link being back up at this point.

---
 tools/testing/selftests/net/forwarding/bridge_vlan_mcast.sh | 1 +
 1 file changed, 1 insertion(+)
tools/testing/selftests/net/forwarding/bridge_vlan_mcast.sh +1 -0
index 72dfbeaf56b92..e8031f68200ad 100755
@@ -414,6 +414,7 @@ vlmc_querier_intvl_test()
 	bridge vlan add vid 10 dev br1 self pvid untagged
 	ip link set dev $h1 master br1
 	ip link set dev br1 up
+	setup_wait_dev $h1 0
 	bridge vlan add vid 10 dev $h1 master
 	bridge vlan global set vid 10 dev br1 mcast_snooping 1 mcast_querier 1
 	sleep 2
Signature · 1 line
2.53.0
author maintainer
#69 lore raw

PATCH 69/162 ipvs: fix NULL deref in ip_vs_add_service error path

In reply to Greg Kroah-Hartman

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

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

From: Weiming Shi <[email protected]>

[ Upstream commit 9a91797e61d286805ae10a92cc48959c30800556 ]

When ip_vs_bind_scheduler() succeeds in ip_vs_add_service(), the local variable sched is set to NULL. If ip_vs_start_estimator() subsequently fails, the out_err cleanup calls ip_vs_unbind_scheduler(svc, sched) with sched == NULL. ip_vs_unbind_scheduler() passes the cur_sched NULL check (because svc->scheduler was set by the successful bind) but then dereferences the NULL sched parameter at sched->done_service, causing a kernel panic at offset 0x30 from NULL.

 Oops: general protection fault, [..] [#1] PREEMPT SMP KASAN NOPTI
 KASAN: null-ptr-deref in range [0x0000000000000030-0x0000000000000037]
 RIP: 0010:ip_vs_unbind_scheduler (net/netfilter/ipvs/ip_vs_sched.c:69)
 Call Trace:
  <TASK>
  ip_vs_add_service.isra.0 (net/netfilter/ipvs/ip_vs_ctl.c:1500)
  do_ip_vs_set_ctl (net/netfilter/ipvs/ip_vs_ctl.c:2809)
  nf_setsockopt (net/netfilter/nf_sockopt.c:102)
  [..]

Fix by simply not clearing the local sched variable after a successful bind. ip_vs_unbind_scheduler() already detects whether a scheduler is installed via svc->scheduler, and keeping sched non-NULL ensures the error path passes the correct pointer to both ip_vs_unbind_scheduler() and ip_vs_scheduler_put().

While the bug is older, the problem popups in more recent kernels (6.2), when the new error path is taken after the ip_vs_start_estimator() call.

Fixes 705dd3444081 ("ipvs: use kthreads for stats estimation")
---
 net/netfilter/ipvs/ip_vs_ctl.c | 1 -
 1 file changed, 1 deletion(-)
net/netfilter/ipvs/ip_vs_ctl.c +0 -1
index 3219338feca4d..efa845ce616d9 100644
@@ -1452,7 +1452,6 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,
 		ret = ip_vs_bind_scheduler(svc, sched);
 		if (ret)
 			goto out_err;
-		sched = NULL;
 	}
 
 	ret = ip_vs_start_estimator(ipvs, &svc->stats);
Signature · 1 line
2.53.0
author maintainer
#70 lore raw

PATCH 70/162 netfilter: nfnetlink_log: initialize nfgenmsg in NLMSG_DONE terminator

In reply to Greg Kroah-Hartman

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

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

From: Xiang Mei <[email protected]>

[ Upstream commit 1f3083aec8836213da441270cdb1ab612dd82cf4 ]

When batching multiple NFLOG messages (inst->qlen > 1), __nfulnl_send() appends an NLMSG_DONE terminator with sizeof(struct nfgenmsg) payload via nlmsg_put(), but never initializes the nfgenmsg bytes. The nlmsg_put() helper only zeroes alignment padding after the payload, not the payload itself, so four bytes of stale kernel heap data are leaked to userspace in the NLMSG_DONE message body.

Use nfnl_msg_put() to build the NLMSG_DONE terminator, which initializes the nfgenmsg payload via nfnl_fill_hdr(), consistent with how __build_packet_message() already constructs NFULNL_MSG_PACKET headers.

Fixes 29c5d4afba51 ("[NETFILTER]: nfnetlink_log: fix sending of multipart messages")
---
 net/netfilter/nfnetlink_log.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
net/netfilter/nfnetlink_log.c +4 -4
index f96421ad14afb..3da32d2f68e09 100644
@@ -361,10 +361,10 @@ static void
 __nfulnl_send(struct nfulnl_instance *inst)
 {
 	if (inst->qlen > 1) {
-		struct nlmsghdr *nlh = nlmsg_put(inst->skb, 0, 0,
-						 NLMSG_DONE,
-						 sizeof(struct nfgenmsg),
-						 0);
+		struct nlmsghdr *nlh = nfnl_msg_put(inst->skb, 0, 0,
+						    NLMSG_DONE, 0,
+						    AF_UNSPEC, NFNETLINK_V0,
+						    htons(inst->group_num));
 		if (WARN_ONCE(!nlh, "bad nlskb size: %u, tailroom %d\n",
 			      inst->skb->len, skb_tailroom(inst->skb))) {
 			kfree_skb(inst->skb);
Signature · 1 line
2.53.0
author maintainer
#71 lore raw

PATCH 71/162 netfilter: xt_multiport: validate range encoding in checkentry

In reply to Greg Kroah-Hartman

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

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

From: Ren Wei <[email protected]>

[ Upstream commit ff64c5bfef12461df8450e0f50bb693b5269c720 ]

ports_match_v1() treats any non-zero pflags entry as the start of a port range and unconditionally consumes the next ports[] element as the range end.

The checkentry path currently validates protocol, flags and count, but it does not validate the range encoding itself. As a result, malformed rules can mark the last slot as a range start or place two range starts back to back, leaving ports_match_v1() to step past the last valid ports[] element while interpreting the rule.

Reject malformed multiport v1 rules in checkentry by validating that each range start has a following element and that the following element is not itself marked as another range start.

Fixes a89ecb6a2ef7 ("[NETFILTER]: x_tables: unify IPv4/IPv6 multiport match")
---
 net/netfilter/xt_multiport.c | 34 ++++++++++++++++++++++++++++++----
 1 file changed, 30 insertions(+), 4 deletions(-)
net/netfilter/xt_multiport.c +30 -4
index 44a00f5acde8a..a1691ff405d3c 100644
@@ -105,6 +105,28 @@ multiport_mt(const struct sk_buff *skb, struct xt_action_param *par)
 	return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1]));
 }
 
+static bool
+multiport_valid_ranges(const struct xt_multiport_v1 *multiinfo)
+{
+	unsigned int i;
+
+	for (i = 0; i < multiinfo->count; i++) {
+		if (!multiinfo->pflags[i])
+			continue;
+
+		if (++i >= multiinfo->count)
+			return false;
+
+		if (multiinfo->pflags[i])
+			return false;
+
+		if (multiinfo->ports[i - 1] > multiinfo->ports[i])
+			return false;
+	}
+
+	return true;
+}
+
 static inline bool
 check(u_int16_t proto,
       u_int8_t ip_invflags,
@@ -127,8 +149,10 @@ static int multiport_mt_check(const struct xt_mtchk_param *par)
 	const struct ipt_ip *ip = par->entryinfo;
 	const struct xt_multiport_v1 *multiinfo = par->matchinfo;
 
-	return check(ip->proto, ip->invflags, multiinfo->flags,
-		     multiinfo->count) ? 0 : -EINVAL;
+	if (!check(ip->proto, ip->invflags, multiinfo->flags, multiinfo->count))
+		return -EINVAL;
+
+	return multiport_valid_ranges(multiinfo) ? 0 : -EINVAL;
 }
 
 static int multiport_mt6_check(const struct xt_mtchk_param *par)
@@ -136,8 +160,10 @@ static int multiport_mt6_check(const struct xt_mtchk_param *par)
 	const struct ip6t_ip6 *ip = par->entryinfo;
 	const struct xt_multiport_v1 *multiinfo = par->matchinfo;
 
-	return check(ip->proto, ip->invflags, multiinfo->flags,
-		     multiinfo->count) ? 0 : -EINVAL;
+	if (!check(ip->proto, ip->invflags, multiinfo->flags, multiinfo->count))
+		return -EINVAL;
+
+	return multiport_valid_ranges(multiinfo) ? 0 : -EINVAL;
 }
 
 static struct xt_match multiport_mt_reg[] __read_mostly = {
Signature · 1 line
2.53.0
author maintainer
#72 lore raw

PATCH 72/162 netfilter: ip6t_eui64: reject invalid MAC header for all packets

In reply to Greg Kroah-Hartman

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

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

From: Zhengchuan Liang <[email protected]>

[ Upstream commit fdce0b3590f724540795b874b4c8850c90e6b0a8 ]

eui64_mt6() derives a modified EUI-64 from the Ethernet source address and compares it with the low 64 bits of the IPv6 source address.

The existing guard only rejects an invalid MAC header when par->fragoff != 0. For packets with par->fragoff == 0, eui64_mt6() can still reach eth_hdr(skb) even when the MAC header is not valid.

Fix this by removing the par->fragoff != 0 condition so that packets with an invalid MAC header are rejected before accessing eth_hdr(skb).

---
 net/ipv6/netfilter/ip6t_eui64.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
net/ipv6/netfilter/ip6t_eui64.c +1 -2
index d704f7ed300c2..da69a27e8332c 100644
@@ -22,8 +22,7 @@ eui64_mt6(const struct sk_buff *skb, struct xt_action_param *par)
 	unsigned char eui64[8];
 
 	if (!(skb_mac_header(skb) >= skb->head &&
-	      skb_mac_header(skb) + ETH_HLEN <= skb->data) &&
-	    par->fragoff != 0) {
+	      skb_mac_header(skb) + ETH_HLEN <= skb->data)) {
 		par->hotdrop = true;
 		return false;
 	}
Signature · 1 line
2.53.0
author maintainer
#73 lore raw

PATCH 73/162 netfilter: nfnetlink_queue: nfqnl_instance GFP_ATOMIC -> GFP_KERNEL_ACCOUNT allocation

In reply to Greg Kroah-Hartman

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

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

From: Scott Mitchell <[email protected]>

[ Upstream commit a4400a5b343d1bc4aa8f685608515413238e7ee2 ]

Currently, instance_create() uses GFP_ATOMIC because it's called while holding instances_lock spinlock. This makes allocation more likely to fail under memory pressure.

Refactor nfqnl_recv_config() to drop RCU lock after instance_lookup() and peer_portid verification. A socket cannot simultaneously send a message and close, so the queue owned by the sending socket cannot be destroyed while processing its CONFIG message. This allows instance_create() to allocate with GFP_KERNEL_ACCOUNT before taking the spinlock.

Stable-dep-of: 936206e3f6ff ("netfilter: nfnetlink_queue: make hash table per queue")

---
 net/netfilter/nfnetlink_queue.c | 75 +++++++++++++++------------------
 1 file changed, 34 insertions(+), 41 deletions(-)
net/netfilter/nfnetlink_queue.c +34 -41
index df0232cf24ce2..5ab750556e992 100644
@@ -178,17 +178,9 @@ instance_create(struct nfnl_queue_net *q, u_int16_t queue_num, u32 portid)
 	unsigned int h;
 	int err;
 
-	spin_lock(&q->instances_lock);
-	if (instance_lookup(q, queue_num)) {
-		err = -EEXIST;
-		goto out_unlock;
-	}
-
-	inst = kzalloc(sizeof(*inst), GFP_ATOMIC);
-	if (!inst) {
-		err = -ENOMEM;
-		goto out_unlock;
-	}
+	inst = kzalloc(sizeof(*inst), GFP_KERNEL_ACCOUNT);
+	if (!inst)
+		return ERR_PTR(-ENOMEM);
 
 	inst->queue_num = queue_num;
 	inst->peer_portid = portid;
@@ -198,9 +190,15 @@ instance_create(struct nfnl_queue_net *q, u_int16_t queue_num, u32 portid)
 	spin_lock_init(&inst->lock);
 	INIT_LIST_HEAD(&inst->queue_list);
 
+	spin_lock(&q->instances_lock);
+	if (instance_lookup(q, queue_num)) {
+		err = -EEXIST;
+		goto out_unlock;
+	}
+
 	if (!try_module_get(THIS_MODULE)) {
 		err = -EAGAIN;
-		goto out_free;
+		goto out_unlock;
 	}
 
 	h = instance_hashfn(queue_num);
@@ -210,10 +208,9 @@ instance_create(struct nfnl_queue_net *q, u_int16_t queue_num, u32 portid)
 
 	return inst;
 
-out_free:
-	kfree(inst);
 out_unlock:
 	spin_unlock(&q->instances_lock);
+	kfree(inst);
 	return ERR_PTR(err);
 }
 
@@ -1602,7 +1599,8 @@ static int nfqnl_recv_config(struct sk_buff *skb, const struct nfnl_info *info,
 	struct nfqnl_msg_config_cmd *cmd = NULL;
 	struct nfqnl_instance *queue;
 	__u32 flags = 0, mask = 0;
-	int ret = 0;
+
+	WARN_ON_ONCE(!lockdep_nfnl_is_held(NFNL_SUBSYS_QUEUE));
 
 	if (nfqa[NFQA_CFG_CMD]) {
 		cmd = nla_data(nfqa[NFQA_CFG_CMD]);
@@ -1648,47 +1646,44 @@ static int nfqnl_recv_config(struct sk_buff *skb, const struct nfnl_info *info,
 		}
 	}
 
+	/* Lookup queue under RCU. After peer_portid check (or for new queue
+	 * in BIND case), the queue is owned by the socket sending this message.
+	 * A socket cannot simultaneously send a message and close, so while
+	 * processing this CONFIG message, nfqnl_rcv_nl_event() (triggered by
+	 * socket close) cannot destroy this queue. Safe to use without RCU.
+	 */
 	rcu_read_lock();
 	queue = instance_lookup(q, queue_num);
 	if (queue && queue->peer_portid != NETLINK_CB(skb).portid) {
-		ret = -EPERM;
-		goto err_out_unlock;
+		rcu_read_unlock();
+		return -EPERM;
 	}
+	rcu_read_unlock();
 
 	if (cmd != NULL) {
 		switch (cmd->command) {
 		case NFQNL_CFG_CMD_BIND:
-			if (queue) {
-				ret = -EBUSY;
-				goto err_out_unlock;
-			}
-			queue = instance_create(q, queue_num,
-						NETLINK_CB(skb).portid);
-			if (IS_ERR(queue)) {
-				ret = PTR_ERR(queue);
-				goto err_out_unlock;
-			}
+			if (queue)
+				return -EBUSY;
+			queue = instance_create(q, queue_num, NETLINK_CB(skb).portid);
+			if (IS_ERR(queue))
+				return PTR_ERR(queue);
 			break;
 		case NFQNL_CFG_CMD_UNBIND:
-			if (!queue) {
-				ret = -ENODEV;
-				goto err_out_unlock;
-			}
+			if (!queue)
+				return -ENODEV;
 			instance_destroy(q, queue);
-			goto err_out_unlock;
+			return 0;
 		case NFQNL_CFG_CMD_PF_BIND:
 		case NFQNL_CFG_CMD_PF_UNBIND:
 			break;
 		default:
-			ret = -ENOTSUPP;
-			goto err_out_unlock;
+			return -EOPNOTSUPP;
 		}
 	}
 
-	if (!queue) {
-		ret = -ENODEV;
-		goto err_out_unlock;
-	}
+	if (!queue)
+		return -ENODEV;
 
 	if (nfqa[NFQA_CFG_PARAMS]) {
 		struct nfqnl_msg_config_params *params =
@@ -1713,9 +1708,7 @@ static int nfqnl_recv_config(struct sk_buff *skb, const struct nfnl_info *info,
 		spin_unlock_bh(&queue->lock);
 	}
 
-err_out_unlock:
-	rcu_read_unlock();
-	return ret;
+	return 0;
 }
 
 static const struct nfnl_callback nfqnl_cb[NFQNL_MSG_MAX] = {
Signature · 1 line
2.53.0
author maintainer
#74 lore raw

PATCH 74/162 netfilter: nfnetlink_queue: make hash table per queue

In reply to Greg Kroah-Hartman

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

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

From: Florian Westphal <[email protected]>

[ Upstream commit 936206e3f6ff411581e615e930263d6f8b78df9d ]

Sharing a global hash table among all queues is tempting, but it can cause crash:

BUG: KASAN: slab-use-after-free in nfqnl_recv_verdict+0x11ac/0x15e0 [nfnetlink_queue]
[..]
 nfqnl_recv_verdict+0x11ac/0x15e0 [nfnetlink_queue]
 nfnetlink_rcv_msg+0x46a/0x930
 kmem_cache_alloc_node_noprof+0x11e/0x450

struct nf_queue_entry is freed via kfree, but parallel cpu can still encounter such an nf_queue_entry when walking the list.

Alternative fix is to free the nf_queue_entry via kfree_rcu() instead, but as we have to alloc/free for each skb this will cause more mem pressure.

Cc Scott Mitchell <[email protected]>
Fixes e19079adcd26 ("netfilter: nfnetlink_queue: optimize verdict lookup with hash table")
---
 include/net/netfilter/nf_queue.h |   1 -
 net/netfilter/nfnetlink_queue.c  | 139 +++++++++++--------------------
 2 files changed, 49 insertions(+), 91 deletions(-)
include/net/netfilter/nf_queue.h +0 -1
index 45eb26b2e95b3..d17035d14d96c 100644
@@ -23,7 +23,6 @@ struct nf_queue_entry {
 	struct nf_hook_state	state;
 	bool			nf_ct_is_unconfirmed;
 	u16			size; /* sizeof(entry) + saved route keys */
-	u16			queue_num;
 
 	/* extra space to store route keys */
 };
net/netfilter/nfnetlink_queue.c +49 -90

248 lines not on this page · raw message

Signature · 1 line
2.53.0
author maintainer
#75 lore raw

PATCH 75/162 net: txgbe: leave space for null terminators on property_entry

In reply to Greg Kroah-Hartman

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

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

From: Fabio Baltieri <[email protected]>

[ Upstream commit 5a37d228799b0ec2c277459c83c814a59d310bc3 ]

Lists of struct property_entry are supposed to be terminated with an empty property, this driver currently seems to be allocating exactly the amount of entry used.

Change the struct definition to leave an extra element for all property_entry.

Fixes c3e382ad6d15 ("net: txgbe: Add software nodes to support phylink")
---
 drivers/net/ethernet/wangxun/txgbe/txgbe_type.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/net/ethernet/wangxun/txgbe/txgbe_type.h +4 -4
index 5fe415f3f2ca9..27f8db89a5c7e 100644
@@ -295,10 +295,10 @@ struct txgbe_nodes {
 	char i2c_name[32];
 	char sfp_name[32];
 	char phylink_name[32];
-	struct property_entry gpio_props[1];
-	struct property_entry i2c_props[3];
-	struct property_entry sfp_props[8];
-	struct property_entry phylink_props[2];
+	struct property_entry gpio_props[2];
+	struct property_entry i2c_props[4];
+	struct property_entry sfp_props[9];
+	struct property_entry phylink_props[3];
 	struct software_node_ref_args i2c_ref[1];
 	struct software_node_ref_args gpio0_ref[1];
 	struct software_node_ref_args gpio1_ref[1];
Signature · 1 line
2.53.0
author maintainer
#76 lore raw

PATCH 76/162 af_unix: read UNIX_DIAG_VFS data under unix_state_lock

In reply to Greg Kroah-Hartman

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

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

From: Jiexun Wang <[email protected]>

[ Upstream commit 39897df386376912d561d4946499379effa1e7ef ]

Exact UNIX diag lookups hold a reference to the socket, but not to u->path. Meanwhile, unix_release_sock() clears u->path under unix_state_lock() and drops the path reference after unlocking.

Read the inode and device numbers for UNIX_DIAG_VFS while holding unix_state_lock(), then emit the netlink attribute after dropping the lock.

This keeps the VFS data stable while the reply is being built.

---
 net/unix/diag.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)
net/unix/diag.c +13 -8
index 9138af8b465e0..6a06a251a2348 100644
@@ -26,18 +26,23 @@ static int sk_diag_dump_name(struct sock *sk, struct sk_buff *nlskb)
 
 static int sk_diag_dump_vfs(struct sock *sk, struct sk_buff *nlskb)
 {
-	struct dentry *dentry = unix_sk(sk)->path.dentry;
+	struct unix_diag_vfs uv;
+	struct dentry *dentry;
+	bool have_vfs = false;
 
+	unix_state_lock(sk);
+	dentry = unix_sk(sk)->path.dentry;
 	if (dentry) {
-		struct unix_diag_vfs uv = {
-			.udiag_vfs_ino = d_backing_inode(dentry)->i_ino,
-			.udiag_vfs_dev = dentry->d_sb->s_dev,
-		};
-
-		return nla_put(nlskb, UNIX_DIAG_VFS, sizeof(uv), &uv);
+		uv.udiag_vfs_ino = d_backing_inode(dentry)->i_ino;
+		uv.udiag_vfs_dev = dentry->d_sb->s_dev;
+		have_vfs = true;
 	}
+	unix_state_unlock(sk);
 
-	return 0;
+	if (!have_vfs)
+		return 0;
+
+	return nla_put(nlskb, UNIX_DIAG_VFS, sizeof(uv), &uv);
 }
 
 static int sk_diag_dump_peer(struct sock *sk, struct sk_buff *nlskb)
Signature · 1 line
2.53.0
author maintainer
#77 lore raw

PATCH 77/162 net: ipa: fix GENERIC_CMD register field masks for IPA v5.0+

In reply to Greg Kroah-Hartman

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

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

From: Alexander Koskovich <[email protected]>

[ Upstream commit 9709b56d908acc120fe8b4ae250b3c9d749ea832 ]

Fix the field masks to match the hardware layout documented in downstream GSI (GSI_V3_0_EE_n_GSI_EE_GENERIC_CMD_*).

Notably this fixes a WARN I was seeing when I tried to send "stop" to the MPSS remoteproc while IPA was up.

---
 drivers/net/ipa/reg/gsi_reg-v5.0.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/net/ipa/reg/gsi_reg-v5.0.c +4 -3
index 36d1e65df71bb..3334d8e20ad28 100644
@@ -156,9 +156,10 @@ REG_FIELDS(EV_CH_CMD, ev_ch_cmd, 0x00025010 + 0x12000 * GSI_EE_AP);
 
 static const u32 reg_generic_cmd_fmask[] = {
 	[GENERIC_OPCODE]				= GENMASK(4, 0),
-	[GENERIC_CHID]					= GENMASK(9, 5),
-	[GENERIC_EE]					= GENMASK(13, 10),
-						/* Bits 14-31 reserved */
+	[GENERIC_CHID]					= GENMASK(12, 5),
+	[GENERIC_EE]					= GENMASK(16, 13),
+						/* Bits 17-23 reserved */
+	[GENERIC_PARAMS]				= GENMASK(31, 24),
 };
 
 REG_FIELDS(GENERIC_CMD, generic_cmd, 0x00025018 + 0x12000 * GSI_EE_AP);
Signature · 1 line
2.53.0
author maintainer
#78 lore raw

PATCH 78/162 net: ipa: fix event ring index not programmed for IPA v5.0+

In reply to Greg Kroah-Hartman

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

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

From: Alexander Koskovich <[email protected]>

[ Upstream commit 56007972c0b1e783ca714d6f1f4d6e66e531d21f ]

For IPA v5.0+, the event ring index field moved from CH_C_CNTXT_0 to CH_C_CNTXT_1. The v5.0 register definition intended to define this field in the CH_C_CNTXT_1 fmask array but used the old identifier of ERINDEX instead of CH_ERINDEX.

Without a valid event ring, GSI channels could never signal transfer completions. This caused gsi_channel_trans_quiesce() to block forever in wait_for_completion().

At least for IPA v5.2 this resolves an issue seen where runtime suspend, system suspend, and remoteproc stop all hanged forever. It also meant the IPA data path was completely non functional.

---
 drivers/net/ipa/reg/gsi_reg-v5.0.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ipa/reg/gsi_reg-v5.0.c +1 -1
index 3334d8e20ad28..6c4a7fbe4de94 100644
@@ -30,7 +30,7 @@ REG_STRIDE_FIELDS(CH_C_CNTXT_0, ch_c_cntxt_0,
 
 static const u32 reg_ch_c_cntxt_1_fmask[] = {
 	[CH_R_LENGTH]					= GENMASK(23, 0),
-	[ERINDEX]					= GENMASK(31, 24),
+	[CH_ERINDEX]					= GENMASK(31, 24),
 };
 
 REG_STRIDE_FIELDS(CH_C_CNTXT_1, ch_c_cntxt_1,
Signature · 1 line
2.53.0
author maintainer
#79 lore raw

PATCH 79/162 l2tp: Drop large packets with UDP encap

In reply to Greg Kroah-Hartman

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

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

From: Alice Mikityanska <[email protected]>

[ Upstream commit ebe560ea5f54134279356703e73b7f867c89db13 ]

syzbot reported a WARN on my patch series [1]. The actual issue is an overflow of 16-bit UDP length field, and it exists in the upstream code. My series added a debug WARN with an overflow check that exposed the issue, that's why syzbot tripped on my patches, rather than on upstream code.

syzbot's repro:

r0 = socket$pppl2tp(0x18, 0x1, 0x1)
r1 = socket$inet6_udp(0xa, 0x2, 0x0)
connect$inet6(r1, &(0x7f00000000c0)={0xa, 0x0, 0x0, @loopback, 0xfffffffc}, 0x1c)
connect$pppl2tp(r0, &(0x7f0000000240)=@pppol2tpin6={0x18, 0x1, {0x0, r1, 0x4, 0x0, 0x0, 0x0, {0xa, 0x4e22, 0xffff, @ipv4={'\x00', '\xff\xff', @empty}}}}, 0x32) writev(r0, &(0x7f0000000080)=[{&(0x7f0000000000)="ee", 0x34000}], 0x1)

It basically sends an oversized (0x34000 bytes) PPPoL2TP packet with UDP encapsulation, and l2tp_xmit_core doesn't check for overflows when it assigns the UDP length field. The value gets trimmed to 16 bites.

Add an overflow check that drops oversized packets and avoids sending packets with trimmed UDP length to the wire.

syzbot's stack trace (with my patch applied):

len >= 65536u

WARNING: ./include/linux/udp.h:38 at udp_set_len_short include/linux/udp.h:38 [inline], CPU#1: syz.0.17/5957
WARNING: ./include/linux/udp.h:38 at l2tp_xmit_core net/l2tp/l2tp_core.c:1293 [inline], CPU#1: syz.0.17/5957
WARNING: ./include/linux/udp.h:38 at l2tp_xmit_skb+0x1204/0x18d0 net/l2tp/l2tp_core.c:1327, CPU#1: syz.0.17/5957
Modules linked in:
CPU: 1 UID: 0 PID: 5957 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
RIP: 0010:udp_set_len_short include/linux/udp.h:38 [inline]
RIP: 0010:l2tp_xmit_core net/l2tp/l2tp_core.c:1293 [inline]
RIP: 0010:l2tp_xmit_skb+0x1204/0x18d0 net/l2tp/l2tp_core.c:1327
Code: 0f 0b 90 e9 21 f9 ff ff e8 e9 05 ec f6 90 0f 0b 90 e9 8d f9 ff ff e8 db 05 ec f6 90 0f 0b 90 e9 cc f9 ff ff e8 cd 05 ec f6 90 <0f> 0b 90 e9 de fa ff ff 44 89 f1 80 e1 07 80 c1 03 38 c1 0f 8c 4f
RSP: 0018:ffffc90003d67878 EFLAGS: 00010293
RAX: ffffffff8ad985e3 RBX: ffff8881a6400090 RCX: ffff8881697f0000
RDX: 0000000000000000 RSI: 0000000000034010 RDI: 000000000000ffff
RBP: dffffc0000000000 R08: 0000000000000003 R09: 0000000000000004
R10: dffffc0000000000 R11: fffff520007acf00 R12: ffff8881baf20900
R13: 0000000000034010 R14: ffff8881a640008e R15: ffff8881760f7000
FS:  000055557e81f500(0000) GS:ffff8882a9467000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000200000033000 CR3: 00000001612f4000 CR4: 00000000000006f0
Call Trace:
 <TASK>
 pppol2tp_sendmsg+0x40a/0x5f0 net/l2tp/l2tp_ppp.c:302
 sock_sendmsg_nosec net/socket.c:727 [inline]
 __sock_sendmsg net/socket.c:742 [inline]
 sock_write_iter+0x503/0x550 net/socket.c:1195
 do_iter_readv_writev+0x619/0x8c0 fs/read_write.c:-1
 vfs_writev+0x33c/0x990 fs/read_write.c:1059
 do_writev+0x154/0x2e0 fs/read_write.c:1105
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f636479c629
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007ffffd4241c8 EFLAGS: 00000246 ORIG_RAX: 0000000000000014
RAX: ffffffffffffffda RBX: 00007f6364a15fa0 RCX: 00007f636479c629
RDX: 0000000000000001 RSI: 0000200000000080 RDI: 0000000000000003
RBP: 00007f6364832b39 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f6364a15fac R14: 00007f6364a15fa0 R15: 00007f6364a15fa0
 </TASK>

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

---
 net/l2tp/l2tp_core.c | 5 +++++
 1 file changed, 5 insertions(+)
net/l2tp/l2tp_core.c +5 -0
index 95060ff7adc5f..87f29ebed5887 100644
@@ -1290,6 +1290,11 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, uns
 		uh->source = inet->inet_sport;
 		uh->dest = inet->inet_dport;
 		udp_len = uhlen + session->hdr_len + data_len;
+		if (udp_len > U16_MAX) {
+			kfree_skb(skb);
+			ret = NET_XMIT_DROP;
+			goto out_unlock;
+		}
 		uh->len = htons(udp_len);
 
 		/* Calculate UDP checksum if configured to do so */
Signature · 1 line
2.53.0
author maintainer
#80 lore raw

PATCH 80/162 gpio: tegra: fix irq_release_resources calling enable instead of disable

In reply to Greg Kroah-Hartman

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

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

From: Samasth Norway Ananda <[email protected]>

[ Upstream commit 1561d96f5f55c1bca9ff047ace5813f4f244eea6 ]

tegra_gpio_irq_release_resources() erroneously calls tegra_gpio_enable() instead of tegra_gpio_disable(). When IRQ resources are released, the GPIO configuration bit (CNF) should be cleared to deconfigure the pin as a GPIO. Leaving it enabled wastes power and can cause unexpected behavior if the pin is later reused for an alternate function via pinctrl.

---
 drivers/gpio/gpio-tegra.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpio/gpio-tegra.c +1 -1
index 6d3a39a03f58e..cc7435ecada80 100644
@@ -593,7 +593,7 @@ static void tegra_gpio_irq_release_resources(struct irq_data *d)
 	struct tegra_gpio_info *tgi = gpiochip_get_data(chip);
 
 	gpiochip_relres_irq(chip, d->hwirq);
-	tegra_gpio_enable(tgi, d->hwirq);
+	tegra_gpio_disable(tgi, d->hwirq);
 }
 
 static void tegra_gpio_irq_print_chip(struct irq_data *d, struct seq_file *s)
Signature · 1 line
2.53.0
author maintainer
#81 lore raw

PATCH 81/162 crypto: af_alg - limit RX SG extraction by receive buffer budget

In reply to Greg Kroah-Hartman

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

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

From: Douya Le <[email protected]>

[ Upstream commit 8eceab19eba9dcbfd2a0daec72e1bf48aa100170 ]

Make af_alg_get_rsgl() limit each RX scatterlist extraction to the remaining receive buffer budget.

af_alg_get_rsgl() currently uses af_alg_readable() only as a gate before extracting data into the RX scatterlist. Limit each extraction to the remaining af_alg_rcvbuf(sk) budget so that receive-side accounting matches the amount of data attached to the request.

If skcipher cannot obtain enough RX space for at least one chunk while more data remains to be processed, reject the recvmsg call instead of rounding the request length down to zero.

Fixes e870456d8e7c8d57c059ea479b5aadbb55ff4c3a ("crypto: algif_skcipher - overhaul memory management")
---
 crypto/af_alg.c         | 2 ++
 crypto/algif_skcipher.c | 5 +++++
 2 files changed, 7 insertions(+)
crypto/af_alg.c +2 -0
index 78e995dddf879..0530dc85e4f87 100644
@@ -1258,6 +1258,8 @@ int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags,
 
 		seglen = min_t(size_t, (maxsize - len),
 			       msg_data_left(msg));
+		/* Never pin more pages than the remaining RX accounting budget. */
+		seglen = min_t(size_t, seglen, af_alg_rcvbuf(sk));
 
 		if (list_empty(&areq->rsgl_list)) {
 			rsgl = &areq->first_rsgl;
crypto/algif_skcipher.c +5 -0
index 125d395c5e009..3549ad1cc42e6 100644
@@ -130,6 +130,11 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
 	 * full block size buffers.
 	 */
 	if (ctx->more || len < ctx->used) {
+		if (len < bs) {
+			err = -EINVAL;
+			goto free;
+		}
+
 		len -= len % bs;
 		cflags |= CRYPTO_SKCIPHER_REQ_NOTFINAL;
 	}
Signature · 1 line
2.53.0
author maintainer
#82 lore raw

PATCH 82/162 perf/x86/intel/uncore: Skip discovery table for offline dies

In reply to Greg Kroah-Hartman

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

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

From: Zide Chen <[email protected]>

[ Upstream commit 7b568e9eba2fad89a696f22f0413d44cf4a1f892 ]

This warning can be triggered if NUMA is disabled and the system boots with fewer CPUs than the number of CPUs in die 0.

WARNING: CPU: 9 PID: 7257 at uncore.c:1157 uncore_pci_pmu_register+0x136/0x160 [intel_uncore]

Currently, the discovery table continues to be parsed even if all CPUs in the associated die are offline. This can lead to an array overflow at "pmu->boxes[die] = box" in uncore_pci_pmu_register(), which may trigger the warning above or cause other issues.

---
 arch/x86/events/intel/uncore_discovery.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/events/intel/uncore_discovery.c +1 -1
index 571e44b496910..aad35190ccf64 100644
@@ -374,7 +374,7 @@ bool intel_uncore_has_discovery_tables(int *ignore)
 				     (val & UNCORE_DISCOVERY_DVSEC2_BIR_MASK) * UNCORE_DISCOVERY_BIR_STEP;
 
 			die = get_device_die_id(dev);
-			if (die < 0)
+			if ((die < 0) || (die >= uncore_max_dies()))
 				continue;
 
 			parse_discovery_table(dev, die, bar_offset, &parsed, ignore);
Signature · 1 line
2.53.0
author maintainer
#83 lore raw

PATCH 83/162 sched/deadline: Use revised wakeup rule for dl_server

In reply to Greg Kroah-Hartman

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

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

From: Peter Zijlstra <[email protected]>

[ Upstream commit 14a857056466be9d3d907a94e92a704ac1be149b ]

John noted that commit 115135422562 ("sched/deadline: Fix 'stuck' dl_server") unfixed the issue from commit a3a70caf7906 ("sched/deadline: Fix dl_server behaviour").

The issue in commit 115135422562 was for wakeups of the server after the deadline; in which case you *have* to start a new period. The case for a3a70caf7906 is wakeups before the deadline.

Now, because the server is effectively running a least-laxity policy, it means that any wakeup during the runnable phase means dl_entity_overflow() will be true. This means we need to adjust the runtime to allow it to still run until the existing deadline expires.

Use the revised wakeup rule for dl_defer entities.

---
 kernel/sched/deadline.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/sched/deadline.c +1 -1
index 8acdd97538546..1ef891f8e3f2f 100644
@@ -1079,7 +1079,7 @@ static void update_dl_entity(struct sched_dl_entity *dl_se)
 	if (dl_time_before(dl_se->deadline, rq_clock(rq)) ||
 	    dl_entity_overflow(dl_se, rq_clock(rq))) {
 
-		if (unlikely(!dl_is_implicit(dl_se) &&
+		if (unlikely((!dl_is_implicit(dl_se) || dl_se->dl_defer) &&
 			     !dl_time_before(dl_se->deadline, rq_clock(rq)) &&
 			     !is_dl_boosted(dl_se))) {
 			update_dl_revised_wakeup(dl_se, rq);
Signature · 1 line
2.53.0
author maintainer
#84 lore raw

PATCH 84/162 clockevents: Prevent timer interrupt starvation

In reply to Greg Kroah-Hartman

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

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

From: Thomas Gleixner <[email protected]>

[ Upstream commit d6e152d905bdb1f32f9d99775e2f453350399a6a ]

Calvin reported an odd NMI watchdog lockup which claims that the CPU locked up in user space. He provided a reproducer, which sets up a timerfd based timer and then rearms it in a loop with an absolute expiry time of 1ns.

As the expiry time is in the past, the timer ends up as the first expiring timer in the per CPU hrtimer base and the clockevent device is programmed with the minimum delta value. If the machine is fast enough, this ends up in a endless loop of programming the delta value to the minimum value defined by the clock event device, before the timer interrupt can fire, which starves the interrupt and consequently triggers the lockup detector because the hrtimer callback of the lockup mechanism is never invoked.

As a first step to prevent this, avoid reprogramming the clock event device when:
- a forced minimum delta event is pending
- the new expiry delta is less then or equal to the minimum delta

Thanks to Calvin for providing the reproducer and to Borislav for testing and providing data from his Zen5 machine.

The problem is not limited to Zen5, but depending on the underlying clock event device (e.g. TSC deadline timer on Intel) and the CPU speed not necessarily observable.

This change serves only as the last resort and further changes will be made to prevent this scenario earlier in the call chain as far as possible.

[ tglx: Updated to restore the old behaviour vs. !force and delta <= 0 and
fixed up the tick-broadcast handlers as pointed out by Borislav ]

---
 include/linux/clockchips.h   |  2 ++
 kernel/time/clockevents.c    | 27 +++++++++++++++++++--------
 kernel/time/hrtimer.c        |  1 +
 kernel/time/tick-broadcast.c |  8 +++++++-
 kernel/time/tick-common.c    |  1 +
 kernel/time/tick-sched.c     |  1 +
 6 files changed, 31 insertions(+), 9 deletions(-)
include/linux/clockchips.h +2 -0
index b0df28ddd394b..50cdc9da8d32a 100644
@@ -80,6 +80,7 @@ enum clock_event_state {
  * @shift:		nanoseconds to cycles divisor (power of two)
  * @state_use_accessors:current state of the device, assigned by the core code
  * @features:		features
+ * @next_event_forced:	True if the last programming was a forced event
  * @retries:		number of forced programming retries
  * @set_state_periodic:	switch state to periodic
  * @set_state_oneshot:	switch state to oneshot
@@ -108,6 +109,7 @@ struct clock_event_device {
 	u32			shift;
 	enum clock_event_state	state_use_accessors;
 	unsigned int		features;
+	unsigned int		next_event_forced;
 	unsigned long		retries;
 
 	int			(*set_state_periodic)(struct clock_event_device *);
kernel/time/clockevents.c +19 -8
index 78c7bd64d0ddf..6f4257e63bba8 100644
@@ -172,6 +172,7 @@ void clockevents_shutdown(struct clock_event_device *dev)
 {
 	clockevents_switch_state(dev, CLOCK_EVT_STATE_SHUTDOWN);
 	dev->next_event = KTIME_MAX;
+	dev->next_event_forced = 0;
 }
 
 /**
@@ -305,7 +306,6 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires,
 {
 	unsigned long long clc;
 	int64_t delta;
-	int rc;
 
 	if (WARN_ON_ONCE(expires < 0))
 		return -ETIME;
@@ -324,16 +324,27 @@ int clockevents_program_event(struct clock_event_device *dev, ktime_t expires,
 		return dev->set_next_ktime(expires, dev);
 
 	delta = ktime_to_ns(ktime_sub(expires, ktime_get()));
-	if (delta <= 0)
-		return force ? clockevents_program_min_delta(dev) : -ETIME;
 
-	delta = min(delta, (int64_t) dev->max_delta_ns);
-	delta = max(delta, (int64_t) dev->min_delta_ns);
+	/* Required for tick_periodic() during early boot */
+	if (delta <= 0 && !force)
+		return -ETIME;
+
+	if (delta > (int64_t)dev->min_delta_ns) {
+		delta = min(delta, (int64_t) dev->max_delta_ns);
+		clc = ((unsigned long long) delta * dev->mult) >> dev->shift;
+		if (!dev->set_next_event((unsigned long) clc, dev))
+			return 0;
+	}
 
-	clc = ((unsigned long long) delta * dev->mult) >> dev->shift;
-	rc = dev->set_next_event((unsigned long) clc, dev);
+	if (dev->next_event_forced)
+		return 0;
 
-	return (rc && force) ? clockevents_program_min_delta(dev) : rc;
+	if (dev->set_next_event(dev->min_delta_ticks, dev)) {
+		if (!force || clockevents_program_min_delta(dev))
+			return -ETIME;
+	}
+	dev->next_event_forced = 1;
+	return 0;
 }
 
 /*
kernel/time/hrtimer.c +1 -0
index 640d2ea4bd1fa..7c57fe7d20d9a 100644
@@ -1852,6 +1852,7 @@ void hrtimer_interrupt(struct clock_event_device *dev)
 	BUG_ON(!cpu_base->hres_active);
 	cpu_base->nr_events++;
 	dev->next_event = KTIME_MAX;
+	dev->next_event_forced = 0;
 
 	raw_spin_lock_irqsave(&cpu_base->lock, flags);
 	entry_time = now = hrtimer_update_base(cpu_base);
kernel/time/tick-broadcast.c +7 -1
index ed58eebb4e8f4..99d2978ef9b98 100644
@@ -76,8 +76,10 @@ const struct clock_event_device *tick_get_wakeup_device(int cpu)
  */
 static void tick_broadcast_start_periodic(struct clock_event_device *bc)
 {
-	if (bc)
+	if (bc) {
+		bc->next_event_forced = 0;
 		tick_setup_periodic(bc, 1);
+	}
 }
 
 /*
@@ -403,6 +405,7 @@ static void tick_handle_periodic_broadcast(struct clock_event_device *dev)
 	bool bc_local;
 
 	raw_spin_lock(&tick_broadcast_lock);
+	tick_broadcast_device.evtdev->next_event_forced = 0;
 
 	/* Handle spurious interrupts gracefully */
 	if (clockevent_state_shutdown(tick_broadcast_device.evtdev)) {
@@ -696,6 +699,7 @@ static void tick_handle_oneshot_broadcast(struct clock_event_device *dev)
 
 	raw_spin_lock(&tick_broadcast_lock);
 	dev->next_event = KTIME_MAX;
+	tick_broadcast_device.evtdev->next_event_forced = 0;
 	next_event = KTIME_MAX;
 	cpumask_clear(tmpmask);
 	now = ktime_get();
@@ -1061,6 +1065,7 @@ static void tick_broadcast_setup_oneshot(struct clock_event_device *bc,
 
 
 	bc->event_handler = tick_handle_oneshot_broadcast;
+	bc->next_event_forced = 0;
 	bc->next_event = KTIME_MAX;
 
 	/*
@@ -1173,6 +1178,7 @@ void hotplug_cpu__broadcast_tick_pull(int deadcpu)
 		}
 
 		/* This moves the broadcast assignment to this CPU: */
+		bc->next_event_forced = 0;
 		clockevents_program_event(bc, bc->next_event, 1);
 	}
 	raw_spin_unlock_irqrestore(&tick_broadcast_lock, flags);
kernel/time/tick-common.c +1 -0
index 9a3859443c042..4b5a42192afa2 100644
@@ -110,6 +110,7 @@ void tick_handle_periodic(struct clock_event_device *dev)
 	int cpu = smp_processor_id();
 	ktime_t next = dev->next_event;
 
+	dev->next_event_forced = 0;
 	tick_periodic(cpu);
 
 	/*
kernel/time/tick-sched.c +1 -0
index f203f000da1ad..e385555b456e8 100644
@@ -1488,6 +1488,7 @@ static void tick_nohz_lowres_handler(struct clock_event_device *dev)
 	struct tick_sched *ts = this_cpu_ptr(&tick_cpu_sched);
 
 	dev->next_event = KTIME_MAX;
+	dev->next_event_forced = 0;
 
 	if (likely(tick_nohz_handler(&ts->sched_timer) == HRTIMER_RESTART))
 		tick_program_event(hrtimer_get_expires(&ts->sched_timer), 1);
Signature · 1 line
2.53.0
author maintainer
#85 lore raw

PATCH 85/162 crypto: algif_aead - Fix minimum RX size check for decryption

In reply to Greg Kroah-Hartman

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

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

From: Herbert Xu <[email protected]>

[ Upstream commit 3d14bd48e3a77091cbce637a12c2ae31b4a1687c ]

The check for the minimum receive buffer size did not take the tag size into account during decryption. Fix this by adding the required extra length.

Reported-by [email protected]
Fixes d887c52d6ae4 ("crypto: algif_aead - overhaul memory management")
---
 crypto/algif_aead.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
crypto/algif_aead.c +1 -1
index 7d58cbbce4af2..481e66f8708bb 100644
@@ -170,7 +170,7 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
 	if (usedpages < outlen) {
 		size_t less = outlen - usedpages;
 
-		if (used < less) {
+		if (used < less + (ctx->enc ? 0 : as)) {
 			err = -EINVAL;
 			goto free;
 		}
Signature · 1 line
2.53.0
#86 lore raw

Re: [PATCH 6.12 085/162] crypto: algif_aead - Fix minimum RX size check for decryption

LGTM -- tested (libkcapi, LUKS, WireGuard/WolfGuard, etc.) atop 6.12.82, with and without patch, with native and libwolfssl.ko crypto, and all 4 scenarios were clean.

Assuming same for 6.18 and 6.19 backports, having bracketed with 6.12 and 7.0.

Quoted 34 lines · Greg Kroah-Hartman

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

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

From: Herbert Xu <[email protected]>

[ Upstream commit 3d14bd48e3a77091cbce637a12c2ae31b4a1687c ]

The check for the minimum receive buffer size did not take the tag size into account during decryption. Fix this by adding the required extra length.

Reported-by [email protected]
Fixes d887c52d6ae4 ("crypto: algif_aead - overhaul memory management")
---
 crypto/algif_aead.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
crypto/algif_aead.c +1 -1
index 7d58cbbce4af2..481e66f8708bb 100644
@@ -170,7 +170,7 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
 	if (usedpages < outlen) {
 		size_t less = outlen - usedpages;
 
-		if (used < less) {
+		if (used < less + (ctx->enc ? 0 : as)) {
 			err = -EINVAL;
 			goto free;
 		}
author maintainer
#87 lore raw

PATCH 86/162 netfilter: conntrack: add missing netlink policy validations

In reply to Greg Kroah-Hartman

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

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

From: Florian Westphal <[email protected]>

[ Upstream commit f900e1d77ee0ef87bfb5ab3fe60f0b3d8ad5ba05 ]

Hyunwoo Kim reports out-of-bounds access in sctp and ctnetlink.

These attributes are used by the kernel without any validation. Extend the netlink policies accordingly.

Quoting the reporter:
nlattr_to_sctp() assigns the user-supplied CTA_PROTOINFO_SCTP_STATE value directly to ct->proto.sctp.state without checking that it is within the valid range. [..]

and: ... with exp->dir = 100, the access at ct->master->tuplehash[100] reads 5600 bytes past the start of a 320-byte nf_conn object, causing a slab-out-of-bounds read confirmed by UBSAN.

Fixes 076a0ca02644 ("netfilter: ctnetlink: add NAT support for expectations")
Fixes a258860e01b8 ("netfilter: ctnetlink: add full support for SCTP to ctnetlink")
---
 net/netfilter/nf_conntrack_netlink.c    | 2 +-
 net/netfilter/nf_conntrack_proto_sctp.c | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)
net/netfilter/nf_conntrack_netlink.c +1 -1
index 323e147fe282b..f51cdfba68fbd 100644
@@ -3460,7 +3460,7 @@ ctnetlink_change_expect(struct nf_conntrack_expect *x,
 
 #if IS_ENABLED(CONFIG_NF_NAT)
 static const struct nla_policy exp_nat_nla_policy[CTA_EXPECT_NAT_MAX+1] = {
-	[CTA_EXPECT_NAT_DIR]	= { .type = NLA_U32 },
+	[CTA_EXPECT_NAT_DIR]	= NLA_POLICY_MAX(NLA_BE32, IP_CT_DIR_REPLY),
 	[CTA_EXPECT_NAT_TUPLE]	= { .type = NLA_NESTED },
 };
 #endif
net/netfilter/nf_conntrack_proto_sctp.c +2 -1
index 4cc97f971264e..fabb2c1ca00ab 100644
@@ -587,7 +587,8 @@ static int sctp_to_nlattr(struct sk_buff *skb, struct nlattr *nla,
 }
 
 static const struct nla_policy sctp_nla_policy[CTA_PROTOINFO_SCTP_MAX+1] = {
-	[CTA_PROTOINFO_SCTP_STATE]	    = { .type = NLA_U8 },
+	[CTA_PROTOINFO_SCTP_STATE]	    = NLA_POLICY_MAX(NLA_U8,
+							 SCTP_CONNTRACK_HEARTBEAT_SENT),
 	[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL]  = { .type = NLA_U32 },
 	[CTA_PROTOINFO_SCTP_VTAG_REPLY]     = { .type = NLA_U32 },
 };
Signature · 1 line
2.53.0
author maintainer
#88 lore raw

PATCH 87/162 Revert "drm/xe/mmio: Avoid double-adjust in 64-bit reads"

In reply to Greg Kroah-Hartman

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

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

This reverts commit 8f6848b2f6eadd903d29572ba0a684eda1e2f4ef.

---
 drivers/gpu/drm/xe/xe_mmio.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/gpu/drm/xe/xe_mmio.c +5 -5
index 449e6c5636712..9ea0973337eda 100644
@@ -316,11 +316,11 @@ u64 __xe_mmio_read64_2x32(struct xe_mmio *mmio, struct xe_reg reg)
 	struct xe_reg reg_udw = { .addr = reg.addr + 0x4 };
 	u32 ldw, udw, oldudw, retries;
 
-	/*
-	 * The two dwords of a 64-bit register can never straddle the offset
-	 * adjustment cutoff.
-	 */
-	xe_tile_assert(mmio->tile, !in_range(mmio->adj_limit, reg.addr + 1, 7));
+	reg.addr = xe_mmio_adjusted_addr(mmio, reg.addr);
+	reg_udw.addr = xe_mmio_adjusted_addr(mmio, reg_udw.addr);
+
+	/* we shouldn't adjust just one register address */
+	xe_tile_assert(mmio->tile, reg_udw.addr == reg.addr + 0x4);
 
 	oldudw = xe_mmio_read32(mmio, reg_udw);
 	for (retries = 5; retries; --retries) {
Signature · 1 line
2.53.0
author maintainer
#89 lore raw

PATCH 88/162 Revert "drm/xe: Switch MMIO interface to take xe_mmio instead of xe_gt"

In reply to Greg Kroah-Hartman

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

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

This reverts commit 26a40327c25c005c1653d66e7b1d8de0fbee15a4.

---
 drivers/gpu/drm/xe/xe_mmio.c  | 131 ++++++++++++++++++----------------
 drivers/gpu/drm/xe/xe_mmio.h  |  76 +++++---------------
 drivers/gpu/drm/xe/xe_trace.h |   7 +-
 3 files changed, 88 insertions(+), 126 deletions(-)
drivers/gpu/drm/xe/xe_mmio.c +68 -63
index 9ea0973337eda..46924f4042418 100644
@@ -67,16 +67,16 @@ static void mmio_multi_tile_setup(struct xe_device *xe, size_t tile_mmio_size)
 
 	/* Possibly override number of tile based on configuration register */
 	if (!xe->info.skip_mtcfg) {
-		struct xe_mmio *mmio = xe_root_tile_mmio(xe);
+		struct xe_gt *gt = xe_root_mmio_gt(xe);
 		u8 tile_count;
 		u32 mtcfg;
 
 		/*
 		 * Although the per-tile mmio regs are not yet initialized, this
-		 * is fine as it's going to the root tile's mmio, that's
-		 * guaranteed to be initialized earlier in xe_mmio_init()
+		 * is fine as it's going to the root gt, that's guaranteed to be
+		 * initialized earlier in xe_mmio_init()
 		 */
-		mtcfg = xe_mmio_read64_2x32(mmio, XEHP_MTCFG_ADDR);
+		mtcfg = xe_mmio_read64_2x32(gt, XEHP_MTCFG_ADDR);
 		tile_count = REG_FIELD_GET(TILE_COUNT, mtcfg) + 1;
 
 		if (tile_count < xe->info.tile_count) {
@@ -187,111 +187,116 @@ int xe_mmio_init(struct xe_device *xe)
 	return devm_add_action_or_reset(xe->drm.dev, mmio_fini, xe);
 }
 
-static void mmio_flush_pending_writes(struct xe_mmio *mmio)
+static void mmio_flush_pending_writes(struct xe_gt *gt)
 {
 #define DUMMY_REG_OFFSET	0x130030
+	struct xe_tile *tile = gt_to_tile(gt);
 	int i;
 
-	if (mmio->tile->xe->info.platform != XE_LUNARLAKE)
+	if (tile->xe->info.platform != XE_LUNARLAKE)
 		return;
 
 	/* 4 dummy writes */
 	for (i = 0; i < 4; i++)
-		writel(0, mmio->regs + DUMMY_REG_OFFSET);
+		writel(0, tile->mmio.regs + DUMMY_REG_OFFSET);
 }
 
-u8 __xe_mmio_read8(struct xe_mmio *mmio, struct xe_reg reg)
+u8 xe_mmio_read8(struct xe_gt *gt, struct xe_reg reg)
 {
-	u32 addr = xe_mmio_adjusted_addr(mmio, reg.addr);
+	struct xe_tile *tile = gt_to_tile(gt);
+	u32 addr = xe_mmio_adjusted_addr(gt, reg.addr);
 	u8 val;
 
 	/* Wa_15015404425 */
-	mmio_flush_pending_writes(mmio);
+	mmio_flush_pending_writes(gt);
 
-	val = readb(mmio->regs + addr);
-	trace_xe_reg_rw(mmio, false, addr, val, sizeof(val));
+	val = readb((reg.ext ? tile->mmio_ext.regs : tile->mmio.regs) + addr);
+	trace_xe_reg_rw(gt, false, addr, val, sizeof(val));
 
 	return val;
 }
 
-u16 __xe_mmio_read16(struct xe_mmio *mmio, struct xe_reg reg)
+u16 xe_mmio_read16(struct xe_gt *gt, struct xe_reg reg)
 {
-	u32 addr = xe_mmio_adjusted_addr(mmio, reg.addr);
+	struct xe_tile *tile = gt_to_tile(gt);
+	u32 addr = xe_mmio_adjusted_addr(gt, reg.addr);
 	u16 val;
 
 	/* Wa_15015404425 */
-	mmio_flush_pending_writes(mmio);
+	mmio_flush_pending_writes(gt);
 
-	val = readw(mmio->regs + addr);
-	trace_xe_reg_rw(mmio, false, addr, val, sizeof(val));
+	val = readw((reg.ext ? tile->mmio_ext.regs : tile->mmio.regs) + addr);
+	trace_xe_reg_rw(gt, false, addr, val, sizeof(val));
 
 	return val;
 }
 
-void __xe_mmio_write32(struct xe_mmio *mmio, struct xe_reg reg, u32 val)
+void xe_mmio_write32(struct xe_gt *gt, struct xe_reg reg, u32 val)
 {
-	u32 addr = xe_mmio_adjusted_addr(mmio, reg.addr);
+	struct xe_tile *tile = gt_to_tile(gt);
+	u32 addr = xe_mmio_adjusted_addr(gt, reg.addr);
 
-	trace_xe_reg_rw(mmio, true, addr, val, sizeof(val));
+	trace_xe_reg_rw(gt, true, addr, val, sizeof(val));
 
-	if (!reg.vf && mmio->sriov_vf_gt)
-		xe_gt_sriov_vf_write32(mmio->sriov_vf_gt, reg, val);
+	if (!reg.vf && IS_SRIOV_VF(gt_to_xe(gt)))
+		xe_gt_sriov_vf_write32(gt, reg, val);
 	else
-		writel(val, mmio->regs + addr);
+		writel(val, (reg.ext ? tile->mmio_ext.regs : tile->mmio.regs) + addr);
 }
 
-u32 __xe_mmio_read32(struct xe_mmio *mmio, struct xe_reg reg)
+u32 xe_mmio_read32(struct xe_gt *gt, struct xe_reg reg)
 {
-	u32 addr = xe_mmio_adjusted_addr(mmio, reg.addr);
+	struct xe_tile *tile = gt_to_tile(gt);
+	u32 addr = xe_mmio_adjusted_addr(gt, reg.addr);
 	u32 val;
 
 	/* Wa_15015404425 */
-	mmio_flush_pending_writes(mmio);
+	mmio_flush_pending_writes(gt);
 
-	if (!reg.vf && mmio->sriov_vf_gt)
-		val = xe_gt_sriov_vf_read32(mmio->sriov_vf_gt, reg);
+	if (!reg.vf && IS_SRIOV_VF(gt_to_xe(gt)))
+		val = xe_gt_sriov_vf_read32(gt, reg);
 	else
-		val = readl(mmio->regs + addr);
+		val = readl((reg.ext ? tile->mmio_ext.regs : tile->mmio.regs) + addr);
 
-	trace_xe_reg_rw(mmio, false, addr, val, sizeof(val));
+	trace_xe_reg_rw(gt, false, addr, val, sizeof(val));
 
 	return val;
 }
 
-u32 __xe_mmio_rmw32(struct xe_mmio *mmio, struct xe_reg reg, u32 clr, u32 set)
+u32 xe_mmio_rmw32(struct xe_gt *gt, struct xe_reg reg, u32 clr, u32 set)
 {
 	u32 old, reg_val;
 
-	old = xe_mmio_read32(mmio, reg);
+	old = xe_mmio_read32(gt, reg);
 	reg_val = (old & ~clr) | set;
-	xe_mmio_write32(mmio, reg, reg_val);
+	xe_mmio_write32(gt, reg, reg_val);
 
 	return old;
 }
 
-int __xe_mmio_write32_and_verify(struct xe_mmio *mmio,
-				 struct xe_reg reg, u32 val, u32 mask, u32 eval)
+int xe_mmio_write32_and_verify(struct xe_gt *gt,
+			       struct xe_reg reg, u32 val, u32 mask, u32 eval)
 {
 	u32 reg_val;
 
-	xe_mmio_write32(mmio, reg, val);
-	reg_val = xe_mmio_read32(mmio, reg);
+	xe_mmio_write32(gt, reg, val);
+	reg_val = xe_mmio_read32(gt, reg);
 
 	return (reg_val & mask) != eval ? -EINVAL : 0;
 }
 
-bool __xe_mmio_in_range(const struct xe_mmio *mmio,
-			const struct xe_mmio_range *range,
-			struct xe_reg reg)
+bool xe_mmio_in_range(const struct xe_gt *gt,
+		      const struct xe_mmio_range *range,
+		      struct xe_reg reg)
 {
-	u32 addr = xe_mmio_adjusted_addr(mmio, reg.addr);
+	u32 addr = xe_mmio_adjusted_addr(gt, reg.addr);
 
 	return range && addr >= range->start && addr <= range->end;
 }
 
 /**
  * xe_mmio_read64_2x32() - Read a 64-bit register as two 32-bit reads
- * @mmio: MMIO target
+ * @gt: MMIO target GT
  * @reg: register to read value from
  *
  * Although Intel GPUs have some 64-bit registers, the hardware officially
@@ -311,21 +316,21 @@ bool __xe_mmio_in_range(const struct xe_mmio *mmio,
  *
  * Returns the value of the 64-bit register.
  */
-u64 __xe_mmio_read64_2x32(struct xe_mmio *mmio, struct xe_reg reg)
+u64 xe_mmio_read64_2x32(struct xe_gt *gt, struct xe_reg reg)
 {
 	struct xe_reg reg_udw = { .addr = reg.addr + 0x4 };
 	u32 ldw, udw, oldudw, retries;
 
-	reg.addr = xe_mmio_adjusted_addr(mmio, reg.addr);
-	reg_udw.addr = xe_mmio_adjusted_addr(mmio, reg_udw.addr);
+	reg.addr = xe_mmio_adjusted_addr(gt, reg.addr);
+	reg_udw.addr = xe_mmio_adjusted_addr(gt, reg_udw.addr);
 
 	/* we shouldn't adjust just one register address */
-	xe_tile_assert(mmio->tile, reg_udw.addr == reg.addr + 0x4);
+	xe_gt_assert(gt, reg_udw.addr == reg.addr + 0x4);
 
-	oldudw = xe_mmio_read32(mmio, reg_udw);
+	oldudw = xe_mmio_read32(gt, reg_udw);
 	for (retries = 5; retries; --retries) {
-		ldw = xe_mmio_read32(mmio, reg);
-		udw = xe_mmio_read32(mmio, reg_udw);
+		ldw = xe_mmio_read32(gt, reg);
+		udw = xe_mmio_read32(gt, reg_udw);
 
 		if (udw == oldudw)
 			break;
@@ -333,14 +338,14 @@ u64 __xe_mmio_read64_2x32(struct xe_mmio *mmio, struct xe_reg reg)
 		oldudw = udw;
 	}
 
-	drm_WARN(&mmio->tile->xe->drm, retries == 0,
-		 "64-bit read of %#x did not stabilize\n", reg.addr);
+	xe_gt_WARN(gt, retries == 0,
+		   "64-bit read of %#x did not stabilize\n", reg.addr);
 
 	return (u64)udw << 32 | ldw;
 }
 
-static int ____xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u32 val, u32 timeout_us,
-			      u32 *out_val, bool atomic, bool expect_match)
+static int __xe_mmio_wait32(struct xe_gt *gt, struct xe_reg reg, u32 mask, u32 val, u32 timeout_us,
+			    u32 *out_val, bool atomic, bool expect_match)
 {
 	ktime_t cur = ktime_get_raw();
 	const ktime_t end = ktime_add_us(cur, timeout_us);
@@ -350,7 +355,7 @@ static int ____xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask,
 	bool check;
 
 	for (;;) {
-		read = xe_mmio_read32(mmio, reg);
+		read = xe_mmio_read32(gt, reg);
 
 		check = (read & mask) == val;
 		if (!expect_match)
@@ -376,7 +381,7 @@ static int ____xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask,
 	}
 
 	if (ret != 0) {
-		read = xe_mmio_read32(mmio, reg);
+		read = xe_mmio_read32(gt, reg);
 
 		check = (read & mask) == val;
 		if (!expect_match)
@@ -394,7 +399,7 @@ static int ____xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask,
 
 /**
  * xe_mmio_wait32() - Wait for a register to match the desired masked value
- * @mmio: MMIO target
+ * @gt: MMIO target GT
  * @reg: register to read value from
  * @mask: mask to be applied to the value read from the register
  * @val: desired value after applying the mask
@@ -411,15 +416,15 @@ static int ____xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask,
  * @timeout_us for different reasons, specially in non-atomic contexts. Thus,
  * it is possible that this function succeeds even after @timeout_us has passed.
  */
-int __xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u32 val, u32 timeout_us,
-		     u32 *out_val, bool atomic)
+int xe_mmio_wait32(struct xe_gt *gt, struct xe_reg reg, u32 mask, u32 val, u32 timeout_us,
+		   u32 *out_val, bool atomic)
 {
-	return ____xe_mmio_wait32(mmio, reg, mask, val, timeout_us, out_val, atomic, true);
+	return __xe_mmio_wait32(gt, reg, mask, val, timeout_us, out_val, atomic, true);
 }
 
 /**
  * xe_mmio_wait32_not() - Wait for a register to return anything other than the given masked value
- * @mmio: MMIO target
+ * @gt: MMIO target GT
  * @reg: register to read value from
  * @mask: mask to be applied to the value read from the register
  * @val: value not to be matched after applying the mask
@@ -430,8 +435,8 @@ int __xe_mmio_wait32(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u32 val,
  * This function works exactly like xe_mmio_wait32() with the exception that
  * @val is expected not to be matched.
  */
-int __xe_mmio_wait32_not(struct xe_mmio *mmio, struct xe_reg reg, u32 mask, u32 val, u32 timeout_us,
-			 u32 *out_val, bool atomic)
+int xe_mmio_wait32_not(struct xe_gt *gt, struct xe_reg reg, u32 mask, u32 val, u32 timeout_us,
+		       u32 *out_val, bool atomic)
 {
-	return ____xe_mmio_wait32(mmio, reg, mask, val, timeout_us, out_val, atomic, false);
+	return __xe_mmio_wait32(gt, reg, mask, val, timeout_us, out_val, atomic, false);
 }
drivers/gpu/drm/xe/xe_mmio.h +17 -59

84 lines not on this page · raw message

drivers/gpu/drm/xe/xe_trace.h +3 -4
index 91130ad8999cd..8573d7a87d840 100644
@@ -21,7 +21,6 @@
 #include "xe_vm.h"
 
 #define __dev_name_xe(xe)	dev_name((xe)->drm.dev)
-#define __dev_name_tile(tile)	__dev_name_xe(tile_to_xe((tile)))
 #define __dev_name_gt(gt)	__dev_name_xe(gt_to_xe((gt)))
 #define __dev_name_eq(q)	__dev_name_gt((q)->gt)
 
@@ -343,12 +342,12 @@ DEFINE_EVENT(xe_hw_fence, xe_hw_fence_try_signal,
 );
 
 TRACE_EVENT(xe_reg_rw,
-	TP_PROTO(struct xe_mmio *mmio, bool write, u32 reg, u64 val, int len),
+	TP_PROTO(struct xe_gt *gt, bool write, u32 reg, u64 val, int len),
 
-	TP_ARGS(mmio, write, reg, val, len),
+	TP_ARGS(gt, write, reg, val, len),
 
 	TP_STRUCT__entry(
-		__string(dev, __dev_name_tile(mmio->tile))
+		__string(dev, __dev_name_gt(gt))
 		__field(u64, val)
 		__field(u32, reg)
 		__field(u16, write)
Signature · 1 line
2.53.0
author maintainer
#90 lore raw

PATCH 89/162 thermal: core: Mark thermal zones as exiting before unregistration

In reply to Greg Kroah-Hartman

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

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

From: Rafael J. Wysocki <[email protected]>

[ Upstream commit 1dae3e70b473adc32f81ca1be926440f9b1de9dc ]

In analogy with a previous change in the thermal zone registration code path, to ensure that __thermal_zone_device_update() will return early for thermal zones that are going away, introduce a thermal zone state flag representing the "exit" state and set it while deleting the thermal zone from thermal_tz_list.

---
 drivers/thermal/thermal_core.c | 3 +++
 drivers/thermal/thermal_core.h | 1 +
 2 files changed, 4 insertions(+)
drivers/thermal/thermal_core.c +3 -0
index aa302ac62b2e2..4663ca7a587c5 100644
@@ -1614,7 +1614,10 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
 	}
 
 	mutex_lock(&tz->lock);
+
+	tz->state |= TZ_STATE_FLAG_EXIT;
 	list_del(&tz->node);
+
 	mutex_unlock(&tz->lock);
 
 	/* Unbind all cdevs associated with 'this' thermal zone */
drivers/thermal/thermal_core.h +1 -0
index 163871699a602..007990ce139d3 100644
@@ -65,6 +65,7 @@ struct thermal_governor {
 #define	TZ_STATE_FLAG_SUSPENDED	BIT(0)
 #define	TZ_STATE_FLAG_RESUMING	BIT(1)
 #define	TZ_STATE_FLAG_INIT	BIT(2)
+#define	TZ_STATE_FLAG_EXIT	BIT(3)
 
 #define TZ_STATE_READY		0
 
Signature · 1 line
2.53.0
author maintainer
#91 lore raw

PATCH 90/162 thermal: core: Address thermal zone removal races with resume

In reply to Greg Kroah-Hartman

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

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

From: Rafael J. Wysocki <[email protected]>

[ Upstream commit 45b859b0728267a6199ee5002d62e6c6f3e8c89d ]

Since thermal_zone_pm_complete() and thermal_zone_device_resume() re-initialize the poll_queue delayed work for the given thermal zone, the cancel_delayed_work_sync() in thermal_zone_device_unregister() may miss some already running work items and the thermal zone may be freed prematurely [1].

There are two failing scenarios that both start with running thermal_pm_notify_complete() right before invoking thermal_zone_device_unregister() for one of the thermal zones.

In the first scenario, there is a work item already running for the given thermal zone when thermal_pm_notify_complete() calls thermal_zone_pm_complete() for that thermal zone and it continues to run when thermal_zone_device_unregister() starts. Since the poll_queue delayed work has been re-initialized by thermal_pm_notify_complete(), the running work item will be missed by the cancel_delayed_work_sync() in thermal_zone_device_unregister() and if it continues to run past the freeing of the thermal zone object, a use-after-free will occur.

In the second scenario, thermal_zone_device_resume() queued up by thermal_pm_notify_complete() runs right after the thermal_zone_exit() called by thermal_zone_device_unregister() has returned. The poll_queue delayed work is re-initialized by it before cancel_delayed_work_sync() is called by thermal_zone_device_unregister(), so it may continue to run after the freeing of the thermal zone object, which also leads to a use-after-free.

Address the first failing scenario by ensuring that no thermal work items will be running when thermal_pm_notify_complete() is called. For this purpose, first move the cancel_delayed_work() call from thermal_zone_pm_complete() to thermal_zone_pm_prepare() to prevent new work from entering the workqueue going forward. Next, switch over to using a dedicated workqueue for thermal events and update the code in thermal_pm_notify() to flush that workqueue after thermal_pm_notify_prepare() has returned which will take care of all leftover thermal work already on the workqueue (that leftover work would do nothing useful anyway because all of the thermal zones have been flagged as suspended).

The second failing scenario is addressed by adding a tz->state check to thermal_zone_device_resume() to prevent it from re-initializing the poll_queue delayed work if the thermal zone is going away.

Note that the above changes will also facilitate relocating the suspend and resume of thermal zones closer to the suspend and resume of devices, respectively.

[ mfo: backport for 6.12.y:
- No guard() or thermal_pm_notify_{prepare,complete}() for the lack of commit d1c8aa2a5c5c ("thermal: core: Manage thermal_list_lock using a mutex guard")
- thermal_zone_device_resume() calls mutex_unlock() to return;
- thermal_pm_notify() has thermal_pm_notify_prepare() in *_PREPARE;
- No WQ_PERCPU flag in alloc_workqueue(), introduced in v6.17. ]

---
 drivers/thermal/thermal_core.c | 33 ++++++++++++++++++++++++++++-----
 1 file changed, 28 insertions(+), 5 deletions(-)
drivers/thermal/thermal_core.c +28 -5
index 4663ca7a587c5..8ce1134e15e56 100644
@@ -42,6 +42,8 @@ static struct thermal_governor *def_governor;
 
 static bool thermal_pm_suspended;
 
+static struct workqueue_struct *thermal_wq __ro_after_init;
+
 /*
  * Governor section: set of functions to handle thermal governors
  *
@@ -328,7 +330,7 @@ static void thermal_zone_device_set_polling(struct thermal_zone_device *tz,
 	if (delay > HZ)
 		delay = round_jiffies_relative(delay);
 
-	mod_delayed_work(system_freezable_power_efficient_wq, &tz->poll_queue, delay);
+	mod_delayed_work(thermal_wq, &tz->poll_queue, delay);
 }
 
 static void thermal_zone_recheck(struct thermal_zone_device *tz, int error)
@@ -1691,6 +1693,12 @@ static void thermal_zone_device_resume(struct work_struct *work)
 
 	mutex_lock(&tz->lock);
 
+	/* If the thermal zone is going away, there's nothing to do. */
+	if (tz->state & TZ_STATE_FLAG_EXIT) {
+		mutex_unlock(&tz->lock);
+		return;
+	}
+
 	tz->state &= ~(TZ_STATE_FLAG_SUSPENDED | TZ_STATE_FLAG_RESUMING);
 
 	thermal_debug_tz_resume(tz);
@@ -1722,6 +1730,9 @@ static void thermal_zone_pm_prepare(struct thermal_zone_device *tz)
 
 	tz->state |= TZ_STATE_FLAG_SUSPENDED;
 
+	/* Prevent new work from getting to the workqueue subsequently. */
+	cancel_delayed_work(&tz->poll_queue);
+
 	mutex_unlock(&tz->lock);
 }
 
@@ -1729,8 +1740,6 @@ static void thermal_zone_pm_complete(struct thermal_zone_device *tz)
 {
 	mutex_lock(&tz->lock);
 
-	cancel_delayed_work(&tz->poll_queue);
-
 	reinit_completion(&tz->resume);
 	tz->state |= TZ_STATE_FLAG_RESUMING;
 
@@ -1740,7 +1749,7 @@ static void thermal_zone_pm_complete(struct thermal_zone_device *tz)
 	 */
 	INIT_DELAYED_WORK(&tz->poll_queue, thermal_zone_device_resume);
 	/* Queue up the work without a delay. */
-	mod_delayed_work(system_freezable_power_efficient_wq, &tz->poll_queue, 0);
+	mod_delayed_work(thermal_wq, &tz->poll_queue, 0);
 
 	mutex_unlock(&tz->lock);
 }
@@ -1762,6 +1771,11 @@ static int thermal_pm_notify(struct notifier_block *nb,
 			thermal_zone_pm_prepare(tz);
 
 		mutex_unlock(&thermal_list_lock);
+		/*
+		 * Allow any leftover thermal work items already on the
+		 * worqueue to complete so they don't get in the way later.
+		 */
+		flush_workqueue(thermal_wq);
 		break;
 	case PM_POST_HIBERNATION:
 	case PM_POST_RESTORE:
@@ -1801,9 +1815,16 @@ static int __init thermal_init(void)
 	if (result)
 		goto error;
 
+	thermal_wq = alloc_workqueue("thermal_events",
+				      WQ_FREEZABLE | WQ_POWER_EFFICIENT, 0);
+	if (!thermal_wq) {
+		result = -ENOMEM;
+		goto unregister_netlink;
+	}
+
 	result = thermal_register_governors();
 	if (result)
-		goto unregister_netlink;
+		goto destroy_workqueue;
 
 	thermal_class = kzalloc(sizeof(*thermal_class), GFP_KERNEL);
 	if (!thermal_class) {
@@ -1830,6 +1851,8 @@ static int __init thermal_init(void)
 
 unregister_governors:
 	thermal_unregister_governors();
+destroy_workqueue:
+	destroy_workqueue(thermal_wq);
 unregister_netlink:
 	thermal_netlink_exit();
 error:
Signature · 1 line
2.53.0
author maintainer
#92 lore raw

PATCH 91/162 ALSA: usb-audio: Improve Focusrite sample rate filtering

In reply to Greg Kroah-Hartman

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

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

From: Geoffrey D. Bennett <[email protected]>

[ Upstream commit 24d2d3c5f94007a5a0554065ab7349bb69e28bcb ]

Replace the bLength == 10 max_rate check in focusrite_valid_sample_rate() with filtering that also examines the bmControls VAL_ALT_SETTINGS bit.

When VAL_ALT_SETTINGS is readable, the device uses strict per-altsetting rate filtering (only the highest rate pair for that altsetting is valid). When it is not readable, all rates up to max_rate are valid.

For devices without the bLength == 10 Format Type descriptor extension but with VAL_ALT_SETTINGS readable and multiple altsettings (only seen in Scarlett 18i8 3rd Gen playback), fall back to the Focusrite
convention: alt 1 = 48kHz, alt 2 = 96kHz, alt 3 = 192kHz.

This produces correct rate tables for all tested Focusrite devices (all Scarlett 2nd, 3rd, and 4th Gen, Clarett+, and Vocaster) using only USB descriptors, allowing QUIRK_FLAG_VALIDATE_RATES to be removed for Focusrite in the next commit.

---
 sound/usb/format.c | 86 +++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 74 insertions(+), 12 deletions(-)
sound/usb/format.c +74 -12
index a9283b2bd2f4e..7041633b02947 100644
@@ -301,9 +301,37 @@ static bool s1810c_valid_sample_rate(struct audioformat *fp,
 }
 
 /*
- * Many Focusrite devices supports a limited set of sampling rates per
- * altsetting. Maximum rate is exposed in the last 4 bytes of Format Type
- * descriptor which has a non-standard bLength = 10.
+ * Focusrite devices use rate pairs: 44100/48000, 88200/96000, and
+ * 176400/192000. Return true if rate is in the pair for max_rate.
+ */
+static bool focusrite_rate_pair(unsigned int rate,
+				unsigned int max_rate)
+{
+	switch (max_rate) {
+	case 48000:  return rate == 44100 || rate == 48000;
+	case 96000:  return rate == 88200 || rate == 96000;
+	case 192000: return rate == 176400 || rate == 192000;
+	default:     return true;
+	}
+}
+
+/*
+ * Focusrite devices report all supported rates in a single clock
+ * source but only a subset is valid per altsetting.
+ *
+ * Detection uses two descriptor features:
+ *
+ * 1. Format Type descriptor bLength == 10: non-standard extension
+ *    with max sample rate in bytes 6..9.
+ *
+ * 2. bmControls VAL_ALT_SETTINGS readable bit: when set, the device
+ *    only supports the highest rate pair for that altsetting, and when
+ *    clear, all rates up to max_rate are valid.
+ *
+ * For devices without the bLength == 10 extension but with
+ * VAL_ALT_SETTINGS readable and multiple altsettings (only seen in
+ * Scarlett 18i8 3rd Gen playback), fall back to the Focusrite
+ * convention: alt 1 = 48kHz, alt 2 = 96kHz, alt 3 = 192kHz.
  */
 static bool focusrite_valid_sample_rate(struct snd_usb_audio *chip,
 					struct audioformat *fp,
@@ -311,8 +339,10 @@ static bool focusrite_valid_sample_rate(struct snd_usb_audio *chip,
 {
 	struct usb_interface *iface;
 	struct usb_host_interface *alts;
+	struct uac2_as_header_descriptor *as;
 	unsigned char *fmt;
 	unsigned int max_rate;
+	bool val_alt;
 
 	iface = usb_ifnum_to_if(chip->dev, fp->iface);
 	if (!iface)
@@ -324,26 +354,58 @@ static bool focusrite_valid_sample_rate(struct snd_usb_audio *chip,
 	if (!fmt)
 		return true;
 
+	as = snd_usb_find_csint_desc(alts->extra, alts->extralen,
+				     NULL, UAC_AS_GENERAL);
+	if (!as)
+		return true;
+
+	val_alt = uac_v2v3_control_is_readable(as->bmControls,
+					       UAC2_AS_VAL_ALT_SETTINGS);
+
 	if (fmt[0] == 10) { /* bLength */
 		max_rate = combine_quad(&fmt[6]);
 
-		/* Validate max rate */
-		if (max_rate != 48000 &&
-		    max_rate != 96000 &&
-		    max_rate != 192000 &&
-		    max_rate != 384000) {
-
+		if (val_alt)
+			return focusrite_rate_pair(rate, max_rate);
+
+		/* No val_alt: rates fall through from higher */
+		switch (max_rate) {
+		case 192000:
+			if (rate == 176400 || rate == 192000)
+				return true;
+			fallthrough;
+		case 96000:
+			if (rate == 88200 || rate == 96000)
+				return true;
+			fallthrough;
+		case 48000:
+			return (rate == 44100 || rate == 48000);
+		default:
 			usb_audio_info(chip,
 				"%u:%d : unexpected max rate: %u\n",
 				fp->iface, fp->altsetting, max_rate);
-
 			return true;
 		}
+	}
 
-		return rate <= max_rate;
+	if (!val_alt)
+		return true;
+
+	/* Multi-altsetting device with val_alt but no max_rate
+	 * in the format descriptor. Use Focusrite convention:
+	 * alt 1 = 48kHz, alt 2 = 96kHz, alt 3 = 192kHz.
+	 */
+	if (iface->num_altsetting <= 2)
+		return true;
+
+	switch (fp->altsetting) {
+	case 1:		max_rate = 48000; break;
+	case 2:		max_rate = 96000; break;
+	case 3:		max_rate = 192000; break;
+	default:	return true;
 	}
 
-	return true;
+	return focusrite_rate_pair(rate, max_rate);
 }
 
 /*
Signature · 1 line
2.53.0
author maintainer
#93 lore raw

PATCH 92/162 idpf: fix PREEMPT_RT raw/bh spinlock nesting for async VC handling

In reply to Greg Kroah-Hartman

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

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

From: Emil Tantilov <[email protected]>

[ Upstream commit 591478118293c1bd628de330a99eb1eb2ef8d76b ]

Switch from using the completion's raw spinlock to a local lock in the idpf_vc_xn struct. The conversion is safe because complete/_all() are called outside the lock and there is no reason to share the completion lock in the current logic. This avoids invalid wait context reported by the kernel due to the async handler taking BH spinlock:

[  805.726977] =============================
[  805.726991] [ BUG: Invalid wait context ]
[  805.727006] 7.0.0-rc2-net-devq-031026+ #28 Tainted: G S         OE
[  805.727026] -----------------------------
[  805.727038] kworker/u261:0/572 is trying to lock:
[  805.727051] ff190da6a8dbb6a0 (&vport_config->mac_filter_list_lock){+...}-{3:3}, at: idpf_mac_filter_async_handler+0xe9/0x260 [idpf]
[  805.727099] other info that might help us debug this:
[  805.727111] context-{5:5}
[  805.727119] 3 locks held by kworker/u261:0/572:
[  805.727132]  #0: ff190da6db3e6148 ((wq_completion)idpf-0000:83:00.0-mbx){+.+.}-{0:0}, at: process_one_work+0x4b5/0x730
[  805.727163]  #1: ff3c6f0a6131fe50 ((work_completion)(&(&adapter->mbx_task)->work)){+.+.}-{0:0}, at: process_one_work+0x1e5/0x730
[  805.727191]  #2: ff190da765190020 (&x->wait#34){+.+.}-{2:2}, at: idpf_recv_mb_msg+0xc8/0x710 [idpf]
[  805.727218] stack backtrace:
...
[  805.727238] Workqueue: idpf-0000:83:00.0-mbx idpf_mbx_task [idpf]
[  805.727247] Call Trace:
[  805.727249]  <TASK>
[  805.727251]  dump_stack_lvl+0x77/0xb0
[  805.727259]  __lock_acquire+0xb3b/0x2290
[  805.727268]  ? __irq_work_queue_local+0x59/0x130
[  805.727275]  lock_acquire+0xc6/0x2f0
[  805.727277]  ? idpf_mac_filter_async_handler+0xe9/0x260 [idpf]
[  805.727284]  ? _printk+0x5b/0x80
[  805.727290]  _raw_spin_lock_bh+0x38/0x50
[  805.727298]  ? idpf_mac_filter_async_handler+0xe9/0x260 [idpf]
[  805.727303]  idpf_mac_filter_async_handler+0xe9/0x260 [idpf]
[  805.727310]  idpf_recv_mb_msg+0x1c8/0x710 [idpf]
[  805.727317]  process_one_work+0x226/0x730
[  805.727322]  worker_thread+0x19e/0x340
[  805.727325]  ? __pfx_worker_thread+0x10/0x10
[  805.727328]  kthread+0xf4/0x130
[  805.727333]  ? __pfx_kthread+0x10/0x10
[  805.727336]  ret_from_fork+0x32c/0x410
[  805.727345]  ? __pfx_kthread+0x10/0x10
[  805.727347]  ret_from_fork_asm+0x1a/0x30
[  805.727354]  </TASK>
---
 drivers/net/ethernet/intel/idpf/idpf_virtchnl.c | 15 ++++++---------
 1 file changed, 6 insertions(+), 9 deletions(-)
drivers/net/ethernet/intel/idpf/idpf_virtchnl.c +6 -9
index a3d4a0185c542..c4ae7d62aaf8d 100644
@@ -59,6 +59,7 @@ typedef int (*async_vc_cb) (struct idpf_adapter *, struct idpf_vc_xn *,
  */
 struct idpf_vc_xn {
 	struct completion completed;
+	spinlock_t lock;
 	enum idpf_vc_xn_state state;
 	size_t reply_sz;
 	struct kvec reply;
@@ -312,26 +313,21 @@ int idpf_send_mb_msg(struct idpf_adapter *adapter, u32 op,
 	return err;
 }
 
-/* API for virtchnl "transaction" support ("xn" for short).
- *
- * We are reusing the completion lock to serialize the accesses to the
- * transaction state for simplicity, but it could be its own separate synchro
- * as well. For now, this API is only used from within a workqueue context;
- * raw_spin_lock() is enough.
- */
+/* API for virtchnl "transaction" support ("xn" for short). */
+
 /**
  * idpf_vc_xn_lock - Request exclusive access to vc transaction
  * @xn: struct idpf_vc_xn* to access
  */
 #define idpf_vc_xn_lock(xn)			\
-	raw_spin_lock(&(xn)->completed.wait.lock)
+	spin_lock(&(xn)->lock)
 
 /**
  * idpf_vc_xn_unlock - Release exclusive access to vc transaction
  * @xn: struct idpf_vc_xn* to access
  */
 #define idpf_vc_xn_unlock(xn)		\
-	raw_spin_unlock(&(xn)->completed.wait.lock)
+	spin_unlock(&(xn)->lock)
 
 /**
  * idpf_vc_xn_release_bufs - Release reference to reply buffer(s) and
@@ -363,6 +359,7 @@ static void idpf_vc_xn_init(struct idpf_vc_xn_manager *vcxn_mngr)
 		xn->state = IDPF_VC_XN_IDLE;
 		xn->idx = i;
 		idpf_vc_xn_release_bufs(xn);
+		spin_lock_init(&xn->lock);
 		init_completion(&xn->completed);
 	}
 
Signature · 1 line
2.53.0
author maintainer
#94 lore raw

PATCH 93/162 nfc: llcp: add missing return after LLCP_CLOSED checks

In reply to Greg Kroah-Hartman

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

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

From: Junxi Qian <[email protected]>

commit 2b5dd4632966c39da6ba74dbc8689b309065e82c upstream.

In nfc_llcp_recv_hdlc() and nfc_llcp_recv_disc(), when the socket state is LLCP_CLOSED, the code correctly calls release_sock() and nfc_llcp_sock_put() but fails to return. Execution falls through to the remainder of the function, which calls release_sock() and nfc_llcp_sock_put() again. This results in a double release_sock() and a refcount underflow via double nfc_llcp_sock_put(), leading to a use-after-free.

Add the missing return statements after the LLCP_CLOSED branches in both functions to prevent the fall-through.

---
 net/nfc/llcp_core.c |    2 ++
 1 file changed, 2 insertions(+)
net/nfc/llcp_core.c +2 -0
@@ -1089,6 +1089,7 @@ static void nfc_llcp_recv_hdlc(struct nf
 	if (sk->sk_state == LLCP_CLOSED) {
 		release_sock(sk);
 		nfc_llcp_sock_put(llcp_sock);
+		return;
 	}
 
 	/* Pass the payload upstream */
@@ -1180,6 +1181,7 @@ static void nfc_llcp_recv_disc(struct nf
 	if (sk->sk_state == LLCP_CLOSED) {
 		release_sock(sk);
 		nfc_llcp_sock_put(llcp_sock);
+		return;
 	}
 
 	if (sk->sk_state == LLCP_CONNECTED) {
author maintainer
#95 lore raw

PATCH 94/162 can: raw: fix ro->uniq use-after-free in raw_rcv()

In reply to Greg Kroah-Hartman

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

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

From: Samuel Page <[email protected]>

commit a535a9217ca3f2fccedaafb2fddb4c48f27d36dc upstream.

raw_release() unregisters raw CAN receive filters via can_rx_unregister(), but receiver deletion is deferred with call_rcu(). This leaves a window where raw_rcv() may still be running in an RCU read-side critical section after raw_release() frees ro->uniq, leading to a use-after-free of the percpu uniq storage.

Move free_percpu(ro->uniq) out of raw_release() and into a raw-specific socket destructor. can_rx_unregister() takes an extra reference to the socket and only drops it from the RCU callback, so freeing uniq from sk_destruct ensures the percpu area is not released until the relevant callbacks have drained.

Fixes 514ac99c64b2 ("can: fix multiple delivery of a single CAN frame for overlapping CAN filters")
Assisted-by Bynario AI
[mkl: applied manually]
---
 net/can/raw.c |   11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
net/can/raw.c +10 -1
@@ -359,6 +359,14 @@ static int raw_notifier(struct notifier_
 	return NOTIFY_DONE;
 }
 
+static void raw_sock_destruct(struct sock *sk)
+{
+	struct raw_sock *ro = raw_sk(sk);
+
+	free_percpu(ro->uniq);
+	can_sock_destruct(sk);
+}
+
 static int raw_init(struct sock *sk)
 {
 	struct raw_sock *ro = raw_sk(sk);
@@ -385,6 +393,8 @@ static int raw_init(struct sock *sk)
 	if (unlikely(!ro->uniq))
 		return -ENOMEM;
 
+	sk->sk_destruct = raw_sock_destruct;
+
 	/* set notifier */
 	spin_lock(&raw_notifier_lock);
 	list_add_tail(&ro->notifier, &raw_notifier_list);
@@ -432,7 +442,6 @@ static int raw_release(struct socket *so
 	ro->bound = 0;
 	ro->dev = NULL;
 	ro->count = 0;
-	free_percpu(ro->uniq);
 
 	sock_orphan(sk);
 	sock->sk = NULL;
author maintainer
#96 lore raw

PATCH 95/162 i2c: s3c24xx: check the size of the SMBUS message before using it

In reply to Greg Kroah-Hartman

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

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

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

commit c0128c7157d639a931353ea344fb44aad6d6e17a upstream.

The first byte of an i2c SMBUS message is the size, and it should be verified to ensure that it is in the range of 0..I2C_SMBUS_BLOCK_MAX before processing it.

This is the same logic that was added in commit a6e04f05ce0b ("i2c:
tegra: check msg length in SMBUS block read") to the i2c tegra driver.

---
 drivers/i2c/busses/i2c-s3c2410.c |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/i2c/busses/i2c-s3c2410.c +6 -1
@@ -504,8 +504,13 @@ static void i2c_s3c_irq_nextbyte(struct
 		i2c->msg->buf[i2c->msg_ptr++] = byte;
 
 		/* Add actual length to read for smbus block read */
-		if (i2c->msg->flags & I2C_M_RECV_LEN && i2c->msg->len == 1)
+		if (i2c->msg->flags & I2C_M_RECV_LEN && i2c->msg->len == 1) {
+			if (byte == 0 || byte > I2C_SMBUS_BLOCK_MAX) {
+				s3c24xx_i2c_stop(i2c, -EPROTO);
+				break;
+			}
 			i2c->msg->len += byte;
+		}
  prepare_read:
 		if (is_msglast(i2c)) {
 			/* last byte of buffer */
author maintainer
#97 lore raw

PATCH 96/162 staging: rtl8723bs: initialize le_tmp64 in rtw_BIP_verify()

In reply to Greg Kroah-Hartman

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

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

From: Lin YuChen <[email protected]>

commit 8c964b82a4e97ec7f25e17b803ee196009b38a57 upstream.

Initialize le_tmp64 to zero in rtw_BIP_verify() to prevent using uninitialized data.

Smatch warns that only 6 bytes are copied to this 8-byte (u64) variable, leaving the last two bytes uninitialized:

drivers/staging/rtl8723bs/core/rtw_security.c:1308 rtw_BIP_verify()
warn: not copying enough bytes for '&le_tmp64' (8 vs 6 bytes)

Initializing the variable at the start of the function fixes this warning and ensures predictable behavior.

---
 drivers/staging/rtl8723bs/core/rtw_security.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/rtl8723bs/core/rtw_security.c +1 -1
@@ -1363,7 +1363,7 @@ u32 rtw_BIP_verify(struct adapter *padap
 	u8 mic[16];
 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
 	__le16 le_tmp;
-	__le64 le_tmp64;
+	__le64 le_tmp64 = 0;
 
 	ori_len = pattrib->pkt_len-WLAN_HDR_A3_LEN+BIP_AAD_SIZE;
 	BIP_AAD = rtw_zmalloc(ori_len);
author maintainer
#98 lore raw

PATCH 97/162 HID: alps: fix NULL pointer dereference in alps_raw_event()

In reply to Greg Kroah-Hartman

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

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

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

commit 1badfc4319224820d5d890f8eab6aa52e4e83339 upstream.

Commit ecfa6f34492c ("HID: Add HID_CLAIMED_INPUT guards in raw_event callbacks missing them") attempted to fix up the HID drivers that had missed the previous fix that was done in 2ff5baa9b527 ("HID: appleir:
Fix potential NULL dereference at raw event handle"), but the alps driver was missed.

Fix this up by properly checking in the hid-alps driver that it had been claimed correctly before attempting to process the raw event.

Fixes 73196ebe134d ("HID: alps: add support for Alps T4 Touchpad device")
Cc stable <[email protected]>
Cc Jiri Kosina <[email protected]>
Cc Benjamin Tissoires <[email protected]>
Cc Masaki Ota <[email protected]>
Assisted-by gregkh_clanker_t1000
---
 drivers/hid/hid-alps.c |    3 +++
 1 file changed, 3 insertions(+)
drivers/hid/hid-alps.c +3 -0
@@ -437,6 +437,9 @@ static int alps_raw_event(struct hid_dev
 	int ret = 0;
 	struct alps_dev *hdata = hid_get_drvdata(hdev);
 
+	if (!(hdev->claimed & HID_CLAIMED_INPUT) || !hdata->input)
+		return 0;
+
 	switch (hdev->product) {
 	case HID_PRODUCT_ID_T4_BTNLESS:
 		ret = t4_raw_event(hdata, data, size);
author maintainer
#99 lore raw

PATCH 98/162 HID: core: clamp report_size in s32ton() to avoid undefined shift

In reply to Greg Kroah-Hartman

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

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

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

commit 69c02ffde6ed4d535fa4e693a9e572729cad3d0d upstream.

s32ton() shifts by n-1 where n is the field's report_size, a value that comes directly from a HID device. The HID parser bounds report_size only to <= 256, so a broken HID device can supply a report descriptor with a wide field that triggers shift exponents up to 256 on a 32-bit type when an output report is built via hid_output_field() or hid_set_field().

Commit ec61b41918587 ("HID: core: fix shift-out-of-bounds in hid_report_raw_event") added the same n > 32 clamp to the function snto32(), but s32ton() was never given the same fix as I guess syzbot hadn't figured out how to fuzz a device the same way.

Fix this up by just clamping the max value of n, just like snto32() does.

Cc stable <[email protected]>
Cc Jiri Kosina <[email protected]>
Cc Benjamin Tissoires <[email protected]>
Assisted-by gregkh_clanker_t1000
---
 drivers/hid/hid-core.c |    3 +++
 1 file changed, 3 insertions(+)
drivers/hid/hid-core.c +3 -0
@@ -71,6 +71,9 @@ static u32 s32ton(__s32 value, unsigned
 	if (!value || !n)
 		return 0;
 
+	if (n > 32)
+		n = 32;
+
 	a = value >> (n - 1);
 	if (a && a != -1)
 		return value < 0 ? 1 << (n - 1) : (1 << (n - 1)) - 1;
author maintainer
#100 lore raw

PATCH 99/162 net: usb: cdc-phonet: fix skb frags[] overflow in rx_complete()

In reply to Greg Kroah-Hartman

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

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

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

commit 600dc40554dc5ad1e6f3af51f700228033f43ea7 upstream.

A malicious USB device claiming to be a CDC Phonet modem can overflow the skb_shared_info->frags[] array by sending an unbounded sequence of full-page bulk transfers.

Drop the skb and increment the length error when the frag limit is reached. This matches the same fix that commit f0813bcd2d9d ("net:
wwan: t7xx: fix potential skb->frags overflow in RX path") did for the t7xx driver.

Cc Andrew Lunn <[email protected]>
Cc "David S. Miller" <[email protected]>
Cc Eric Dumazet <[email protected]>
Cc Jakub Kicinski <[email protected]>
Cc Paolo Abeni <[email protected]>
Cc stable <[email protected]>
Assisted-by gregkh_clanker_t1000
Fixes 87cf65601e17 ("USB host CDC Phonet network interface driver")
---
 drivers/net/usb/cdc-phonet.c |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/net/usb/cdc-phonet.c +6 -1
@@ -157,11 +157,16 @@ static void rx_complete(struct urb *req)
 						PAGE_SIZE);
 				page = NULL;
 			}
-		} else {
+		} else if (skb_shinfo(skb)->nr_frags < MAX_SKB_FRAGS) {
 			skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
 					page, 0, req->actual_length,
 					PAGE_SIZE);
 			page = NULL;
+		} else {
+			dev_kfree_skb_any(skb);
+			pnd->rx_skb = NULL;
+			skb = NULL;
+			dev->stats.rx_length_errors++;
 		}
 		if (req->actual_length < PAGE_SIZE)
 			pnd->rx_skb = NULL; /* Last fragment */
author maintainer
#101 lore raw

PATCH 100/162 NFC: digital: Bounds check NFC-A cascade depth in SDD response handler

In reply to Greg Kroah-Hartman

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

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

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

commit 46ce8be2ced389bccd84bcc04a12cf2f4d0c22d1 upstream.

The NFC-A anti-collision cascade in digital_in_recv_sdd_res() appends 3 or 4 bytes to target->nfcid1 on each round, but the number of cascade rounds is controlled entirely by the peer device. The peer sets the cascade tag in the SDD_RES (deciding 3 vs 4 bytes) and the cascade-incomplete bit in the SEL_RES (deciding whether another round follows).

ISO 14443-3 limits NFC-A to three cascade levels and target->nfcid1 is sized accordingly (NFC_NFCID1_MAXSIZE = 10), but nothing in the driver actually enforces this. This means a malicious peer can keep the cascade running, writing past the heap-allocated nfc_target with each round.

Fix this by rejecting the response when the accumulated UID would exceed the buffer.

Commit e329e71013c9 ("NFC: nci: Bounds check struct nfc_target arrays") fixed similar missing checks against the same field on the NCI path.

Cc Simon Horman <[email protected]>
Cc Kees Cook <[email protected]>
Cc Thierry Escande <[email protected]>
Cc Samuel Ortiz <[email protected]>
Fixes 2c66daecc409 ("NFC Digital: Add NFC-A technology support")
Cc stable <[email protected]>
Assisted-by gregkh_clanker_t1000
---
 net/nfc/digital_technology.c |    6 ++++++
 1 file changed, 6 insertions(+)
net/nfc/digital_technology.c +6 -0
@@ -424,6 +424,12 @@ static void digital_in_recv_sdd_res(stru
 		size = 4;
 	}
 
+	if (target->nfcid1_len + size > NFC_NFCID1_MAXSIZE) {
+		PROTOCOL_ERR("4.7.2.1");
+		rc = -EPROTO;
+		goto exit;
+	}
+
 	memcpy(target->nfcid1 + target->nfcid1_len, sdd_res->nfcid1 + offset,
 	       size);
 	target->nfcid1_len += size;
author maintainer
#102 lore raw

PATCH 101/162 drm/vc4: platform_get_irq_byname() returns an int

In reply to Greg Kroah-Hartman

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

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

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

commit e597a809a2b97e927060ba182f58eb3e6101bc70 upstream.

platform_get_irq_byname() will return a negative value if an error happens, so it should be checked and not just passed directly into devm_request_threaded_irq() hoping all will be ok.

Cc Maxime Ripard <[email protected]>
Cc Dave Stevenson <[email protected]>
Cc Maíra Canal <[email protected]>
Cc Raspberry Pi Kernel Maintenance <[email protected]>
Cc Maarten Lankhorst <[email protected]>
Cc Thomas Zimmermann <[email protected]>
Cc David Airlie <[email protected]>
Cc Simona Vetter <[email protected]>
Cc stable <[email protected]>
Assisted-by gkh_clanker_2000
---
 drivers/gpu/drm/vc4/vc4_hdmi.c |   14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)
drivers/gpu/drm/vc4/vc4_hdmi.c +10 -4
@@ -2391,17 +2391,23 @@ static int vc4_hdmi_hotplug_init(struct
 	int ret;
 
 	if (vc4_hdmi->variant->external_irq_controller) {
-		unsigned int hpd_con = platform_get_irq_byname(pdev, "hpd-connected");
-		unsigned int hpd_rm = platform_get_irq_byname(pdev, "hpd-removed");
+		int hpd = platform_get_irq_byname(pdev, "hpd-connected");
 
-		ret = devm_request_threaded_irq(&pdev->dev, hpd_con,
+		if (hpd < 0)
+			return hpd;
+
+		ret = devm_request_threaded_irq(&pdev->dev, hpd,
 						NULL,
 						vc4_hdmi_hpd_irq_thread, IRQF_ONESHOT,
 						"vc4 hdmi hpd connected", vc4_hdmi);
 		if (ret)
 			return ret;
 
-		ret = devm_request_threaded_irq(&pdev->dev, hpd_rm,
+		hpd = platform_get_irq_byname(pdev, "hpd-removed");
+		if (hpd < 0)
+			return hpd;
+
+		ret = devm_request_threaded_irq(&pdev->dev, hpd,
 						NULL,
 						vc4_hdmi_hpd_irq_thread, IRQF_ONESHOT,
 						"vc4 hdmi hpd disconnected", vc4_hdmi);
author maintainer
#103 lore raw

PATCH 102/162 ALSA: fireworks: bound device-supplied status before string array lookup

In reply to Greg Kroah-Hartman

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

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

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

commit 07704bbf36f57e4379e4cadf96410dab14621e3b upstream.

The status field in an EFW response is a 32-bit value supplied by the firewire device. efr_status_names[] has 17 entries so a status value outside that range goes off into the weeds when looking at the %s value.

Even worse, the status could return EFR_STATUS_INCOMPLETE which is 0x80000000, and is obviously not in that array of potential strings.

Fix this up by properly bounding the index against the array size and printing "unknown" if it's not recognized.

Cc Clemens Ladisch <[email protected]>
Cc Takashi Sakamoto <[email protected]>
Cc Jaroslav Kysela <[email protected]>
Cc Takashi Iwai <[email protected]>
Fixes bde8a8f23bbe ("ALSA: fireworks: Add transaction and some commands")
Cc stable <[email protected]>
Assisted-by gregkh_clanker_t1000
---
 sound/firewire/fireworks/fireworks_command.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
sound/firewire/fireworks/fireworks_command.c +4 -1
@@ -151,10 +151,13 @@ efw_transaction(struct snd_efw *efw, uns
 	    (be32_to_cpu(header->category) != category) ||
 	    (be32_to_cpu(header->command) != command) ||
 	    (be32_to_cpu(header->status) != EFR_STATUS_OK)) {
+		u32 st = be32_to_cpu(header->status);
+
 		dev_err(&efw->unit->device, "EFW command failed [%u/%u]: %s\n",
 			be32_to_cpu(header->category),
 			be32_to_cpu(header->command),
-			efr_status_names[be32_to_cpu(header->status)]);
+			st < ARRAY_SIZE(efr_status_names) ?
+				efr_status_names[st] : "unknown");
 		err = -EIO;
 		goto end;
 	}
author maintainer
#104 lore raw

PATCH 103/162 fbdev: tdfxfb: avoid divide-by-zero on FBIOPUT_VSCREENINFO

In reply to Greg Kroah-Hartman

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

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

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

commit 8f98b81fe011e1879e6a7b1247e69e06a5e17af2 upstream.

Much like commit 19f953e74356 ("fbdev: fb_pm2fb: Avoid potential divide by zero error"), we also need to prevent that same crash from happening in the udlfb driver as it uses pixclock directly when dividing, which will crash.

Cc Helge Deller <[email protected]>
Assisted-by gregkh_clanker_t1000
Cc stable <[email protected]>
---
 drivers/video/fbdev/tdfxfb.c |    3 +++
 1 file changed, 3 insertions(+)
drivers/video/fbdev/tdfxfb.c +3 -0
@@ -496,6 +496,9 @@ static int tdfxfb_check_var(struct fb_va
 		}
 	}
 
+	if (!var->pixclock)
+		return -EINVAL;
+
 	if (PICOS2KHZ(var->pixclock) > par->max_pixclock) {
 		DPRINTK("pixclock too high (%ldKHz)\n",
 			PICOS2KHZ(var->pixclock));
author maintainer
#105 lore raw

PATCH 104/162 usb: gadget: f_ncm: validate minimum block_len in ncm_unwrap_ntb()

In reply to Greg Kroah-Hartman

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

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

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

commit 8f993d30b95dc9557a8a96ceca11abed674c8acb upstream.

The block_len read from the host-supplied NTB header is checked against ntb_max but has no lower bound. When block_len is smaller than opts->ndp_size, the bounds check of:

	ndp_index > (block_len - opts->ndp_size)

will underflow producing a huge unsigned value that ndp_index can never exceed, defeating the check entirely.

The same underflow occurs in the datagram index checks against block_len
- opts->dpe_size. With those checks neutered, a malicious USB host can choose ndp_index and datagram offsets that point past the actual transfer, and the skb_put_data() copies adjacent kernel memory into the network skb.

Fix this by rejecting block lengths that cannot hold at least the NTB header plus one NDP. This will make block_len - opts->ndp_size and block_len - opts->dpe_size both well-defined.

Commit 8d2b1a1ec9f5 ("CDC-NCM: avoid overflow in sanity checking") fixed a related class of issues on the host side of NCM.

Fixes 2b74b0a04d3e ("USB: gadget: f_ncm: add bounds checks to ncm_unwrap_ntb()")
Cc stable <[email protected]>
Assisted-by gregkh_clanker_t1000
---
 drivers/usb/gadget/function/f_ncm.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/usb/gadget/function/f_ncm.c +2 -2
@@ -1209,8 +1209,8 @@ parse_ntb:
 
 	block_len = get_ncm(&tmp, opts->block_length);
 	/* (d)wBlockLength */
-	if (block_len > ntb_max) {
-		INFO(port->func.config->cdev, "OUT size exceeded\n");
+	if ((block_len < opts->nth_size + opts->ndp_size) || (block_len > ntb_max)) {
+		INFO(port->func.config->cdev, "Bad block length: %#X\n", block_len);
 		goto err;
 	}
 
author maintainer
#106 lore raw

PATCH 105/162 usb: gadget: f_phonet: fix skb frags[] overflow in pn_rx_complete()

In reply to Greg Kroah-Hartman

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

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

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

commit c088d5dd2fffb4de1fb8e7f57751c8b82942180a upstream.

A broken/bored/mean USB host can overflow the skb_shared_info->frags[] array on a Linux gadget exposing a Phonet function by sending an unbounded sequence of full-page OUT transfers.

pn_rx_complete() finalizes the skb only when req->actual < req->length, where req->length is set to PAGE_SIZE by the gadget. If the host always sends exactly PAGE_SIZE bytes per transfer, fp->rx.skb will never be reset and each completion will add another fragment via skb_add_rx_frag(). Once nr_frags exceeds MAX_SKB_FRAGS (default 17), subsequent frag stores overwrite memory adjacent to the shinfo on the heap.

Drop the skb and account a length error when the frag limit is reached, matching the fix applied in t7xx by commit f0813bcd2d9d ("net: wwan:
t7xx: fix potential skb->frags overflow in RX path").

---
 drivers/usb/gadget/function/f_phonet.c |    9 +++++++++
 1 file changed, 9 insertions(+)
drivers/usb/gadget/function/f_phonet.c +9 -0
@@ -333,6 +333,15 @@ static void pn_rx_complete(struct usb_ep
 		if (unlikely(!skb))
 			break;
 
+		if (unlikely(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS)) {
+			/* Frame count from host exceeds frags[] capacity */
+			dev_kfree_skb_any(skb);
+			if (fp->rx.skb == skb)
+				fp->rx.skb = NULL;
+			dev->stats.rx_length_errors++;
+			break;
+		}
+
 		if (skb->len == 0) { /* First fragment */
 			skb->protocol = htons(ETH_P_PHONET);
 			skb_reset_mac_header(skb);
author maintainer
#107 lore raw

PATCH 106/162 usb: gadget: renesas_usb3: validate endpoint index in standard request handlers

In reply to Greg Kroah-Hartman

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

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

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

commit f880aac8a57ebd92abfa685d45424b2998ac1059 upstream.

The GET_STATUS and SET/CLEAR_FEATURE handlers extract the endpoint number from the host-supplied wIndex without any sort of validation. Fix this up by validating the number of endpoints actually match up with the number the device has before attempting to dereference a pointer based on this math.

This is just like what was done in commit ee0d382feb44 ("usb: gadget:
aspeed_udc: validate endpoint index for ast udc") for the aspeed driver.

Fixes 746bfe63bba3 ("usb: gadget: renesas_usb3: add support for Renesas USB3.0 peripheral controller")
Cc stable <[email protected]>
Assisted-by gregkh_clanker_t1000
---
 drivers/usb/gadget/udc/renesas_usb3.c |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/usb/gadget/udc/renesas_usb3.c +6 -1
@@ -1669,6 +1669,10 @@ static bool usb3_std_req_get_status(stru
 		break;
 	case USB_RECIP_ENDPOINT:
 		num = le16_to_cpu(ctrl->wIndex) & USB_ENDPOINT_NUMBER_MASK;
+		if (num >= usb3->num_usb3_eps) {
+			stall = true;
+			break;
+		}
 		usb3_ep = usb3_get_ep(usb3, num);
 		if (usb3_ep->halt)
 			status |= 1 << USB_ENDPOINT_HALT;
@@ -1781,7 +1785,8 @@ static bool usb3_std_req_feature_endpoin
 	struct renesas_usb3_ep *usb3_ep;
 	struct renesas_usb3_request *usb3_req;
 
-	if (le16_to_cpu(ctrl->wValue) != USB_ENDPOINT_HALT)
+	if ((le16_to_cpu(ctrl->wValue) != USB_ENDPOINT_HALT) ||
+	    (num >= usb3->num_usb3_eps))
 		return true;	/* stall */
 
 	usb3_ep = usb3_get_ep(usb3, num);
author maintainer
#108 lore raw

PATCH 107/162 smb: client: fix off-by-8 bounds check in check_wsl_eas()

In reply to Greg Kroah-Hartman

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

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

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

commit 3d8b9d06bd3ac4c6846f5498800b0f5f8062e53b upstream.

The bounds check uses (u8 *)ea + nlen + 1 + vlen as the end of the EA name and value, but ea_data sits at offset sizeof(struct smb2_file_full_ea_info) = 8 from ea, not at offset 0. The strncmp() later reads ea->ea_data[0..nlen-1] and the value bytes follow at ea_data[nlen+1..nlen+vlen], so the actual end is ea->ea_data + nlen + 1
+ vlen. Isn't pointer math fun?

The earlier check (u8 *)ea > end - sizeof(*ea) only guarantees the 8-byte header is in bounds, but since the last EA is placed within 8 bytes of the end of the response, the name and value bytes are read past the end of iov.

Fix this mess all up by using ea->ea_data as the base for the bounds check.

An "untrusted" server can use this to leak up to 8 bytes of kernel heap into the EA name comparison and influence which WSL xattr the data is interpreted as.

---
 fs/smb/client/smb2inode.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/smb/client/smb2inode.c +1 -1
@@ -125,7 +125,7 @@ static int check_wsl_eas(struct kvec *rs
 		nlen = ea->ea_name_length;
 		vlen = le16_to_cpu(ea->ea_value_length);
 		if (nlen != SMB2_WSL_XATTR_NAME_LEN ||
-		    (u8 *)ea + nlen + 1 + vlen > end)
+		    (u8 *)ea->ea_data + nlen + 1 + vlen > end)
 			return -EINVAL;
 
 		switch (vlen) {
author maintainer
#109 lore raw

PATCH 108/162 ksmbd: validate EaNameLength in smb2_get_ea()

In reply to Greg Kroah-Hartman

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

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

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

commit 66751841212c2cc196577453c37f7774ff363f02 upstream.

smb2_get_ea() reads ea_req->EaNameLength from the client request and passes it directly to strncmp() as the comparison length without verifying that the length of the name really is the size of the input buffer received.

Fix this up by properly checking the size of the name based on the value received and the overall size of the request, to prevent a later strncmp() call to use the length as a "trusted" size of the buffer. Without this check, uninitialized heap values might be slowly leaked to the client.

---
 fs/smb/server/smb2pdu.c |    5 +++++
 1 file changed, 5 insertions(+)
fs/smb/server/smb2pdu.c +5 -0
@@ -4728,6 +4728,11 @@ static int smb2_get_ea(struct ksmbd_work
 
 		ea_req = (struct smb2_ea_info_req *)((char *)req +
 						     le16_to_cpu(req->InputBufferOffset));
+
+		if (le32_to_cpu(req->InputBufferLength) <
+		    offsetof(struct smb2_ea_info_req, name) +
+		    ea_req->EaNameLength)
+			return -EINVAL;
 	} else {
 		/* need to send all EAs, if no specific EA is requested*/
 		if (le32_to_cpu(req->Flags) & SL_RETURN_SINGLE_ENTRY)
author maintainer
#110 lore raw

PATCH 109/162 ksmbd: require 3 sub-authorities before reading sub_auth[2]

In reply to Greg Kroah-Hartman

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

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

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

commit 53370cf9090777774e07fd9a8ebce67c6cc333ab upstream.

parse_dacl() compares each ACE SID against sid_unix_NFS_mode and on match reads sid.sub_auth[2] as the file mode. If sid_unix_NFS_mode is the prefix S-1-5-88-3 with num_subauth = 2 then compare_sids() compares only min(num_subauth, 2) sub-authorities so a client SID with num_subauth = 2 and sub_auth = {88, 3} will match.

If num_subauth = 2 and the ACE is placed at the very end of the security descriptor, sub_auth[2] will be 4 bytes past end_of_acl. The out-of-band bytes will then be masked to the low 9 bits and applied as the file's POSIX mode, probably not something that is good to have happen.

Fix this up by forcing the SID to actually carry a third sub-authority before reading it at all.

---
 fs/smb/server/smbacl.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
fs/smb/server/smbacl.c +2 -1
@@ -451,7 +451,8 @@ static void parse_dacl(struct mnt_idmap
 		ppace[i]->access_req =
 			smb_map_generic_desired_access(ppace[i]->access_req);
 
-		if (!(compare_sids(&ppace[i]->sid, &sid_unix_NFS_mode))) {
+		if (ppace[i]->sid.num_subauth >= 3 &&
+		    !(compare_sids(&ppace[i]->sid, &sid_unix_NFS_mode))) {
 			fattr->cf_mode =
 				le32_to_cpu(ppace[i]->sid.sub_auth[2]);
 			break;
author maintainer
#111 lore raw

PATCH 110/162 ksmbd: fix mechToken leak when SPNEGO decode fails after token alloc

In reply to Greg Kroah-Hartman

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

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

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

commit ad0057fb91218914d6c98268718ceb9d59b388e1 upstream.

The kernel ASN.1 BER decoder calls action callbacks incrementally as it walks the input. When ksmbd_decode_negTokenInit() reaches the mechToken
[2] OCTET STRING element, ksmbd_neg_token_alloc() allocates conn->mechToken immediately via kmemdup_nul(). If a later element in the same blob is malformed, then the decoder will return nonzero after the allocation is already live. This could happen if mechListMIC [3] overrunse the enclosing SEQUENCE.

decode_negotiation_token() then sets conn->use_spnego = false because both the negTokenInit and negTokenTarg grammars failed. The cleanup at the bottom of smb2_sess_setup() is gated on use_spnego:

	if (conn->use_spnego && conn->mechToken) {
		kfree(conn->mechToken);
		conn->mechToken = NULL;
	}

so the kfree is skipped, causing the mechToken to never be freed.

This codepath is reachable pre-authentication, so untrusted clients can cause slow memory leaks on a server without even being properly authenticated.

Fix this up by not checking check for use_spnego, as it's not required, so the memory will always be properly freed. At the same time, always free the memory in ksmbd_conn_free() incase some other failure path forgot to free it.

---
 fs/smb/server/connection.c |    1 +
 fs/smb/server/smb2pdu.c    |    2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)
fs/smb/server/connection.c +1 -0
@@ -39,6 +39,7 @@ void ksmbd_conn_free(struct ksmbd_conn *
 	xa_destroy(&conn->sessions);
 	kvfree(conn->request_buf);
 	kfree(conn->preauth_info);
+	kfree(conn->mechToken);
 	if (atomic_dec_and_test(&conn->refcnt)) {
 		conn->transport->ops->free_transport(conn->transport);
 		kfree(conn);
fs/smb/server/smb2pdu.c +1 -1
@@ -1921,7 +1921,7 @@ out_err:
 	else if (rc)
 		rsp->hdr.Status = STATUS_LOGON_FAILURE;
 
-	if (conn->use_spnego && conn->mechToken) {
+	if (conn->mechToken) {
 		kfree(conn->mechToken);
 		conn->mechToken = NULL;
 	}
author maintainer
#112 lore raw

PATCH 111/162 usbip: validate number_of_packets in usbip_pack_ret_submit()

In reply to Greg Kroah-Hartman

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

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

From: Nathan Rebello <[email protected]>

commit 2ab833a16a825373aad2ba7d54b572b277e95b71 upstream.

When a USB/IP client receives a RET_SUBMIT response, usbip_pack_ret_submit() unconditionally overwrites urb->number_of_packets from the network PDU. This value is subsequently used as the loop bound in usbip_recv_iso() and usbip_pad_iso() to iterate over urb->iso_frame_desc[], a flexible array whose size was fixed at URB allocation time based on the *original* number_of_packets from the CMD_SUBMIT.

A malicious USB/IP server can set number_of_packets in the response to a value larger than what was originally submitted, causing a heap out-of-bounds write when usbip_recv_iso() writes to urb->iso_frame_desc[i] beyond the allocated region.

KASAN confirmed this with kernel 7.0.0-rc5:

  BUG: KASAN: slab-out-of-bounds in usbip_recv_iso+0x46a/0x640
  Write of size 4 at addr ffff888106351d40 by task vhci_rx/69

The buggy address is located 0 bytes to the right of
allocated 320-byte region [ffff888106351c00, ffff888106351d40)

The server side (stub_rx.c) and gadget side (vudc_rx.c) already validate number_of_packets in the CMD_SUBMIT path since commits c6688ef9f297 ("usbip: fix stub_rx: harden CMD_SUBMIT path to handle malicious input") and b78d830f0049 ("usbip: fix vudc_rx: harden CMD_SUBMIT path to handle malicious input"). The server side validates against USBIP_MAX_ISO_PACKETS because no URB exists yet at that point. On the client side we have the original URB, so we can use the tighter
bound: the response must not exceed the original number_of_packets.

This mirrors the existing validation of actual_length against transfer_buffer_length in usbip_recv_xbuff(), which checks the response value against the original allocation size.

Kelvin Mbogo's series ("usb: usbip: fix integer overflow in usbip_recv_iso()", v2) hardens the receive-side functions themselves; this patch complements that work by catching the bad value at its source -- in usbip_pack_ret_submit() before the overwrite -- and using the tighter per-URB allocation bound rather than the global USBIP_MAX_ISO_PACKETS limit.

Fix this by checking rpdu->number_of_packets against urb->number_of_packets in usbip_pack_ret_submit() before the overwrite. On violation, clamp to zero so that usbip_recv_iso() and usbip_pad_iso() safely return early.

Fixes 1325f85fa49f ("staging: usbip: bugfix add number of packets for isochronous frames")
Cc stable <[email protected]>
---
 drivers/usb/usbip/usbip_common.c |   12 ++++++++++++
 1 file changed, 12 insertions(+)
drivers/usb/usbip/usbip_common.c +12 -0
@@ -470,6 +470,18 @@ static void usbip_pack_ret_submit(struct
 		urb->status		= rpdu->status;
 		urb->actual_length	= rpdu->actual_length;
 		urb->start_frame	= rpdu->start_frame;
+		/*
+		 * The number_of_packets field determines the length of
+		 * iso_frame_desc[], which is a flexible array allocated
+		 * at URB creation time. A response must never claim more
+		 * packets than originally submitted; doing so would cause
+		 * an out-of-bounds write in usbip_recv_iso() and
+		 * usbip_pad_iso(). Clamp to zero on violation so both
+		 * functions safely return early.
+		 */
+		if (rpdu->number_of_packets < 0 ||
+		    rpdu->number_of_packets > urb->number_of_packets)
+			rpdu->number_of_packets = 0;
 		urb->number_of_packets = rpdu->number_of_packets;
 		urb->error_count	= rpdu->error_count;
 	}
author maintainer
#113 lore raw

PATCH 112/162 usb: storage: Expand range of matched versions for VL817 quirks entry

In reply to Greg Kroah-Hartman

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

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

From: Daniel Brát <[email protected]>

commit 609865ab3d5d803556f628e221ecd3d06aed9f30 upstream.

Expands range of matched bcdDevice values for the VL817 quirk entry. This is based on experience with Axagon EE35-GTR rev1 3.5" HDD enclosure, which reports its bcdDevice as 0x0843, but presumably other vendors using this IC in their products may set it to any other value.

---
 drivers/usb/storage/unusual_devs.h |    7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/usb/storage/unusual_devs.h +4 -3
@@ -2350,10 +2350,11 @@ UNUSUAL_DEV(  0x2027, 0xa001, 0x0000, 0x
 		US_FL_SCM_MULT_TARG ),
 
 /*
- * Reported by DocMAX <[email protected]>
- * and Thomas Weißschuh <[email protected]>
+ * Reported by DocMAX <[email protected]>,
+ * Thomas Weißschuh <[email protected]>
+ * and Daniel Brát <[email protected]>
  */
-UNUSUAL_DEV( 0x2109, 0x0715, 0x9999, 0x9999,
+UNUSUAL_DEV( 0x2109, 0x0715, 0x0000, 0x9999,
 		"VIA Labs, Inc.",
 		"VL817 SATA Bridge",
 		USB_SC_DEVICE, USB_PR_DEVICE, NULL,
author maintainer
#114 lore raw

PATCH 113/162 USB: cdc-acm: Add quirks for Yoga Book 9 14IAH10 INGENIC touchscreen

In reply to Greg Kroah-Hartman

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

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

From: Dave Carey <[email protected]>

commit f58752ebcb35e156c85cd1a82d6579c7af3b9023 upstream.

The Lenovo Yoga Book 9 14IAH10 (83KJ) has a composite USB device (17EF:6161) that controls both touchscreens via a CDC ACM interface. Interface 0 is a standard CDC ACM control interface, but interface 1 (the data interface) incorrectly declares vendor-specific class (0xFF) instead of USB_CLASS_CDC_DATA. cdc-acm rejects the device at probe with -EINVAL, leaving interface 0 unbound and EP 0x82 never polled.

With no consumer polling EP 0x82, the firmware's watchdog fires every ~20 seconds and resets the USB bus, producing a continuous disconnect/ reconnect loop that prevents the touchscreens from ever initialising.

Add two new quirk flags:

VENDOR_CLASS_DATA_IFACE: Bypasses the bInterfaceClass check in acm_probe() that would otherwise reject the vendor-class data interface with -EINVAL.

ALWAYS_POLL_CTRL: Submits the notification URB at probe() rather than waiting for a TTY open. This keeps EP 0x82 polled at all times, permanently suppressing the firmware watchdog. The URB is resubmitted after port_shutdown() and on system resume. SET_CONTROL_LINE_STATE (DTR|RTS) is sent at probe and after port_shutdown() to complete firmware handshake.

Note: the firmware performs exactly 4 USB connect/disconnect cycles (~19 s each) on every cold boot before stabilising. This is a fixed firmware property; touch is available ~75-80 s after power-on.

---
 drivers/usb/class/cdc-acm.c |   53 ++++++++++++++++++++++++++++++++++++++------
 1 file changed, 46 insertions(+), 7 deletions(-)
drivers/usb/class/cdc-acm.c +46 -7
@@ -114,6 +114,8 @@ static int acm_ctrl_msg(struct acm *acm,
 	int retval;
 
 	retval = usb_autopm_get_interface(acm->control);
+#define VENDOR_CLASS_DATA_IFACE		BIT(9)  /* data interface uses vendor-specific class */
+#define ALWAYS_POLL_CTRL		BIT(10) /* keep ctrl URB active even without an open TTY */
 	if (retval)
 		return retval;
 
@@ -710,12 +712,14 @@ static int acm_port_activate(struct tty_
 	set_bit(TTY_NO_WRITE_SPLIT, &tty->flags);
 	acm->control->needs_remote_wakeup = 1;
 
-	acm->ctrlurb->dev = acm->dev;
-	retval = usb_submit_urb(acm->ctrlurb, GFP_KERNEL);
-	if (retval) {
-		dev_err(&acm->control->dev,
-			"%s - usb_submit_urb(ctrl irq) failed\n", __func__);
-		goto error_submit_urb;
+	if (!(acm->quirks & ALWAYS_POLL_CTRL)) {
+		acm->ctrlurb->dev = acm->dev;
+		retval = usb_submit_urb(acm->ctrlurb, GFP_KERNEL);
+		if (retval) {
+			dev_err(&acm->control->dev,
+				"%s - usb_submit_urb(ctrl irq) failed\n", __func__);
+			goto error_submit_urb;
+		}
 	}
 
 	acm_tty_set_termios(tty, NULL);
@@ -788,6 +792,14 @@ static void acm_port_shutdown(struct tty
 
 	acm_unpoison_urbs(acm);
 
+	if (acm->quirks & ALWAYS_POLL_CTRL) {
+		acm->ctrlurb->dev = acm->dev;
+		if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL))
+			dev_dbg(&acm->control->dev,
+				"ctrl polling restart failed after port close\n");
+		/* port_shutdown() cleared DTR/RTS; restore them */
+		acm_set_control(acm, USB_CDC_CTRL_DTR | USB_CDC_CTRL_RTS);
+	}
 }
 
 static void acm_tty_cleanup(struct tty_struct *tty)
@@ -1328,6 +1340,9 @@ skip_normal_probe:
 			dev_dbg(&intf->dev,
 				"Your device has switched interfaces.\n");
 			swap(control_interface, data_interface);
+		} else if (quirks & VENDOR_CLASS_DATA_IFACE) {
+			dev_dbg(&intf->dev,
+				"Vendor-specific data interface class, continuing.\n");
 		} else {
 			return -EINVAL;
 		}
@@ -1522,6 +1537,9 @@ skip_countries:
 	acm->line.bDataBits = 8;
 	acm_set_line(acm, &acm->line);
 
+	if (quirks & ALWAYS_POLL_CTRL)
+		acm_set_control(acm, USB_CDC_CTRL_DTR | USB_CDC_CTRL_RTS);
+
 	if (!acm->combined_interfaces) {
 		rv = usb_driver_claim_interface(&acm_driver, data_interface, acm);
 		if (rv)
@@ -1543,6 +1561,13 @@ skip_countries:
 
 	dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor);
 
+	if (acm->quirks & ALWAYS_POLL_CTRL) {
+		acm->ctrlurb->dev = acm->dev;
+		if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL))
+			dev_warn(&intf->dev,
+				 "failed to start persistent ctrl polling\n");
+	}
+
 	return 0;
 
 err_release_data_interface:
@@ -1669,7 +1694,7 @@ static int acm_resume(struct usb_interfa
 
 	acm_unpoison_urbs(acm);
 
-	if (tty_port_initialized(&acm->port)) {
+	if (tty_port_initialized(&acm->port) || (acm->quirks & ALWAYS_POLL_CTRL)) {
 		rv = usb_submit_urb(acm->ctrlurb, GFP_ATOMIC);
 
 		for (;;) {
@@ -2016,6 +2041,20 @@ static const struct usb_device_id acm_id
 	/* CH343 supports CAP_BRK, but doesn't advertise it */
 	{ USB_DEVICE(0x1a86, 0x55d3), .driver_info = MISSING_CAP_BRK, },
 
+	/*
+	 * Lenovo Yoga Book 9 14IAH10 (83KJ) — INGENIC 17EF:6161 touchscreen
+	 * composite device.  The CDC ACM control interface (0) uses a standard
+	 * Union descriptor, but the data interface (1) is declared as vendor-
+	 * specific class (0xff) with no CDC data descriptors, so cdc-acm would
+	 * normally reject it.  The firmware also requires continuous polling of
+	 * the notification endpoint (EP 0x82) to suppress a 20-second watchdog
+	 * reset; ALWAYS_POLL_CTRL keeps the ctrlurb active even when no TTY is
+	 * open.  Match only the control interface by class to avoid probing the
+	 * vendor-specific data interface.
+	 */
+	{ USB_DEVICE_INTERFACE_CLASS(0x17ef, 0x6161, USB_CLASS_COMM),
+	  .driver_info = VENDOR_CLASS_DATA_IFACE | ALWAYS_POLL_CTRL },
+
 	/* control interfaces without any protocol set */
 	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
 		USB_CDC_PROTO_NONE) },
author maintainer
#115 lore raw

PATCH 114/162 usb: gadget: f_hid: dont call cdev_init while cdev in use

In reply to Greg Kroah-Hartman

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

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

From: Michael Zimmermann <[email protected]>

commit 81ebd43cc0d6d106ce7b6ccbf7b5e40ca7f5503d upstream.

When calling unbind, then bind again, cdev_init reinitialized the cdev, even though there may still be references to it. That's the case when the /dev/hidg* device is still opened. This obviously unsafe behavior like oopes.

This fixes this by using cdev_alloc to put the cdev on the heap. That way, we can simply allocate a new one in hidg_bind.

---
 drivers/usb/gadget/function/f_hid.c |   15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)
drivers/usb/gadget/function/f_hid.c +10 -5
@@ -103,7 +103,7 @@ struct f_hidg {
 	struct list_head		report_list;
 
 	struct device			dev;
-	struct cdev			cdev;
+	struct cdev			*cdev;
 	struct usb_function		func;
 
 	struct usb_ep			*in_ep;
@@ -764,8 +764,9 @@ static int f_hidg_release(struct inode *
 
 static int f_hidg_open(struct inode *inode, struct file *fd)
 {
+	struct kobject *parent = inode->i_cdev->kobj.parent;
 	struct f_hidg *hidg =
-		container_of(inode->i_cdev, struct f_hidg, cdev);
+		container_of(parent, struct f_hidg, dev.kobj);
 
 	fd->private_data = hidg;
 
@@ -1270,8 +1271,12 @@ static int hidg_bind(struct usb_configur
 	}
 
 	/* create char device */
-	cdev_init(&hidg->cdev, &f_hidg_fops);
-	status = cdev_device_add(&hidg->cdev, &hidg->dev);
+	hidg->cdev = cdev_alloc();
+	if (!hidg->cdev)
+		goto fail_free_all;
+	hidg->cdev->ops = &f_hidg_fops;
+
+	status = cdev_device_add(hidg->cdev, &hidg->dev);
 	if (status)
 		goto fail_free_all;
 
@@ -1521,7 +1526,7 @@ static void hidg_unbind(struct usb_confi
 {
 	struct f_hidg *hidg = func_to_hidg(f);
 
-	cdev_device_del(&hidg->cdev, &hidg->dev);
+	cdev_device_del(hidg->cdev, &hidg->dev);
 	destroy_workqueue(hidg->workqueue);
 	usb_free_all_descriptors(f);
 }
author maintainer
#116 lore raw

PATCH 115/162 usb: port: add delay after usb_hub_set_port_power()

In reply to Greg Kroah-Hartman

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

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

From: Xu Yang <[email protected]>

commit b84cc80610a8ce036deb987f056ce3196ead7f1e upstream.

When a port is disabled, an attached device will be disconnected. This causes a port-status-change event, which will race with hub autosuspend (if the disabled port was the only connected port on its hub), causing an immediate resume and a second autosuspend. Both of these can be avoided by adding a short delay after the call to usb_hub_set_port_power().

Below log shows what is happening:

$ echo 1 > usb1-port1/disable
[   37.958239] usb 1-1: USB disconnect, device number 2
[   37.964101] usb 1-1: unregistering device
[   37.970070] hub 1-0:1.0: hub_suspend
[   37.971305] hub 1-0:1.0: state 7 ports 1 chg 0000 evt 0002
[   37.974412] usb usb1: bus auto-suspend, wakeup 1
[   37.988175] usb usb1: suspend raced with wakeup event         <---
[   37.993947] usb usb1: usb auto-resume
[   37.998401] hub 1-0:1.0: hub_resume
[   38.105688] usb usb1-port1: status 0000, change 0000, 12 Mb/s
[   38.112399] hub 1-0:1.0: state 7 ports 1 chg 0000 evt 0000
[   38.118645] hub 1-0:1.0: hub_suspend
[   38.122963] usb usb1: bus auto-suspend, wakeup 1
[   38.200368] usb usb1: usb wakeup-resume
[   38.204982] usb usb1: usb auto-resume
[   38.209376] hub 1-0:1.0: hub_resume
[   38.213676] usb usb1-port1: status 0101 change 0001
[   38.321552] hub 1-0:1.0: state 7 ports 1 chg 0002 evt 0000
[   38.327978] usb usb1-port1: status 0101, change 0000, 12 Mb/s
[   38.457429] usb 1-1: new high-speed USB device number 3 using ci_hdrc

Then, port change bit will be fixed to the final state and usb_clear_port_feature() can correctly clear it after this period. This will also avoid usb runtime suspend routine to run because usb_autopm_put_interface() not run yet.

Fixes f061f43d7418 ("usb: hub: port: add sysfs entry to switch port power")
---
 drivers/usb/core/port.c |    1 +
 1 file changed, 1 insertion(+)
drivers/usb/core/port.c +1 -0
@@ -139,6 +139,7 @@ static ssize_t disable_store(struct devi
 		usb_disconnect(&port_dev->child);
 
 	rc = usb_hub_set_port_power(hdev, hub, port1, !disabled);
+	msleep(2 * hub_power_on_good_delay(hub));
 
 	if (disabled) {
 		usb_clear_port_feature(hdev, port1, USB_PORT_FEAT_C_CONNECTION);
author maintainer
#117 lore raw

PATCH 116/162 fbdev: udlfb: avoid divide-by-zero on FBIOPUT_VSCREENINFO

In reply to Greg Kroah-Hartman

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

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

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

commit a31e4518bec70333a0a98f2946a12b53b45fe5b9 upstream.

Much like commit 19f953e74356 ("fbdev: fb_pm2fb: Avoid potential divide by zero error"), we also need to prevent that same crash from happening in the udlfb driver as it uses pixclock directly when dividing, which will crash.

Cc Bernie Thompson <[email protected]>
Cc Helge Deller <[email protected]>
Fixes 59277b679f8b ("Staging: udlfb: add dynamic modeset support")
Assisted-by gregkh_clanker_t1000
---
 drivers/video/fbdev/udlfb.c |    3 +++
 1 file changed, 3 insertions(+)
drivers/video/fbdev/udlfb.c +3 -0
@@ -1018,6 +1018,9 @@ static int dlfb_ops_check_var(struct fb_
 	struct fb_videomode mode;
 	struct dlfb_data *dlfb = info->par;
 
+	if (!var->pixclock)
+		return -EINVAL;
+
 	/* set device-specific elements of var unrelated to mode */
 	dlfb_var_color_format(var);
 
author maintainer
#118 lore raw

PATCH 117/162 scripts: generate_rust_analyzer.py: avoid FD leak

In reply to Greg Kroah-Hartman

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

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

From: Tamir Duberstein <[email protected]>

commit 9b4744d8eda2824041064a5639ccbb079850914d upstream.

Use pathlib.Path.read_text() to avoid leaking file descriptors.

---
 scripts/generate_rust_analyzer.py |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
scripts/generate_rust_analyzer.py +2 -1
@@ -146,9 +146,10 @@ def generate_crates(srctree, objtree, sy
 
     def is_root_crate(build_file, target):
         try:
-            return f"{target}.o" in open(build_file).read()
+            contents = build_file.read_text()
         except FileNotFoundError:
             return False
+        return f"{target}.o" in contents
 
     # Then, the rest outside of `rust/`.
     #
author maintainer
#119 lore raw

PATCH 118/162 wifi: rtw88: fix device leak on probe failure

In reply to Greg Kroah-Hartman

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

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

From: Johan Hovold <[email protected]>

commit bbb15e71156cd9f5e1869eee7207a06ea8e96c39 upstream.

Driver core holds a reference to the USB interface and its parent USB device while the interface is bound to a driver and there is no need to take additional references unless the structures are needed after disconnect.

This driver takes a reference to the USB device during probe but does not to release it on all probe errors (e.g. when descriptor parsing fails).

Drop the redundant device reference to fix the leak, reduce cargo culting, make it easier to spot drivers where an extra reference is needed, and reduce the risk of further memory leaks.

---
 drivers/net/wireless/realtek/rtw88/usb.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/net/wireless/realtek/rtw88/usb.c +1 -2
@@ -953,7 +953,7 @@ static int rtw_usb_intf_init(struct rtw_
 			     struct usb_interface *intf)
 {
 	struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
-	struct usb_device *udev = usb_get_dev(interface_to_usbdev(intf));
+	struct usb_device *udev = interface_to_usbdev(intf);
 	int ret;
 
 	rtwusb->udev = udev;
@@ -979,7 +979,6 @@ static void rtw_usb_intf_deinit(struct r
 {
 	struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
 
-	usb_put_dev(rtwusb->udev);
 	kfree(rtwusb->usb_data);
 	usb_set_intfdata(intf, NULL);
 }
author maintainer
#120 lore raw

PATCH 119/162 staging: sm750fb: fix division by zero in ps_to_hz()

In reply to Greg Kroah-Hartman

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

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

From: Junrui Luo <[email protected]>

commit 75a1621e4f91310673c9acbcbb25c2a7ff821cd3 upstream.

ps_to_hz() is called from hw_sm750_crtc_set_mode() without validating that pixclock is non-zero. A zero pixclock passed via FBIOPUT_VSCREENINFO causes a division by zero.

Fix by rejecting zero pixclock in lynxfb_ops_check_var(), consistent with other framebuffer drivers.

---
 drivers/staging/sm750fb/sm750.c |    3 +++
 1 file changed, 3 insertions(+)
drivers/staging/sm750fb/sm750.c +3 -0
@@ -483,6 +483,9 @@ static int lynxfb_ops_check_var(struct f
 	struct lynxfb_crtc *crtc;
 	resource_size_t request;
 
+	if (!var->pixclock)
+		return -EINVAL;
+
 	ret = 0;
 	par = info->par;
 	crtc = &par->crtc;
author maintainer
#121 lore raw

PATCH 120/162 USB: serial: option: add Telit Cinterion FN990A MBIM composition

In reply to Greg Kroah-Hartman

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

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

From: Fabio Porcedda <[email protected]>

commit f8cc59ecc22841be5deb07b549c0c6a2657cd5f9 upstream.

Add the following Telit Cinterion FN990A MBIM composition:

0x1074: MBIM + tty (AT/NMEA) + tty (AT) + tty (AT) + tty (diag) +
DPL (Data Packet Logging) + adb

T:  Bus=01 Lev=01 Prnt=04 Port=06 Cnt=01 Dev#=  7 Spd=480  MxCh= 0
D:  Ver= 2.10 Cls=ef(misc ) Sub=02 Prot=01 MxPS=64 #Cfgs=  1
P:  Vendor=1bc7 ProdID=1074 Rev=05.04
S:  Manufacturer=Telit Wireless Solutions
S:  Product=FN990
S:  SerialNumber=70628d0c
C:  #Ifs= 8 Cfg#= 1 Atr=e0 MxPwr=500mA
I:  If#= 0 Alt= 0 #EPs= 1 Cls=02(commc) Sub=0e Prot=00 Driver=cdc_mbim
E:  Ad=81(I) Atr=03(Int.) MxPS=  64 Ivl=32ms
I:  If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim
E:  Ad=0f(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=8e(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:  If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=60 Driver=option
E:  Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=83(I) Atr=03(Int.) MxPS=  10 Ivl=32ms
I:  If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option
E:  Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=85(I) Atr=03(Int.) MxPS=  10 Ivl=32ms
I:  If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option
E:  Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=87(I) Atr=03(Int.) MxPS=  10 Ivl=32ms
I:  If#= 5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option
E:  Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=88(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:  If#= 6 Alt= 0 #EPs= 1 Cls=ff(vend.) Sub=ff Prot=80 Driver=(none)
E:  Ad=8f(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
I:  If#= 7 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none)
E:  Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=89(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
---
 drivers/usb/serial/option.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/usb/serial/option.c +2 -0
@@ -1383,6 +1383,8 @@ static const struct usb_device_id option
 	  .driver_info = NCTRL(2) | RSVD(3) },
 	{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1073, 0xff),	/* Telit FN990A (ECM) */
 	  .driver_info = NCTRL(0) | RSVD(1) },
+	{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1074, 0xff),	/* Telit FN990A (MBIM) */
+	  .driver_info = NCTRL(5) | RSVD(6) | RSVD(7) },
 	{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1075, 0xff),	/* Telit FN990A (PCIe) */
 	  .driver_info = RSVD(0) },
 	{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1077, 0xff),	/* Telit FN990A (rmnet + audio) */
author maintainer
#122 lore raw

PATCH 121/162 Docs/admin-guide/mm/damon/reclaim: warn commit_inputs vs param updates race

In reply to Greg Kroah-Hartman

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

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

From: SeongJae Park <[email protected]>

commit 0beba407d4585a15b0dc09f2064b5b3ddcb0e857 upstream.

Patch series "Docs/admin-guide/mm/damon: warn commit_inputs vs other params race".

Writing 'Y' to the commit_inputs parameter of DAMON_RECLAIM and DAMON_LRU_SORT, and writing other parameters before the commit_inputs request is completely processed can cause race conditions. While the consequence can be bad, the documentation is not clearly describing that. Add clear warnings.

The issue was discovered [1,2] by sashiko.

This patch (of 2):

DAMON_RECLAIM handles commit_inputs request inside kdamond thread, reading the module parameters. If the user updates the module parameters while the kdamond thread is reading those, races can happen. To avoid this, the commit_inputs parameter shows whether it is still in the progress, assuming users wouldn't update parameters in the middle of the work. Some users might ignore that. Add a warning about the behavior.

The issue was discovered in [1] by sashiko.

---
 Documentation/admin-guide/mm/damon/reclaim.rst |    4 ++++
 1 file changed, 4 insertions(+)
Documentation/admin-guide/mm/damon/reclaim.rst +4 -0
@@ -71,6 +71,10 @@ of parametrs except ``enabled`` again.
 parameter is set as ``N``.  If invalid parameters are found while the
 re-reading, DAMON_RECLAIM will be disabled.
 
+Once ``Y`` is written to this parameter, the user must not write to any
+parameters until reading ``commit_inputs`` again returns ``N``.  If users
+violate this rule, the kernel may exhibit undefined behavior.
+
 min_age
 -------
 
author maintainer
#123 lore raw

PATCH 122/162 ALSA: ctxfi: Limit PTP to a single page

In reply to Greg Kroah-Hartman

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

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

From: Harin Lee <[email protected]>

commit e9418da50d9e5c496c22fe392e4ad74c038a94eb upstream.

Commit 391e69143d0a increased CT_PTP_NUM from 1 to 4 to support 256 playback streams, but the additional pages are not used by the card correctly. The CT20K2 hardware already has multiple VMEM_PTPAL registers, but using them separately would require refactoring the entire virtual memory allocation logic.

ct_vm_map() always uses PTEs in vm->ptp[0].area regardless of CT_PTP_NUM. On AMD64 systems, a single PTP covers 512 PTEs (2M). When aggregate memory allocations exceed this limit, ct_vm_map() tries to access beyond the allocated space and causes a page fault:

  BUG: unable to handle page fault for address: ffffd4ae8a10a000
  Oops: Oops: 0002 [#1] SMP PTI
  RIP: 0010:ct_vm_map+0x17c/0x280 [snd_ctxfi]
  Call Trace:
  atc_pcm_playback_prepare+0x225/0x3b0
  ct_pcm_playback_prepare+0x38/0x60
  snd_pcm_do_prepare+0x2f/0x50
  snd_pcm_action_single+0x36/0x90
  snd_pcm_action_nonatomic+0xbf/0xd0
  snd_pcm_ioctl+0x28/0x40
  __x64_sys_ioctl+0x97/0xe0
  do_syscall_64+0x81/0x610
  entry_SYSCALL_64_after_hwframe+0x76/0x7e

Revert CT_PTP_NUM to 1. The 256 SRC_RESOURCE_NUM and playback_count remain unchanged.

Fixes 391e69143d0a ("ALSA: ctxfi: Bump playback substreams to 256")
---
 sound/pci/ctxfi/ctvmem.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
sound/pci/ctxfi/ctvmem.h +1 -1
@@ -15,7 +15,7 @@
 #ifndef CTVMEM_H
 #define CTVMEM_H
 
-#define CT_PTP_NUM	4	/* num of device page table pages */
+#define CT_PTP_NUM	1	/* num of device page table pages */
 
 #include <linux/mutex.h>
 #include <linux/list.h>
author maintainer
#124 lore raw

PATCH 123/162 dcache: Limit the minimal number of bucket to two

In reply to Greg Kroah-Hartman

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

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

From: Zhihao Cheng <[email protected]>

commit f08fe8891c3eeb63b73f9f1f6d97aa629c821579 upstream.

There is an OOB read problem on dentry_hashtable when user sets 'dhash_entries=1':

  BUG: unable to handle page fault for address: ffff888b30b774b0
  #PF: supervisor read access in kernel mode
  #PF: error_code(0x0000) - not-present page
  Oops: Oops: 0000 [#1] SMP PTI
  RIP: 0010:__d_lookup+0x56/0x120
   Call Trace:
    d_lookup.cold+0x16/0x5d
    lookup_dcache+0x27/0xf0
    lookup_one_qstr_excl+0x2a/0x180
    start_dirop+0x55/0xa0
    simple_start_creating+0x8d/0xa0
    debugfs_start_creating+0x8c/0x180
    debugfs_create_dir+0x1d/0x1c0
    pinctrl_init+0x6d/0x140
    do_one_initcall+0x6d/0x3d0
    kernel_init_freeable+0x39f/0x460
    kernel_init+0x2a/0x260

There will be only one bucket in dentry_hashtable when dhash_entries is set as one, and d_hash_shift is calculated as 32 by dcache_init(). Then, following process will access more than one buckets(which memory region is not allocated) in dentry_hashtable:
d_lookup
b = d_hash(hash)

    dentry_hashtable + ((u32)hashlen >> d_hash_shift)
    // The C standard defines the behavior of right shift amounts
    // exceeding the bit width of the operand as undefined. The
    // result of '(u32)hashlen >> d_hash_shift' becomes 'hashlen',
    // so 'b' will point to an unallocated memory region.
  hlist_bl_for_each_entry_rcu(b)
   hlist_bl_first_rcu(head)
    h->first  // read OOB!

Fix it by limiting the minimal number of dentry_hashtable bucket to two, so that 'd_hash_shift' won't exceeds the bit width of type u32.

---
 fs/dcache.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
fs/dcache.c +2 -2
@@ -3127,7 +3127,7 @@ static void __init dcache_init_early(voi
 					HASH_EARLY | HASH_ZERO,
 					&d_hash_shift,
 					NULL,
-					0,
+					2,
 					0);
 	d_hash_shift = 32 - d_hash_shift;
 
@@ -3158,7 +3158,7 @@ static void __init dcache_init(void)
 					HASH_ZERO,
 					&d_hash_shift,
 					NULL,
-					0,
+					2,
 					0);
 	d_hash_shift = 32 - d_hash_shift;
 
author maintainer
#125 lore raw

PATCH 124/162 media: vidtv: fix NULL pointer dereference in vidtv_channel_pmt_match_sections

In reply to Greg Kroah-Hartman

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

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

From: Ruslan Valiyev <[email protected]>

commit f8e1fc918a9fe67103bcda01d20d745f264d00a7 upstream.

syzbot reported a general protection fault in vidtv_psi_desc_assign [1].

vidtv_psi_pmt_stream_init() can return NULL on memory allocation failure, but vidtv_channel_pmt_match_sections() does not check for this. When tail is NULL, the subsequent call to vidtv_psi_desc_assign(&tail->descriptor, desc) dereferences a NULL pointer offset, causing a general protection fault.

Add a NULL check after vidtv_psi_pmt_stream_init(). On failure, clean up the already-allocated stream chain and return.

[1]

Oops: general protection fault, probably for non-canonical address 0xdffffc0000000000: 0000 [#1] SMP KASAN PTI
KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
RIP: 0010:vidtv_psi_desc_assign+0x24/0x90 drivers/media/test-drivers/vidtv/vidtv_psi.c:629
Call Trace:
 <TASK>
 vidtv_channel_pmt_match_sections drivers/media/test-drivers/vidtv/vidtv_channel.c:349 [inline]
 vidtv_channel_si_init+0x1445/0x1a50 drivers/media/test-drivers/vidtv/vidtv_channel.c:479
 vidtv_mux_init+0x526/0xbe0 drivers/media/test-drivers/vidtv/vidtv_mux.c:519
 vidtv_start_streaming drivers/media/test-drivers/vidtv/vidtv_bridge.c:194 [inline]
 vidtv_start_feed+0x33e/0x4d0 drivers/media/test-drivers/vidtv/vidtv_bridge.c:239
---
 drivers/media/test-drivers/vidtv/vidtv_channel.c |    4 ++++
 1 file changed, 4 insertions(+)
drivers/media/test-drivers/vidtv/vidtv_channel.c +4 -0
@@ -341,6 +341,10 @@ vidtv_channel_pmt_match_sections(struct
 					tail = vidtv_psi_pmt_stream_init(tail,
 									 s->type,
 									 e_pid);
+					if (!tail) {
+						vidtv_psi_pmt_stream_destroy(head);
+						return;
+					}
 
 					if (!head)
 						head = tail;
author maintainer
#126 lore raw

PATCH 125/162 ocfs2: fix possible deadlock between unlink and dio_end_io_write

In reply to Greg Kroah-Hartman

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

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

From: Joseph Qi <[email protected]>

commit b02da26a992db0c0e2559acbda0fc48d4a2fd337 upstream.

ocfs2_unlink takes orphan dir inode_lock first and then ip_alloc_sem, while in ocfs2_dio_end_io_write, it acquires these locks in reverse order. This creates an ABBA lock ordering violation on lock classes ocfs2_sysfile_lock_key[ORPHAN_DIR_SYSTEM_INODE] and ocfs2_file_ip_alloc_sem_key.

Lock Chain #0 (orphan dir inode_lock -> ip_alloc_sem):
ocfs2_unlink
ocfs2_prepare_orphan_dir
ocfs2_lookup_lock_orphan_dir
inode_lock(orphan_dir_inode) <- lock A
__ocfs2_prepare_orphan_dir
ocfs2_prepare_dir_for_insert
ocfs2_extend_dir
ocfs2_expand_inline_dir
down_write(&oi->ip_alloc_sem) <- Lock B

Lock Chain #1 (ip_alloc_sem -> orphan dir inode_lock):
ocfs2_dio_end_io_write
down_write(&oi->ip_alloc_sem) <- Lock B ocfs2_del_inode_from_orphan()
inode_lock(orphan_dir_inode) <- Lock A

Deadlock Scenario:
CPU0 (unlink) CPU1 (dio_end_io_write)
------ ------
inode_lock(orphan_dir_inode)
down_write(ip_alloc_sem)
down_write(ip_alloc_sem)
inode_lock(orphan_dir_inode)

Since ip_alloc_sem is to protect allocation changes, which is unrelated with operations in ocfs2_del_inode_from_orphan. So move ocfs2_del_inode_from_orphan out of ip_alloc_sem to fix the deadlock.

Reported-by [email protected]
Fixes a86a72a4a4e0 ("ocfs2: take ip_alloc_sem in ocfs2_dio_get_block & ocfs2_dio_end_io_write")
Cc Mark Fasheh <[email protected]>
Cc Joel Becker <[email protected]>
Cc Junxiao Bi <[email protected]>
Cc Joseph Qi <[email protected]>
Cc Changwei Ge <[email protected]>
Cc Jun Piao <[email protected]>
---
 fs/ocfs2/aops.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
fs/ocfs2/aops.c +1 -2
@@ -2318,8 +2318,6 @@ static int ocfs2_dio_end_io_write(struct
 		goto out;
 	}
 
-	down_write(&oi->ip_alloc_sem);
-
 	/* Delete orphan before acquire i_rwsem. */
 	if (dwc->dw_orphaned) {
 		BUG_ON(dwc->dw_writer_pid != task_pid_nr(current));
@@ -2332,6 +2330,7 @@ static int ocfs2_dio_end_io_write(struct
 			mlog_errno(ret);
 	}
 
+	down_write(&oi->ip_alloc_sem);
 	di = (struct ocfs2_dinode *)di_bh->b_data;
 
 	ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), di_bh);
author maintainer
#127 lore raw

PATCH 126/162 ocfs2: fix use-after-free in ocfs2_fault() when VM_FAULT_RETRY

In reply to Greg Kroah-Hartman

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

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

From: Tejas Bharambe <[email protected]>

commit 7de554cabf160e331e4442e2a9ad874ca9875921 upstream.

filemap_fault() may drop the mmap_lock before returning VM_FAULT_RETRY, as documented in mm/filemap.c:

"If our return value has VM_FAULT_RETRY set, it's because the mmap_lock may be dropped before doing I/O or by lock_folio_maybe_drop_mmap()."

When this happens, a concurrent munmap() can call remove_vma() and free the vm_area_struct via RCU. The saved 'vma' pointer in ocfs2_fault() then becomes a dangling pointer, and the subsequent trace_ocfs2_fault() call dereferences it -- a use-after-free.

Fix this by saving ip_blkno as a plain integer before calling filemap_fault(), and removing vma from the trace event. Since ip_blkno is copied by value before the lock can be dropped, it remains valid regardless of what happens to the vma or inode afterward.

---
 fs/ocfs2/mmap.c        |    7 +++----
 fs/ocfs2/ocfs2_trace.h |   10 ++++------
 2 files changed, 7 insertions(+), 10 deletions(-)
fs/ocfs2/mmap.c +3 -4
@@ -30,7 +30,8 @@
 
 static vm_fault_t ocfs2_fault(struct vm_fault *vmf)
 {
-	struct vm_area_struct *vma = vmf->vma;
+	unsigned long long ip_blkno =
+		OCFS2_I(file_inode(vmf->vma->vm_file))->ip_blkno;
 	sigset_t oldset;
 	vm_fault_t ret;
 
@@ -38,11 +39,9 @@ static vm_fault_t ocfs2_fault(struct vm_
 	ret = filemap_fault(vmf);
 	ocfs2_unblock_signals(&oldset);
 
-	trace_ocfs2_fault(OCFS2_I(vma->vm_file->f_mapping->host)->ip_blkno,
-			  vma, vmf->page, vmf->pgoff);
+	trace_ocfs2_fault(ip_blkno, vmf->page, vmf->pgoff);
 	return ret;
 }
-
 static vm_fault_t __ocfs2_page_mkwrite(struct file *file,
 			struct buffer_head *di_bh, struct page *page)
 {
fs/ocfs2/ocfs2_trace.h +4 -6
@@ -1246,22 +1246,20 @@ TRACE_EVENT(ocfs2_write_end_inline,
 
 TRACE_EVENT(ocfs2_fault,
 	TP_PROTO(unsigned long long ino,
-		 void *area, void *page, unsigned long pgoff),
-	TP_ARGS(ino, area, page, pgoff),
+		 void *page, unsigned long pgoff),
+	TP_ARGS(ino, page, pgoff),
 	TP_STRUCT__entry(
 		__field(unsigned long long, ino)
-		__field(void *, area)
 		__field(void *, page)
 		__field(unsigned long, pgoff)
 	),
 	TP_fast_assign(
 		__entry->ino = ino;
-		__entry->area = area;
 		__entry->page = page;
 		__entry->pgoff = pgoff;
 	),
-	TP_printk("%llu %p %p %lu",
-		  __entry->ino, __entry->area, __entry->page, __entry->pgoff)
+	TP_printk("%llu %p %lu",
+		  __entry->ino, __entry->page, __entry->pgoff)
 );
 
 /* End of trace events for fs/ocfs2/mmap.c. */
author maintainer
#128 lore raw

PATCH 127/162 ocfs2: handle invalid dinode in ocfs2_group_extend

In reply to Greg Kroah-Hartman

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

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

From: ZhengYuan Huang <[email protected]>

commit 4a1c0ddc6e7bcf2e9db0eeaab9340dcfe97f448f upstream.

[BUG]
kernel BUG at fs/ocfs2/resize.c:308!

Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI
RIP: 0010:ocfs2_group_extend+0x10aa/0x1ae0 fs/ocfs2/resize.c:308
Code: 8b8520ff ffff83f8 860f8580 030000e8 5cc3c1fe
Call Trace:
 ...
 ocfs2_ioctl+0x175/0x6e0 fs/ocfs2/ioctl.c:869
 vfs_ioctl fs/ioctl.c:51 [inline]
 __do_sys_ioctl fs/ioctl.c:597 [inline]
 __se_sys_ioctl fs/ioctl.c:583 [inline]
 __x64_sys_ioctl+0x197/0x1e0 fs/ioctl.c:583
 x64_sys_call+0x1144/0x26a0 arch/x86/include/generated/asm/syscalls_64.h:17
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0x93/0xf80 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x76/0x7e
 ...

[CAUSE]
ocfs2_group_extend() assumes that the global bitmap inode block returned from ocfs2_inode_lock() has already been validated and BUG_ONs when the signature is not a dinode. That assumption is too strong for crafted filesystems because the JBD2-managed buffer path can bypass structural validation and return an invalid dinode to the resize ioctl.

[FIX]
Validate the dinode explicitly in ocfs2_group_extend(). If the global bitmap buffer does not contain a valid dinode, report filesystem corruption with ocfs2_error() and fail the resize operation instead of crashing the kernel.

Fixes 10995aa2451a ("ocfs2: Morph the haphazard OCFS2_IS_VALID_DINODE() checks.")
Cc Mark Fasheh <[email protected]>
Cc Joel Becker <[email protected]>
Cc Junxiao Bi <[email protected]>
Cc Changwei Ge <[email protected]>
Cc Jun Piao <[email protected]>
Cc Heming Zhao <[email protected]>
---
 fs/ocfs2/resize.c |   10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
fs/ocfs2/resize.c +7 -3
@@ -303,9 +303,13 @@ int ocfs2_group_extend(struct inode * in
 
 	fe = (struct ocfs2_dinode *)main_bm_bh->b_data;
 
-	/* main_bm_bh is validated by inode read inside ocfs2_inode_lock(),
-	 * so any corruption is a code bug. */
-	BUG_ON(!OCFS2_IS_VALID_DINODE(fe));
+	/* JBD-managed buffers can bypass validation, so treat this as corruption. */
+	if (!OCFS2_IS_VALID_DINODE(fe)) {
+		ret = ocfs2_error(main_bm_inode->i_sb,
+				  "Invalid dinode #%llu\n",
+				  (unsigned long long)OCFS2_I(main_bm_inode)->ip_blkno);
+		goto out_unlock;
+	}
 
 	if (le16_to_cpu(fe->id2.i_chain.cl_cpg) !=
 		ocfs2_group_bitmap_size(osb->sb, 0,
author maintainer
#129 lore raw

PATCH 128/162 PCI: endpoint: pci-epf-vntb: Stop cmd_handler work in epf_ntb_epc_cleanup

In reply to Greg Kroah-Hartman

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

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

From: Koichiro Den <[email protected]>

commit d799984233a50abd2667a7d17a9a710a3f10ebe2 upstream.

Disable the delayed work before clearing BAR mappings and doorbells to avoid running the handler after resources have been torn down.

  Unable to handle kernel paging request at virtual address ffff800083f46004
  [...]
  Internal error: Oops: 0000000096000007 [#1]  SMP
  [...]
  Call trace:
   epf_ntb_cmd_handler+0x54/0x200 [pci_epf_vntb] (P)
   process_one_work+0x154/0x3b0
   worker_thread+0x2c8/0x400
   kthread+0x148/0x210
   ret_from_fork+0x10/0x20
---
 drivers/pci/endpoint/functions/pci-epf-vntb.c |    1 +
 1 file changed, 1 insertion(+)
drivers/pci/endpoint/functions/pci-epf-vntb.c +1 -0
@@ -799,6 +799,7 @@ err_config_interrupt:
  */
 static void epf_ntb_epc_cleanup(struct epf_ntb *ntb)
 {
+	disable_delayed_work_sync(&ntb->cmd_handler);
 	epf_ntb_mw_bar_clear(ntb, ntb->num_mws);
 	epf_ntb_db_bar_clear(ntb);
 	epf_ntb_config_sspad_bar_clear(ntb);
author maintainer
#130 lore raw

PATCH 129/162 KVM: SEV: Reject attempts to sync VMSA of an already-launched/encrypted vCPU

In reply to Greg Kroah-Hartman

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

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

From: Sean Christopherson <[email protected]>

commit 9b9f7962e3e879d12da2bf47e02a24ec51690e3d upstream.

Reject synchronizing vCPU state to its associated VMSA if the vCPU has already been launched, i.e. if the VMSA has already been encrypted. On a host with SNP enabled, accessing guest-private memory generates an RMP #PF and panics the host.

  BUG: unable to handle page fault for address: ff1276cbfdf36000
  #PF: supervisor write access in kernel mode
  #PF: error_code(0x80000003) - RMP violation
  PGD 5a31801067 P4D 5a31802067 PUD 40ccfb5063 PMD 40e5954063 PTE 80000040fdf36163
  SEV-SNP: PFN 0x40fdf36, RMP entry: [0x6010fffffffff001 - 0x000000000000001f]
  Oops: Oops: 0003 [#1] SMP NOPTI
  CPU: 33 UID: 0 PID: 996180 Comm: qemu-system-x86 Tainted: G           OE
  Tainted: [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
  Hardware name: Dell Inc. PowerEdge R7625/0H1TJT, BIOS 1.5.8 07/21/2023
  RIP: 0010:sev_es_sync_vmsa+0x54/0x4c0 [kvm_amd]
  Call Trace:
   <TASK>
   snp_launch_update_vmsa+0x19d/0x290 [kvm_amd]
   snp_launch_finish+0xb6/0x380 [kvm_amd]
   sev_mem_enc_ioctl+0x14e/0x720 [kvm_amd]
   kvm_arch_vm_ioctl+0x837/0xcf0 [kvm]
   kvm_vm_ioctl+0x3fd/0xcc0 [kvm]
   __x64_sys_ioctl+0xa3/0x100
   x64_sys_call+0xfe0/0x2350
   do_syscall_64+0x81/0x10f0
   entry_SYSCALL_64_after_hwframe+0x76/0x7e
  RIP: 0033:0x7ffff673287d
   </TASK>

Note, the KVM flaw has been present since commit ad73109ae7ec ("KVM: SVM:
Provide support to launch and run an SEV-ES guest"), but has only been actively dangerous for the host since SNP support was added. With SEV-ES, KVM would "just" clobber guest state, which is totally fine from a host kernel perspective since userspace can clobber guest state any time before sev_launch_update_vmsa().

---
 arch/x86/kvm/svm/sev.c |    3 +++
 1 file changed, 3 insertions(+)
arch/x86/kvm/svm/sev.c +3 -0
@@ -814,6 +814,9 @@ static int sev_es_sync_vmsa(struct vcpu_
 	u8 *d;
 	int i;
 
+	if (vcpu->arch.guest_state_protected)
+		return -EINVAL;
+
 	/* Check some debug related fields before encrypting the VMSA */
 	if (svm->vcpu.guest_debug || (svm->vmcb->save.dr7 & ~DR7_FIXED_1))
 		return -EINVAL;
author maintainer
#131 lore raw

PATCH 130/162 KVM: SEV: Disallow LAUNCH_FINISH if vCPUs are actively being created

In reply to Greg Kroah-Hartman

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

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

From: Sean Christopherson <[email protected]>

commit 624bf3440d7214b62c22d698a0a294323f331d5d upstream.

Reject LAUNCH_FINISH for SEV-ES and SNP VMs if KVM is actively creating one or more vCPUs, as KVM needs to process and encrypt each vCPU's VMSA. Letting userspace create vCPUs while LAUNCH_FINISH is in-progress is "fine", at least in the current code base, as kvm_for_each_vcpu() operates on online_vcpus, LAUNCH_FINISH (all SEV+ sub-ioctls) holds kvm->mutex, and fully onlining a vCPU in kvm_vm_ioctl_create_vcpu() is done under kvm->mutex. I.e. there's no difference between an in-progress vCPU and a vCPU that is created entirely after LAUNCH_FINISH.

However, given that concurrent LAUNCH_FINISH and vCPU creation can't possibly work (for any reasonable definition of "work"), since userspace can't guarantee whether a particular vCPU will be encrypted or not, disallow the combination as a hardening measure, to reduce the probability of introducing bugs in the future, and to avoid having to reason about the safety of future changes related to LAUNCH_FINISH.

---
 arch/x86/kvm/svm/sev.c   |   10 ++++++++--
 include/linux/kvm_host.h |    7 +++++++
 2 files changed, 15 insertions(+), 2 deletions(-)
arch/x86/kvm/svm/sev.c +8 -2
@@ -962,6 +962,9 @@ static int sev_launch_update_vmsa(struct
 	if (!sev_es_guest(kvm))
 		return -ENOTTY;
 
+	if (kvm_is_vcpu_creation_in_progress(kvm))
+		return -EBUSY;
+
 	kvm_for_each_vcpu(i, vcpu, kvm) {
 		ret = mutex_lock_killable(&vcpu->mutex);
 		if (ret)
@@ -2061,8 +2064,8 @@ static int sev_check_source_vcpus(struct
 	struct kvm_vcpu *src_vcpu;
 	unsigned long i;
 
-	if (src->created_vcpus != atomic_read(&src->online_vcpus) ||
-	    dst->created_vcpus != atomic_read(&dst->online_vcpus))
+	if (kvm_is_vcpu_creation_in_progress(src) ||
+	    kvm_is_vcpu_creation_in_progress(dst))
 		return -EBUSY;
 
 	if (!sev_es_guest(src))
@@ -2456,6 +2459,9 @@ static int snp_launch_update_vmsa(struct
 	unsigned long i;
 	int ret;
 
+	if (kvm_is_vcpu_creation_in_progress(kvm))
+		return -EBUSY;
+
 	data.gctx_paddr = __psp_pa(sev->snp_context);
 	data.page_type = SNP_PAGE_TYPE_VMSA;
 
include/linux/kvm_host.h +7 -0
@@ -1017,6 +1017,13 @@ static inline struct kvm_vcpu *kvm_get_v
 	return NULL;
 }
 
+static inline bool kvm_is_vcpu_creation_in_progress(struct kvm *kvm)
+{
+	lockdep_assert_held(&kvm->lock);
+
+	return kvm->created_vcpus != atomic_read(&kvm->online_vcpus);
+}
+
 void kvm_destroy_vcpus(struct kvm *kvm);
 
 void vcpu_load(struct kvm_vcpu *vcpu);
author maintainer
#132 lore raw

PATCH 131/162 KVM: SEV: Drop WARN on large size for KVM_MEMORY_ENCRYPT_REG_REGION

In reply to Greg Kroah-Hartman

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

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

From: Sean Christopherson <[email protected]>

commit 8acffeef5ef720c35e513e322ab08e32683f32f2 upstream.

Drop the WARN in sev_pin_memory() on npages overflowing an int, as the WARN is comically trivially to trigger from userspace, e.g. by doing:

  struct kvm_enc_region range = {
          .addr = 0,
          .size = -1ul,
  };

  __vm_ioctl(vm, KVM_MEMORY_ENCRYPT_REG_REGION, &range);

Note, the checks in sev_mem_enc_register_region() that presumably exist to verify the incoming address+size are completely worthless, as both "addr" and "size" are u64s and SEV is 64-bit only, i.e. they _can't_ be greater than ULONG_MAX. That wart will be cleaned up in the near future.

	if (range->addr > ULONG_MAX || range->size > ULONG_MAX)
		return -EINVAL;

Opportunistically add a comment to explain why the code calculates the number of pages the "hard" way, e.g. instead of just shifting @ulen.

---
 arch/x86/kvm/svm/sev.c |   11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
arch/x86/kvm/svm/sev.c +7 -4
@@ -642,10 +642,16 @@ static struct page **sev_pin_memory(stru
 	if (ulen == 0 || uaddr + ulen < uaddr)
 		return ERR_PTR(-EINVAL);
 
-	/* Calculate number of pages. */
+	/*
+	 * Calculate the number of pages that need to be pinned to cover the
+	 * entire range.  Note!  This isn't simply ulen >> PAGE_SHIFT, as KVM
+	 * doesn't require the incoming address+size to be page aligned!
+	 */
 	first = (uaddr & PAGE_MASK) >> PAGE_SHIFT;
 	last = ((uaddr + ulen - 1) & PAGE_MASK) >> PAGE_SHIFT;
 	npages = (last - first + 1);
+	if (npages > INT_MAX)
+		return ERR_PTR(-EINVAL);
 
 	locked = sev->pages_locked + npages;
 	lock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
@@ -654,9 +660,6 @@ static struct page **sev_pin_memory(stru
 		return ERR_PTR(-ENOMEM);
 	}
 
-	if (WARN_ON_ONCE(npages > INT_MAX))
-		return ERR_PTR(-EINVAL);
-
 	/* Avoid using vmalloc for smaller buffers. */
 	size = npages * sizeof(struct page *);
 	if (size > PAGE_SIZE)
author maintainer
#133 lore raw

PATCH 132/162 gpiolib: unify two loops initializing GPIO descriptors

In reply to Greg Kroah-Hartman

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

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

From: Bartosz Golaszewski <[email protected]>

[ Upstream commit fa17f749ee5bc6afdaa9e0ddbe6a816b490dad7d ]

We currently iterate over the descriptors owned by the GPIO device we're adding twice with the first loop just setting the gdev pointer. It's not used anywhere between this and the second loop so just drop the first one and move the assignment to the second.

---
 drivers/gpio/gpiolib.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/gpio/gpiolib.c +2 -3
index 967ff661e4c96..3f9019cc832ac 100644
@@ -1026,9 +1026,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
 		}
 	}
 
-	for (desc_index = 0; desc_index < gc->ngpio; desc_index++)
-		gdev->descs[desc_index].gdev = gdev;
-
 	BLOCKING_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier);
 	BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier);
 
@@ -1058,6 +1055,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
 	for (desc_index = 0; desc_index < gc->ngpio; desc_index++) {
 		struct gpio_desc *desc = &gdev->descs[desc_index];
 
+		desc->gdev = gdev;
+
 		if (gc->get_direction && gpiochip_line_is_valid(gc, desc_index)) {
 			assign_bit(FLAG_IS_OUT,
 				   &desc->flags, !gc->get_direction(gc, desc_index));
Signature · 1 line
2.53.0
author maintainer
#134 lore raw

PATCH 133/162 gpiolib: fix race condition for gdev->srcu

In reply to Greg Kroah-Hartman

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

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

From: Paweł Narewski <[email protected]>

[ Upstream commit a7ac22d53d0990152b108c3f4fe30df45fcb0181 ]

If two drivers were calling gpiochip_add_data_with_key(), one may be traversing the srcu-protected list in gpio_name_to_desc(), meanwhile other has just added its gdev in gpiodev_add_to_list_unlocked(). This creates a non-mutexed and non-protected timeframe, when one instance is dereferencing and using &gdev->srcu, before the other has initialized it, resulting in crash:

[    4.935481] Unable to handle kernel paging request at virtual address ffff800272bcc000
[    4.943396] Mem abort info:
[    4.943400]   ESR = 0x0000000096000005
[    4.943403]   EC = 0x25: DABT (current EL), IL = 32 bits
[    4.943407]   SET = 0, FnV = 0
[    4.943410]   EA = 0, S1PTW = 0
[    4.943413]   FSC = 0x05: level 1 translation fault
[    4.943416] Data abort info:
[    4.943418]   ISV = 0, ISS = 0x00000005, ISS2 = 0x00000000
[    4.946220]   CM = 0, WnR = 0, TnD = 0, TagAccess = 0
[    4.955261]   GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
[    4.955268] swapper pgtable: 4k pages, 48-bit VAs, pgdp=0000000038e6c000
[    4.961449] [ffff800272bcc000] pgd=0000000000000000
[    4.969203] , p4d=1000000039739003
[    4.979730] , pud=0000000000000000
[    4.980210] phandle (CPU): 0x0000005e, phandle (BE): 0x5e000000 for node "reset"
[    4.991736] Internal error: Oops: 0000000096000005 [#1] PREEMPT SMP
...
[    5.121359] pc : __srcu_read_lock+0x44/0x98
[    5.131091] lr : gpio_name_to_desc+0x60/0x1a0
[    5.153671] sp : ffff8000833bb430
[    5.298440]
[    5.298443] Call trace:
[    5.298445]  __srcu_read_lock+0x44/0x98
[    5.309484]  gpio_name_to_desc+0x60/0x1a0
[    5.320692]  gpiochip_add_data_with_key+0x488/0xf00
    5.946419] ---[ end trace 0000000000000000 ]---

Move initialization code for gdev fields before it is added to gpio_devices, with adjacent initialization code. Adjust goto statements to reflect modified order of operations

Fixes 47d8b4c1d868 ("gpio: add SRCU infrastructure to struct gpio_device")
[Bartosz: fixed a build issue, removed stray newline]

[missing commit fcc8b637c542 ("gpiolib: switch the line state notifier
to atomic"), commit dcb73cbaaeb3 ("gpio: cdev: use raw notifier for line state events") and commit d4f335b410dd ("gpiolib: rename GPIO chip printk macros") in 6.12.y.
Both notifiers as well as both srcu inits are moved before the scoped_guard, following same logic as in a7ac22d53d09.
Rest is changes to git context only.]

---
 drivers/gpio/gpiolib.c | 38 +++++++++++++++++++-------------------
 1 file changed, 19 insertions(+), 19 deletions(-)
drivers/gpio/gpiolib.c +19 -19
index 3f9019cc832ac..5c8cd81656963 100644
@@ -988,6 +988,17 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
 	gdev->ngpio = gc->ngpio;
 	gdev->can_sleep = gc->can_sleep;
 
+	BLOCKING_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier);
+	BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier);
+
+	ret = init_srcu_struct(&gdev->srcu);
+	if (ret)
+		goto err_free_label;
+
+	ret = init_srcu_struct(&gdev->desc_srcu);
+	if (ret)
+		goto err_cleanup_gdev_srcu;
+
 	scoped_guard(mutex, &gpio_devices_lock) {
 		/*
 		 * TODO: this allocates a Linux GPIO number base in the global
@@ -1002,7 +1013,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
 			if (base < 0) {
 				ret = base;
 				base = 0;
-				goto err_free_label;
+				goto err_cleanup_desc_srcu;
 			}
 
 			/*
@@ -1022,21 +1033,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
 		ret = gpiodev_add_to_list_unlocked(gdev);
 		if (ret) {
 			chip_err(gc, "GPIO integer space overlap, cannot add chip\n");
-			goto err_free_label;
+			goto err_cleanup_desc_srcu;
 		}
 	}
 
-	BLOCKING_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier);
-	BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier);
-
-	ret = init_srcu_struct(&gdev->srcu);
-	if (ret)
-		goto err_remove_from_list;
-
-	ret = init_srcu_struct(&gdev->desc_srcu);
-	if (ret)
-		goto err_cleanup_gdev_srcu;
-
 #ifdef CONFIG_PINCTRL
 	INIT_LIST_HEAD(&gdev->pin_ranges);
 #endif
@@ -1046,11 +1046,11 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
 
 	ret = gpiochip_set_names(gc);
 	if (ret)
-		goto err_cleanup_desc_srcu;
+		goto err_remove_from_list;
 
 	ret = gpiochip_init_valid_mask(gc);
 	if (ret)
-		goto err_cleanup_desc_srcu;
+		goto err_remove_from_list;
 
 	for (desc_index = 0; desc_index < gc->ngpio; desc_index++) {
 		struct gpio_desc *desc = &gdev->descs[desc_index];
@@ -1117,10 +1117,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
 	of_gpiochip_remove(gc);
 err_free_valid_mask:
 	gpiochip_free_valid_mask(gc);
-err_cleanup_desc_srcu:
-	cleanup_srcu_struct(&gdev->desc_srcu);
-err_cleanup_gdev_srcu:
-	cleanup_srcu_struct(&gdev->srcu);
 err_remove_from_list:
 	scoped_guard(mutex, &gpio_devices_lock)
 		list_del_rcu(&gdev->list);
@@ -1130,6 +1126,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
 		gpio_device_put(gdev);
 		goto err_print_message;
 	}
+err_cleanup_desc_srcu:
+	cleanup_srcu_struct(&gdev->desc_srcu);
+err_cleanup_gdev_srcu:
+	cleanup_srcu_struct(&gdev->srcu);
 err_free_label:
 	kfree_const(gdev->label);
 err_free_descs:
Signature · 1 line
2.53.0
author maintainer
#135 lore raw

PATCH 134/162 net: sched: fix TCF_LAYER_TRANSPORT handling in tcf_get_base_ptr()

In reply to Greg Kroah-Hartman

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

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

From: Eric Dumazet <[email protected]>

[Upstream commit 4fe5a00ec70717a7f1002d8913ec6143582b3c8e]

syzbot reported that tcf_get_base_ptr() can be called while transport header is not set [1].

Instead of returning a dangling pointer, return NULL.

Fix tcf_get_base_ptr() callers to handle this NULL value.

[1]

 WARNING: CPU: 1 PID: 6019 at ./include/linux/skbuff.h:3071 skb_transport_header include/linux/skbuff.h:3071 [inline]
 WARNING: CPU: 1 PID: 6019 at ./include/linux/skbuff.h:3071 tcf_get_base_ptr include/net/pkt_cls.h:539 [inline]
 WARNING: CPU: 1 PID: 6019 at ./include/linux/skbuff.h:3071 em_nbyte_match+0x2d8/0x3f0 net/sched/em_nbyte.c:43
Modules linked in:
CPU: 1 UID: 0 PID: 6019 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full)
Call Trace:
 <TASK>
  tcf_em_match net/sched/ematch.c:494 [inline]
  __tcf_em_tree_match+0x1ac/0x770 net/sched/ematch.c:520
  tcf_em_tree_match include/net/pkt_cls.h:512 [inline]
  basic_classify+0x115/0x2d0 net/sched/cls_basic.c:50
  tc_classify include/net/tc_wrapper.h:197 [inline]
  __tcf_classify net/sched/cls_api.c:1764 [inline]
  tcf_classify+0x4cf/0x1140 net/sched/cls_api.c:1860
  multiq_classify net/sched/sch_multiq.c:39 [inline]
  multiq_enqueue+0xfd/0x4c0 net/sched/sch_multiq.c:66
  dev_qdisc_enqueue+0x4e/0x260 net/core/dev.c:4118
  __dev_xmit_skb net/core/dev.c:4214 [inline]
  __dev_queue_xmit+0xe83/0x3b50 net/core/dev.c:4729
  packet_snd net/packet/af_packet.c:3076 [inline]
  packet_sendmsg+0x3e33/0x5080 net/packet/af_packet.c:3108
  sock_sendmsg_nosec net/socket.c:727 [inline]
  __sock_sendmsg+0x21c/0x270 net/socket.c:742
  ____sys_sendmsg+0x505/0x830 net/socket.c:2630
---
 include/net/pkt_cls.h |  2 ++
 net/sched/em_cmp.c    |  5 ++++-
 net/sched/em_nbyte.c  |  2 ++
 net/sched/em_text.c   | 11 +++++++++--
 4 files changed, 17 insertions(+), 3 deletions(-)
include/net/pkt_cls.h +2 -0
index 4229e4fcd2a9e..ea2c69fdc8396 100644
@@ -536,6 +536,8 @@ static inline unsigned char * tcf_get_base_ptr(struct sk_buff *skb, int layer)
 		case TCF_LAYER_NETWORK:
 			return skb_network_header(skb);
 		case TCF_LAYER_TRANSPORT:
+			if (!skb_transport_header_was_set(skb))
+				break;
 			return skb_transport_header(skb);
 	}
 
net/sched/em_cmp.c +4 -1
index 64b637f18bc7d..48c1bce74f498 100644
@@ -22,9 +22,12 @@ static int em_cmp_match(struct sk_buff *skb, struct tcf_ematch *em,
 			struct tcf_pkt_info *info)
 {
 	struct tcf_em_cmp *cmp = (struct tcf_em_cmp *) em->data;
-	unsigned char *ptr = tcf_get_base_ptr(skb, cmp->layer) + cmp->off;
+	unsigned char *ptr = tcf_get_base_ptr(skb, cmp->layer);
 	u32 val = 0;
 
+	if (!ptr)
+		return 0;
+	ptr += cmp->off;
 	if (!tcf_valid_offset(skb, ptr, cmp->align))
 		return 0;
 
net/sched/em_nbyte.c +2 -0
index 4f9f21a05d5e4..c65ffa5fff946 100644
@@ -42,6 +42,8 @@ static int em_nbyte_match(struct sk_buff *skb, struct tcf_ematch *em,
 	struct nbyte_data *nbyte = (struct nbyte_data *) em->data;
 	unsigned char *ptr = tcf_get_base_ptr(skb, nbyte->hdr.layer);
 
+	if (!ptr)
+		return 0;
 	ptr += nbyte->hdr.off;
 
 	if (!tcf_valid_offset(skb, ptr, nbyte->hdr.len))
net/sched/em_text.c +9 -2
index 420c66203b177..8331f38eadc60 100644
@@ -29,12 +29,19 @@ static int em_text_match(struct sk_buff *skb, struct tcf_ematch *m,
 			 struct tcf_pkt_info *info)
 {
 	struct text_match *tm = EM_TEXT_PRIV(m);
+	unsigned char *ptr;
 	int from, to;
 
-	from = tcf_get_base_ptr(skb, tm->from_layer) - skb->data;
+	ptr = tcf_get_base_ptr(skb, tm->from_layer);
+	if (!ptr)
+		return 0;
+	from = ptr - skb->data;
 	from += tm->from_offset;
 
-	to = tcf_get_base_ptr(skb, tm->to_layer) - skb->data;
+	ptr = tcf_get_base_ptr(skb, tm->to_layer);
+	if (!ptr)
+		return 0;
+	to = ptr - skb->data;
 	to += tm->to_offset;
 
 	return skb_find_text(skb, from, to, tm->config) != UINT_MAX;
Signature · 1 line
2.53.0
author maintainer
#136 lore raw

PATCH 135/162 kernel: be more careful about dup_mmap() failures and uprobe registering

In reply to Greg Kroah-Hartman

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

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

From: Liam R. Howlett <[email protected]>

[ Upstream commit 64c37e134b120fb462fb4a80694bfb8e7be77b14 ]

If a memory allocation fails during dup_mmap(), the maple tree can be left in an unsafe state for other iterators besides the exit path. All the locks are dropped before the exit_mmap() call (in mm/mmap.c), but the incomplete mm_struct can be reached through (at least) the rmap finding the vmas which have a pointer back to the mm_struct.

Up to this point, there have been no issues with being able to find an mm_struct that was only partially initialised. Syzbot was able to make the incomplete mm_struct fail with recent forking changes, so it has been proven unsafe to use the mm_struct that hasn't been initialised, as referenced in the link below.

Although 8ac662f5da19f ("fork: avoid inappropriate uprobe access to invalid mm") fixed the uprobe access, it does not completely remove the race.

This patch sets the MMF_OOM_SKIP to avoid the iteration of the vmas on the oom side (even though this is extremely unlikely to be selected as an oom victim in the race window), and sets MMF_UNSTABLE to avoid other potential users from using a partially initialised mm_struct.

When registering vmas for uprobe, skip the vmas in an mm that is marked unstable. Modifying a vma in an unstable mm may cause issues if the mm isn't fully initialised.

Fixes d24062914837 ("fork: use __mt_dup() to duplicate maple tree in dup_mmap()")
Cc Oleg Nesterov <[email protected]>
Cc Masami Hiramatsu <[email protected]>
Cc Jann Horn <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Michal Hocko <[email protected]>
Cc Peng Zhang <[email protected]>
Cc Matthew Wilcox <[email protected]>

[resolved conflict from missing header includes:
- linux/workqueue.h missing, introduced by commit 2bf8e5aceff8 ("uprobes:
allow put_uprobe() from non-sleepable softirq context")
- linux/srcu.h missing, introduced by commit dd1a7567784e ("uprobes:
SRCU-protect uretprobe lifetime (with timeout)") ]

---
 kernel/events/uprobes.c |  4 ++++
 kernel/fork.c           | 17 ++++++++++++++---
 2 files changed, 18 insertions(+), 3 deletions(-)
kernel/events/uprobes.c +4 -0
index 1ff26dc3bdb01..5059de5fcc230 100644
@@ -27,6 +27,7 @@
 #include <linux/shmem_fs.h>
 #include <linux/khugepaged.h>
 #include <linux/rcupdate_trace.h>
+#include <linux/oom.h>          /* check_stable_address_space */
 
 #include <linux/uprobes.h>
 
@@ -1106,6 +1107,9 @@ register_for_each_vma(struct uprobe *uprobe, struct uprobe_consumer *new)
 		 * returns NULL in find_active_uprobe_rcu().
 		 */
 		mmap_write_lock(mm);
+		if (check_stable_address_space(mm))
+			goto unlock;
+
 		vma = find_vma(mm, info->vaddr);
 		if (!vma || !valid_vma(vma, is_register) ||
 		    file_inode(vma->vm_file) != uprobe->inode)
kernel/fork.c +14 -3
index 55086df4d24cb..a01cf3a904bfd 100644
@@ -766,7 +766,8 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
 		mt_set_in_rcu(vmi.mas.tree);
 		ksm_fork(mm, oldmm);
 		khugepaged_fork(mm, oldmm);
-	} else if (mpnt) {
+	} else {
+
 		/*
 		 * The entire maple tree has already been duplicated. If the
 		 * mmap duplication fails, mark the failure point with
@@ -774,8 +775,18 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
 		 * stop releasing VMAs that have not been duplicated after this
 		 * point.
 		 */
-		mas_set_range(&vmi.mas, mpnt->vm_start, mpnt->vm_end - 1);
-		mas_store(&vmi.mas, XA_ZERO_ENTRY);
+		if (mpnt) {
+			mas_set_range(&vmi.mas, mpnt->vm_start, mpnt->vm_end - 1);
+			mas_store(&vmi.mas, XA_ZERO_ENTRY);
+			/* Avoid OOM iterating a broken tree */
+			set_bit(MMF_OOM_SKIP, &mm->flags);
+		}
+		/*
+		 * The mm_struct is going to exit, but the locks will be dropped
+		 * first.  Set the mm_struct as unstable is advisable as it is
+		 * not fully initialised.
+		 */
+		set_bit(MMF_UNSTABLE, &mm->flags);
 	}
 out:
 	mmap_write_unlock(mm);
Signature · 1 line
2.53.0
author maintainer
#137 lore raw

PATCH 136/162 KVM: Remove subtle "struct kvm_stats_desc" pseudo-overlay

In reply to Greg Kroah-Hartman

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

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

From: Sean Christopherson <[email protected]>

[ Upstream commit da142f3d373a6ddaca0119615a8db2175ddc4121 ]

Remove KVM's internal pseudo-overlay of kvm_stats_desc, which subtly aliases the flexible name[] in the uAPI definition with a fixed-size array of the same name. The unusual embedded structure results in compiler warnings due to -Wflex-array-member-not-at-end, and also necessitates an extra level of dereferencing in KVM. To avoid the "overlay", define the uAPI structure to have a fixed-size name when building for the kernel.

Opportunistically clean up the indentation for the stats macros, and replace spaces with tabs.

No functional change intended.

---
 arch/arm64/kvm/guest.c    |    4 +-
 arch/loongarch/kvm/vcpu.c |    2 -
 arch/loongarch/kvm/vm.c   |    2 -
 arch/mips/kvm/mips.c      |    4 +-
 arch/powerpc/kvm/book3s.c |    4 +-
 arch/powerpc/kvm/booke.c  |    4 +-
 arch/riscv/kvm/vcpu.c     |    2 -
 arch/riscv/kvm/vm.c       |    2 -
 arch/s390/kvm/kvm-s390.c  |    4 +-
 arch/x86/kvm/x86.c        |    4 +-
 include/linux/kvm_host.h  |   83 +++++++++++++++++++---------------------------
 include/uapi/linux/kvm.h  |    8 ++++
 virt/kvm/binary_stats.c   |    2 -
 virt/kvm/kvm_main.c       |   20 +++++------
 14 files changed, 70 insertions(+), 75 deletions(-)
arch/arm64/kvm/guest.c +2 -2
@@ -29,7 +29,7 @@
 
 #include "trace.h"
 
-const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
+const struct kvm_stats_desc kvm_vm_stats_desc[] = {
 	KVM_GENERIC_VM_STATS()
 };
 
@@ -42,7 +42,7 @@ const struct kvm_stats_header kvm_vm_sta
 		       sizeof(kvm_vm_stats_desc),
 };
 
-const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
+const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {
 	KVM_GENERIC_VCPU_STATS(),
 	STATS_DESC_COUNTER(VCPU, hvc_exit_stat),
 	STATS_DESC_COUNTER(VCPU, wfe_exit_stat),
arch/loongarch/kvm/vcpu.c +1 -1
@@ -14,7 +14,7 @@
 #define CREATE_TRACE_POINTS
 #include "trace.h"
 
-const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
+const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {
 	KVM_GENERIC_VCPU_STATS(),
 	STATS_DESC_COUNTER(VCPU, int_exits),
 	STATS_DESC_COUNTER(VCPU, idle_exits),
arch/loongarch/kvm/vm.c +1 -1
@@ -7,7 +7,7 @@
 #include <asm/kvm_mmu.h>
 #include <asm/kvm_vcpu.h>
 
-const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
+const struct kvm_stats_desc kvm_vm_stats_desc[] = {
 	KVM_GENERIC_VM_STATS(),
 	STATS_DESC_ICOUNTER(VM, pages),
 	STATS_DESC_ICOUNTER(VM, hugepages),
arch/mips/kvm/mips.c +2 -2
@@ -38,7 +38,7 @@
 #define VECTORSPACING 0x100	/* for EI/VI mode */
 #endif
 
-const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
+const struct kvm_stats_desc kvm_vm_stats_desc[] = {
 	KVM_GENERIC_VM_STATS()
 };
 
@@ -51,7 +51,7 @@ const struct kvm_stats_header kvm_vm_sta
 		       sizeof(kvm_vm_stats_desc),
 };
 
-const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
+const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {
 	KVM_GENERIC_VCPU_STATS(),
 	STATS_DESC_COUNTER(VCPU, wait_exits),
 	STATS_DESC_COUNTER(VCPU, cache_exits),
arch/powerpc/kvm/book3s.c +2 -2
@@ -38,7 +38,7 @@
 
 /* #define EXIT_DEBUG */
 
-const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
+const struct kvm_stats_desc kvm_vm_stats_desc[] = {
 	KVM_GENERIC_VM_STATS(),
 	STATS_DESC_ICOUNTER(VM, num_2M_pages),
 	STATS_DESC_ICOUNTER(VM, num_1G_pages)
@@ -53,7 +53,7 @@ const struct kvm_stats_header kvm_vm_sta
 		       sizeof(kvm_vm_stats_desc),
 };
 
-const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
+const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {
 	KVM_GENERIC_VCPU_STATS(),
 	STATS_DESC_COUNTER(VCPU, sum_exits),
 	STATS_DESC_COUNTER(VCPU, mmio_exits),
arch/powerpc/kvm/booke.c +2 -2
@@ -36,7 +36,7 @@
 
 unsigned long kvmppc_booke_handlers;
 
-const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
+const struct kvm_stats_desc kvm_vm_stats_desc[] = {
 	KVM_GENERIC_VM_STATS(),
 	STATS_DESC_ICOUNTER(VM, num_2M_pages),
 	STATS_DESC_ICOUNTER(VM, num_1G_pages)
@@ -51,7 +51,7 @@ const struct kvm_stats_header kvm_vm_sta
 		       sizeof(kvm_vm_stats_desc),
 };
 
-const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
+const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {
 	KVM_GENERIC_VCPU_STATS(),
 	STATS_DESC_COUNTER(VCPU, sum_exits),
 	STATS_DESC_COUNTER(VCPU, mmio_exits),
arch/riscv/kvm/vcpu.c +1 -1
@@ -24,7 +24,7 @@
 #define CREATE_TRACE_POINTS
 #include "trace.h"
 
-const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
+const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {
 	KVM_GENERIC_VCPU_STATS(),
 	STATS_DESC_COUNTER(VCPU, ecall_exit_stat),
 	STATS_DESC_COUNTER(VCPU, wfi_exit_stat),
arch/riscv/kvm/vm.c +1 -1
@@ -12,7 +12,7 @@
 #include <linux/uaccess.h>
 #include <linux/kvm_host.h>
 
-const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
+const struct kvm_stats_desc kvm_vm_stats_desc[] = {
 	KVM_GENERIC_VM_STATS()
 };
 static_assert(ARRAY_SIZE(kvm_vm_stats_desc) ==
arch/s390/kvm/kvm-s390.c +2 -2
@@ -59,7 +59,7 @@
 #define VCPU_IRQS_MAX_BUF (sizeof(struct kvm_s390_irq) * \
 			   (KVM_MAX_VCPUS + LOCAL_IRQS))
 
-const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
+const struct kvm_stats_desc kvm_vm_stats_desc[] = {
 	KVM_GENERIC_VM_STATS(),
 	STATS_DESC_COUNTER(VM, inject_io),
 	STATS_DESC_COUNTER(VM, inject_float_mchk),
@@ -85,7 +85,7 @@ const struct kvm_stats_header kvm_vm_sta
 		       sizeof(kvm_vm_stats_desc),
 };
 
-const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
+const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {
 	KVM_GENERIC_VCPU_STATS(),
 	STATS_DESC_COUNTER(VCPU, exit_userspace),
 	STATS_DESC_COUNTER(VCPU, exit_null),
arch/x86/kvm/x86.c +2 -2
@@ -229,7 +229,7 @@ EXPORT_SYMBOL_GPL(allow_smaller_maxphyad
 bool __read_mostly enable_apicv = true;
 EXPORT_SYMBOL_GPL(enable_apicv);
 
-const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
+const struct kvm_stats_desc kvm_vm_stats_desc[] = {
 	KVM_GENERIC_VM_STATS(),
 	STATS_DESC_COUNTER(VM, mmu_shadow_zapped),
 	STATS_DESC_COUNTER(VM, mmu_pte_write),
@@ -255,7 +255,7 @@ const struct kvm_stats_header kvm_vm_sta
 		       sizeof(kvm_vm_stats_desc),
 };
 
-const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
+const struct kvm_stats_desc kvm_vcpu_stats_desc[] = {
 	KVM_GENERIC_VCPU_STATS(),
 	STATS_DESC_COUNTER(VCPU, pf_taken),
 	STATS_DESC_COUNTER(VCPU, pf_fixed),
include/linux/kvm_host.h +35 -48

107 lines not on this page · raw message

include/uapi/linux/kvm.h +8 -0
@@ -14,6 +14,10 @@
 #include <linux/ioctl.h>
 #include <asm/kvm.h>
 
+#ifdef __KERNEL__
+#include <linux/kvm_types.h>
+#endif
+
 #define KVM_API_VERSION 12
 
 /*
@@ -1526,7 +1530,11 @@ struct kvm_stats_desc {
 	__u16 size;
 	__u32 offset;
 	__u32 bucket_size;
+#ifdef __KERNEL__
+	char name[KVM_STATS_NAME_SIZE];
+#else
 	char name[];
+#endif
 };
 
 #define KVM_GET_STATS_FD  _IO(KVMIO,  0xce)
virt/kvm/binary_stats.c +1 -1
@@ -50,7 +50,7 @@
  * Return: the number of bytes that has been successfully read
  */
 ssize_t kvm_stats_read(char *id, const struct kvm_stats_header *header,
-		       const struct _kvm_stats_desc *desc,
+		       const struct kvm_stats_desc *desc,
 		       void *stats, size_t size_stats,
 		       char __user *user_buffer, size_t size, loff_t *offset)
 {
virt/kvm/kvm_main.c +10 -10
@@ -1013,9 +1013,9 @@ static void kvm_free_memslots(struct kvm
 		kvm_free_memslot(kvm, memslot);
 }
 
-static umode_t kvm_stats_debugfs_mode(const struct _kvm_stats_desc *pdesc)
+static umode_t kvm_stats_debugfs_mode(const struct kvm_stats_desc *desc)
 {
-	switch (pdesc->desc.flags & KVM_STATS_TYPE_MASK) {
+	switch (desc->flags & KVM_STATS_TYPE_MASK) {
 	case KVM_STATS_TYPE_INSTANT:
 		return 0444;
 	case KVM_STATS_TYPE_CUMULATIVE:
@@ -1050,7 +1050,7 @@ static int kvm_create_vm_debugfs(struct
 	struct dentry *dent;
 	char dir_name[ITOA_MAX_LEN * 2];
 	struct kvm_stat_data *stat_data;
-	const struct _kvm_stats_desc *pdesc;
+	const struct kvm_stats_desc *pdesc;
 	int i, ret = -ENOMEM;
 	int kvm_debugfs_num_entries = kvm_vm_stats_header.num_desc +
 				      kvm_vcpu_stats_header.num_desc;
@@ -6164,11 +6164,11 @@ static int kvm_stat_data_get(void *data,
 	switch (stat_data->kind) {
 	case KVM_STAT_VM:
 		r = kvm_get_stat_per_vm(stat_data->kvm,
-					stat_data->desc->desc.offset, val);
+					stat_data->desc->offset, val);
 		break;
 	case KVM_STAT_VCPU:
 		r = kvm_get_stat_per_vcpu(stat_data->kvm,
-					  stat_data->desc->desc.offset, val);
+					  stat_data->desc->offset, val);
 		break;
 	}
 
@@ -6186,11 +6186,11 @@ static int kvm_stat_data_clear(void *dat
 	switch (stat_data->kind) {
 	case KVM_STAT_VM:
 		r = kvm_clear_stat_per_vm(stat_data->kvm,
-					  stat_data->desc->desc.offset);
+					  stat_data->desc->offset);
 		break;
 	case KVM_STAT_VCPU:
 		r = kvm_clear_stat_per_vcpu(stat_data->kvm,
-					    stat_data->desc->desc.offset);
+					    stat_data->desc->offset);
 		break;
 	}
 
@@ -6338,7 +6338,7 @@ static void kvm_uevent_notify_change(uns
 static void kvm_init_debug(void)
 {
 	const struct file_operations *fops;
-	const struct _kvm_stats_desc *pdesc;
+	const struct kvm_stats_desc *pdesc;
 	int i;
 
 	kvm_debugfs_dir = debugfs_create_dir("kvm", NULL);
@@ -6351,7 +6351,7 @@ static void kvm_init_debug(void)
 			fops = &vm_stat_readonly_fops;
 		debugfs_create_file(pdesc->name, kvm_stats_debugfs_mode(pdesc),
 				kvm_debugfs_dir,
-				(void *)(long)pdesc->desc.offset, fops);
+				(void *)(long)pdesc->offset, fops);
 	}
 
 	for (i = 0; i < kvm_vcpu_stats_header.num_desc; ++i) {
@@ -6362,7 +6362,7 @@ static void kvm_init_debug(void)
 			fops = &vcpu_stat_readonly_fops;
 		debugfs_create_file(pdesc->name, kvm_stats_debugfs_mode(pdesc),
 				kvm_debugfs_dir,
-				(void *)(long)pdesc->desc.offset, fops);
+				(void *)(long)pdesc->offset, fops);
 	}
 }
 
author maintainer
#138 lore raw

PATCH 137/162 KVM: x86: Use __DECLARE_FLEX_ARRAY() for UAPI structures with VLAs

In reply to Greg Kroah-Hartman

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

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

From: David Woodhouse <[email protected]>

[ Upstream commit 2619da73bb2f10d88f7e1087125c40144fdf0987 ]

Commit 94dfc73e7cf4 ("treewide: uapi: Replace zero-length arrays with flexible-array members") broke the userspace API for C++.

These structures ending in VLAs are typically a *header*, which can be followed by an arbitrary number of entries. Userspace typically creates a larger structure with some non-zero number of entries, for example in QEMU's kvm_arch_get_supported_msr_feature():

    struct {
        struct kvm_msrs info;
        struct kvm_msr_entry entries[1];
    } msr_data = {};

While that works in C, it fails in C++ with an error like:
flexible array member 'kvm_msrs::entries' not at end of 'struct msr_data'

Fix this by using __DECLARE_FLEX_ARRAY() for the VLA, which uses [0] for C++ compilation.

Fixes 94dfc73e7cf4 ("treewide: uapi: Replace zero-length arrays with flexible-array members")
[sean: tag for stable@]
---
 arch/x86/include/uapi/asm/kvm.h |   12 ++++++------
 include/uapi/linux/kvm.h        |   11 ++++++-----
 2 files changed, 12 insertions(+), 11 deletions(-)
arch/x86/include/uapi/asm/kvm.h +6 -6
@@ -192,13 +192,13 @@ struct kvm_msrs {
 	__u32 nmsrs; /* number of msrs in entries */
 	__u32 pad;
 
-	struct kvm_msr_entry entries[];
+	__DECLARE_FLEX_ARRAY(struct kvm_msr_entry, entries);
 };
 
 /* for KVM_GET_MSR_INDEX_LIST */
 struct kvm_msr_list {
 	__u32 nmsrs; /* number of msrs in entries */
-	__u32 indices[];
+	__DECLARE_FLEX_ARRAY(__u32, indices);
 };
 
 /* Maximum size of any access bitmap in bytes */
@@ -240,7 +240,7 @@ struct kvm_cpuid_entry {
 struct kvm_cpuid {
 	__u32 nent;
 	__u32 padding;
-	struct kvm_cpuid_entry entries[];
+	__DECLARE_FLEX_ARRAY(struct kvm_cpuid_entry, entries);
 };
 
 struct kvm_cpuid_entry2 {
@@ -262,7 +262,7 @@ struct kvm_cpuid_entry2 {
 struct kvm_cpuid2 {
 	__u32 nent;
 	__u32 padding;
-	struct kvm_cpuid_entry2 entries[];
+	__DECLARE_FLEX_ARRAY(struct kvm_cpuid_entry2, entries);
 };
 
 /* for KVM_GET_PIT and KVM_SET_PIT */
@@ -393,7 +393,7 @@ struct kvm_xsave {
 	 * the contents of CPUID leaf 0xD on the host.
 	 */
 	__u32 region[1024];
-	__u32 extra[];
+	__DECLARE_FLEX_ARRAY(__u32, extra);
 };
 
 #define KVM_MAX_XCRS	16
@@ -530,7 +530,7 @@ struct kvm_pmu_event_filter {
 	__u32 fixed_counter_bitmap;
 	__u32 flags;
 	__u32 pad[4];
-	__u64 events[];
+	__DECLARE_FLEX_ARRAY(__u64, events);
 };
 
 #define KVM_PMU_EVENT_ALLOW 0
include/uapi/linux/kvm.h +6 -5
@@ -11,6 +11,7 @@
 #include <linux/const.h>
 #include <linux/types.h>
 #include <linux/compiler.h>
+#include <linux/stddef.h>
 #include <linux/ioctl.h>
 #include <asm/kvm.h>
 
@@ -496,7 +497,7 @@ struct kvm_coalesced_mmio {
 
 struct kvm_coalesced_mmio_ring {
 	__u32 first, last;
-	struct kvm_coalesced_mmio coalesced_mmio[];
+	__DECLARE_FLEX_ARRAY(struct kvm_coalesced_mmio, coalesced_mmio);
 };
 
 #define KVM_COALESCED_MMIO_MAX \
@@ -546,7 +547,7 @@ struct kvm_clear_dirty_log {
 /* for KVM_SET_SIGNAL_MASK */
 struct kvm_signal_mask {
 	__u32 len;
-	__u8  sigset[];
+	__DECLARE_FLEX_ARRAY(__u8, sigset);
 };
 
 /* for KVM_TPR_ACCESS_REPORTING */
@@ -999,7 +1000,7 @@ struct kvm_irq_routing_entry {
 struct kvm_irq_routing {
 	__u32 nr;
 	__u32 flags;
-	struct kvm_irq_routing_entry entries[];
+	__DECLARE_FLEX_ARRAY(struct kvm_irq_routing_entry, entries);
 };
 
 #define KVM_IRQFD_FLAG_DEASSIGN (1 << 0)
@@ -1086,7 +1087,7 @@ struct kvm_dirty_tlb {
 
 struct kvm_reg_list {
 	__u64 n; /* number of regs */
-	__u64 reg[];
+	__DECLARE_FLEX_ARRAY(__u64, reg);
 };
 
 struct kvm_one_reg {
@@ -1533,7 +1534,7 @@ struct kvm_stats_desc {
 #ifdef __KERNEL__
 	char name[KVM_STATS_NAME_SIZE];
 #else
-	char name[];
+	__DECLARE_FLEX_ARRAY(char, name);
 #endif
 };
 
author maintainer
#139 lore raw

PATCH 138/162 checkpatch: add support for Assisted-by tag

In reply to Greg Kroah-Hartman

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

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

From: Sasha Levin <[email protected]>

commit d1db4118489fffd2b2f612140b7acbb477880839 upstream.

The Assisted-by tag was introduced in Documentation/process/coding-assistants.rst for attributing AI tool contributions to kernel patches. However, checkpatch.pl did not recognize this tag, causing two issues:

WARNING: Non-standard signature: Assisted-by:
ERROR: Unrecognized email address: 'AGENT_NAME:MODEL_VERSION'

Fix this by:
1. Adding Assisted-by to the recognized $signature_tags list
2. Skipping email validation for Assisted-by lines since they use the AGENT_NAME:MODEL_VERSION format instead of an email address
3. Warning when the Assisted-by value doesn't match the expected format

---
 scripts/checkpatch.pl |   10 ++++++++++
 1 file changed, 10 insertions(+)
scripts/checkpatch.pl +10 -0
@@ -622,6 +622,7 @@ our $signature_tags = qr{(?xi:
 	Reviewed-by:|
 	Reported-by:|
 	Suggested-by:|
+	Assisted-by:|
 	To:|
 	Cc:
 )};
@@ -3070,6 +3071,15 @@ sub process {
 				}
 			}
 
+			# Assisted-by uses AGENT_NAME:MODEL_VERSION format, not email
+			if ($sign_off =~ /^Assisted-by:/i) {
+				if ($email !~ /^\S+:\S+/) {
+					WARN("BAD_SIGN_OFF",
+					     "Assisted-by expects 'AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2]' format\n" . $herecurr);
+				}
+				next;
+			}
+
 			my ($email_name, $name_comment, $email_address, $comment) = parse_email($email);
 			my $suggested_email = format_email(($email_name, $name_comment, $email_address, $comment));
 			if ($suggested_email eq "") {
author maintainer
#140 lore raw

PATCH 139/162 x86-64: rename misleadingly named __copy_user_nocache() function

In reply to Greg Kroah-Hartman

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

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

From: Linus Torvalds <[email protected]>

commit d187a86de793f84766ea40b9ade7ac60aabbb4fe upstream.

This function was a masterclass in bad naming, for various historical reasons.

It claimed to be a non-cached user copy. It is literally _neither_ of those things. It's a specialty memory copy routine that uses non-temporal stores for the destination (but not the source), and that does exception handling for both source and destination accesses.

Also note that while it works for unaligned targets, any unaligned parts (whether at beginning or end) will not use non-temporal stores, since only words and quadwords can be non-temporal on x86.

The exception handling means that it _can_ be used for user space accesses, but not on its own - it needs all the normal "start user space access" logic around it.

But typically the user space access would be the source, not the non-temporal destination. That was the original intention of this, where the destination was some fragile persistent memory target that needed non-temporal stores in order to catch machine check exceptions synchronously and deal with them gracefully.

Thus that non-descriptive name: one use case was to copy from user space into a non-cached kernel buffer. However, the existing users are a mix of that intended use-case, and a couple of random drivers that just did this as a performance tweak.

Some of those random drivers then actively misused the user copying version (with STAC/CLAC and all) to do kernel copies without ever even caring about the exception handling, _just_ for the non-temporal destination.

Rename it as a first small step to actually make it halfway sane, and change the prototype to be more normal: it doesn't take a user pointer unless the caller has done the proper conversion, and the argument size is the full size_t (it still won't actually copy more than 4GB in one go, but there's also no reason to silently truncate the size argument in the caller).

Finally, use this now sanely named function in the NTB code, which mis-used a user copy version (with STAC/CLAC and all) of this interface despite it not actually being a user copy at all.

---
 arch/x86/include/asm/uaccess_64.h    |    5 +++--
 arch/x86/lib/copy_user_uncached_64.S |    6 +++---
 arch/x86/lib/usercopy_64.c           |    4 ++--
 drivers/infiniband/sw/rdmavt/qp.c    |    8 +++-----
 drivers/ntb/ntb_transport.c          |    7 ++++---
 tools/objtool/check.c                |    2 +-
 6 files changed, 16 insertions(+), 16 deletions(-)
arch/x86/include/asm/uaccess_64.h +3 -2
@@ -147,7 +147,8 @@ raw_copy_to_user(void __user *dst, const
 	return copy_user_generic((__force void *)dst, src, size);
 }
 
-extern long __copy_user_nocache(void *dst, const void __user *src, unsigned size);
+#define copy_to_nontemporal copy_to_nontemporal
+extern size_t copy_to_nontemporal(void *dst, const void *src, size_t size);
 extern long __copy_user_flushcache(void *dst, const void __user *src, unsigned size);
 
 static inline int
@@ -157,7 +158,7 @@ __copy_from_user_inatomic_nocache(void *
 	long ret;
 	kasan_check_write(dst, size);
 	stac();
-	ret = __copy_user_nocache(dst, src, size);
+	ret = copy_to_nontemporal(dst, (__force const void *)src, size);
 	clac();
 	return ret;
 }
arch/x86/lib/copy_user_uncached_64.S +3 -3
@@ -26,7 +26,7 @@
  * Output:
  * rax uncopied bytes or 0 if successful.
  */
-SYM_FUNC_START(__copy_user_nocache)
+SYM_FUNC_START(copy_to_nontemporal)
 	/* If destination is not 7-byte aligned, we'll have to align it */
 	testb $7,%dil
 	jne .Lalign
@@ -238,5 +238,5 @@ _ASM_EXTABLE_UA(95b, .Ldone)
 _ASM_EXTABLE_UA(52b, .Ldone0)
 _ASM_EXTABLE_UA(53b, .Ldone0)
 
-SYM_FUNC_END(__copy_user_nocache)
-EXPORT_SYMBOL(__copy_user_nocache)
+SYM_FUNC_END(copy_to_nontemporal)
+EXPORT_SYMBOL(copy_to_nontemporal)
arch/x86/lib/usercopy_64.c +2 -2
@@ -49,11 +49,11 @@ long __copy_user_flushcache(void *dst, c
 	long rc;
 
 	stac();
-	rc = __copy_user_nocache(dst, src, size);
+	rc = copy_to_nontemporal(dst, (__force const void *)src, size);
 	clac();
 
 	/*
-	 * __copy_user_nocache() uses non-temporal stores for the bulk
+	 * copy_to_nontemporal() uses non-temporal stores for the bulk
 	 * of the transfer, but we need to manually flush if the
 	 * transfer is unaligned. A cached memory copy is used when
 	 * destination or size is not naturally aligned. That is:
drivers/infiniband/sw/rdmavt/qp.c +3 -5
@@ -92,12 +92,10 @@ static int rvt_wss_llc_size(void)
 static void cacheless_memcpy(void *dst, void *src, size_t n)
 {
 	/*
-	 * Use the only available X64 cacheless copy.  Add a __user cast
-	 * to quiet sparse.  The src agument is already in the kernel so
-	 * there are no security issues.  The extra fault recovery machinery
-	 * is not invoked.
+	 * Use the only available X64 cacheless copy.
+	 * The extra fault recovery machinery is not invoked.
 	 */
-	__copy_user_nocache(dst, (void __user *)src, n);
+	copy_to_nontemporal(dst, src, n);
 }
 
 void rvt_wss_exit(struct rvt_dev_info *rdi)
drivers/ntb/ntb_transport.c +4 -3
@@ -1802,12 +1802,13 @@ static void ntb_tx_copy_callback(void *d
 
 static void ntb_memcpy_tx(struct ntb_queue_entry *entry, void __iomem *offset)
 {
-#ifdef ARCH_HAS_NOCACHE_UACCESS
+#ifdef copy_to_nontemporal
 	/*
 	 * Using non-temporal mov to improve performance on non-cached
-	 * writes, even though we aren't actually copying from user space.
+	 * writes. This only works if __iomem is strictly memory-like,
+	 * but that is the case on x86-64
 	 */
-	__copy_from_user_inatomic_nocache(offset, entry->buf, entry->len);
+	copy_to_nontemporal(offset, entry->buf, entry->len);
 #else
 	memcpy_toio(offset, entry->buf, entry->len);
 #endif
tools/objtool/check.c +1 -1
@@ -1258,7 +1258,7 @@ static const char *uaccess_safe_builtin[
 	"copy_mc_enhanced_fast_string",
 	"rep_stos_alternative",
 	"rep_movs_alternative",
-	"__copy_user_nocache",
+	"copy_to_nontemporal",
 	NULL
 };
 
author maintainer
#141 lore raw

PATCH 140/162 x86: rename and clean up __copy_from_user_inatomic_nocache()

In reply to Greg Kroah-Hartman

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

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

From: Linus Torvalds <[email protected]>

commit 5de7bcaadf160c1716b20a263cf8f5b06f658959 upstream.

Similarly to the previous commit, this renames the somewhat confusingly named function. But in this case, it was at least less confusing: the __copy_from_user_inatomic_nocache is indeed copying from user memory, and it is indeed ok to be used in an atomic context, so it will not warn about it.

But the previous commit also removed the NTB mis-use of the __copy_from_user_inatomic_nocache() function, and as a result every call-site is now _actually_ doing a real user copy. That means that we can now do the proper user pointer verification too.

End result: add proper address checking, remove the double underscores, and change the "nocache" to "nontemporal" to more accurately describe what this x86-only function actually does. It might be worth noting that only the target is non-temporal: the actual user accesses are normal memory accesses.

Also worth noting is that non-x86 targets (and on older 32-bit x86 CPU's before XMM2 in the Pentium III) we end up just falling back on a regular user copy, so nothing can actually depend on the non-temporal semantics, but that has always been true.

---
 arch/x86/include/asm/uaccess.h    |    2 +-
 arch/x86/include/asm/uaccess_32.h |    8 +-------
 arch/x86/include/asm/uaccess_64.h |    3 ++-
 arch/x86/lib/usercopy_32.c        |    9 +++++----
 drivers/gpu/drm/i915/i915_gem.c   |    2 +-
 drivers/gpu/drm/qxl/qxl_ioctl.c   |    2 +-
 include/linux/uaccess.h           |   11 ++++++++---
 lib/iov_iter.c                    |    2 +-
 8 files changed, 20 insertions(+), 19 deletions(-)
arch/x86/include/asm/uaccess.h +1 -1
@@ -508,7 +508,7 @@ extern struct movsl_mask {
 } ____cacheline_aligned_in_smp movsl_mask;
 #endif
 
-#define ARCH_HAS_NOCACHE_UACCESS 1
+#define ARCH_HAS_NONTEMPORAL_UACCESS 1
 
 /*
  * The "unsafe" user accesses aren't really "unsafe", but the naming
arch/x86/include/asm/uaccess_32.h +1 -7
@@ -26,13 +26,7 @@ raw_copy_from_user(void *to, const void
 	return __copy_user_ll(to, (__force const void *)from, n);
 }
 
-static __always_inline unsigned long
-__copy_from_user_inatomic_nocache(void *to, const void __user *from,
-				  unsigned long n)
-{
-       return __copy_from_user_ll_nocache_nozero(to, from, n);
-}
-
+unsigned long __must_check copy_from_user_inatomic_nontemporal(void *, const void __user *, unsigned long n);
 unsigned long __must_check clear_user(void __user *mem, unsigned long len);
 unsigned long __must_check __clear_user(void __user *mem, unsigned long len);
 
arch/x86/include/asm/uaccess_64.h +2 -1
@@ -152,11 +152,12 @@ extern size_t copy_to_nontemporal(void *
 extern long __copy_user_flushcache(void *dst, const void __user *src, unsigned size);
 
 static inline int
-__copy_from_user_inatomic_nocache(void *dst, const void __user *src,
+copy_from_user_inatomic_nontemporal(void *dst, const void __user *src,
 				  unsigned size)
 {
 	long ret;
 	kasan_check_write(dst, size);
+	src = mask_user_address(src);
 	stac();
 	ret = copy_to_nontemporal(dst, (__force const void *)src, size);
 	clac();
arch/x86/lib/usercopy_32.c +5 -4
@@ -322,10 +322,11 @@ unsigned long __copy_user_ll(void *to, c
 }
 EXPORT_SYMBOL(__copy_user_ll);
 
-unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *from,
+unsigned long copy_from_user_inatomic_nontemporal(void *to, const void __user *from,
 					unsigned long n)
 {
-	__uaccess_begin_nospec();
+	if (!user_access_begin(from, n))
+		return n;
 #ifdef CONFIG_X86_INTEL_USERCOPY
 	if (n > 64 && static_cpu_has(X86_FEATURE_XMM2))
 		n = __copy_user_intel_nocache(to, from, n);
@@ -334,7 +335,7 @@ unsigned long __copy_from_user_ll_nocach
 #else
 	__copy_user(to, from, n);
 #endif
-	__uaccess_end();
+	user_access_end();
 	return n;
 }
-EXPORT_SYMBOL(__copy_from_user_ll_nocache_nozero);
+EXPORT_SYMBOL(copy_from_user_inatomic_nontemporal);
drivers/gpu/drm/i915/i915_gem.c +1 -1
@@ -519,7 +519,7 @@ ggtt_write(struct io_mapping *mapping,
 
 	/* We can use the cpu mem copy function because this is X86. */
 	vaddr = io_mapping_map_atomic_wc(mapping, base);
-	unwritten = __copy_from_user_inatomic_nocache((void __force *)vaddr + offset,
+	unwritten = copy_from_user_inatomic_nontemporal((void __force *)vaddr + offset,
 						      user_data, length);
 	io_mapping_unmap_atomic(vaddr);
 	if (unwritten) {
drivers/gpu/drm/qxl/qxl_ioctl.c +1 -1
@@ -182,7 +182,7 @@ static int qxl_process_single_command(st
 
 	/* TODO copy slow path code from i915 */
 	fb_cmd = qxl_bo_kmap_atomic_page(qdev, cmd_bo, (release->release_offset & PAGE_MASK));
-	unwritten = __copy_from_user_inatomic_nocache
+	unwritten = copy_from_user_inatomic_nontemporal
 		(fb_cmd + sizeof(union qxl_release_info) + (release->release_offset & ~PAGE_MASK),
 		 u64_to_user_ptr(cmd->command), cmd->command_size);
 
include/linux/uaccess.h +8 -3
@@ -318,16 +318,21 @@ static inline size_t probe_subpage_write
 
 #endif /* CONFIG_ARCH_HAS_SUBPAGE_FAULTS */
 
-#ifndef ARCH_HAS_NOCACHE_UACCESS
+#ifndef ARCH_HAS_NONTEMPORAL_UACCESS
 
 static inline __must_check unsigned long
-__copy_from_user_inatomic_nocache(void *to, const void __user *from,
+copy_from_user_inatomic_nontemporal(void *to, const void __user *from,
 				  unsigned long n)
 {
+	if (can_do_masked_user_access())
+		from = mask_user_address(from);
+	else
+		if (!access_ok(from, n))
+			return n;
 	return __copy_from_user_inatomic(to, from, n);
 }
 
-#endif		/* ARCH_HAS_NOCACHE_UACCESS */
+#endif		/* ARCH_HAS_NONTEMPORAL_UACCESS */
 
 extern __must_check int check_zeroed_user(const void __user *from, size_t size);
 
lib/iov_iter.c +1 -1
@@ -265,7 +265,7 @@ static __always_inline
 size_t copy_from_user_iter_nocache(void __user *iter_from, size_t progress,
 				   size_t len, void *to, void *priv2)
 {
-	return __copy_from_user_inatomic_nocache(to + progress, iter_from, len);
+	return copy_from_user_inatomic_nontemporal(to + progress, iter_from, len);
 }
 
 size_t _copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i)
author maintainer
#142 lore raw

PATCH 141/162 x86-64/arm64/powerpc: clean up and rename __copy_from_user_flushcache

In reply to Greg Kroah-Hartman

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

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

From: Linus Torvalds <[email protected]>

commit 809b997a5ce945ab470f70c187048fe4f5df20bf upstream.

This finishes the work on these odd functions that were only implemented by a handful of architectures.

The 'flushcache' function was only used from the iterator code, and let's make it do the same thing that the nontemporal version does:
remove the two underscores and add the user address checking.

Yes, yes, the user address checking is also done at iovec import time, but we have long since walked away from the old double-underscore thing where we try to avoid address checking overhead at access time, and these functions shouldn't be so special and old-fashioned.

The arm64 version already did the address check, in fact, so there it's just a matter of renaming it. For powerpc and x86-64 we now do the proper user access boilerplate.

---
 arch/arm64/include/asm/uaccess.h   |    2 +-
 arch/powerpc/include/asm/uaccess.h |    3 +--
 arch/powerpc/lib/pmem.c            |   11 ++++++-----
 arch/x86/include/asm/uaccess_64.h  |    8 ++++----
 arch/x86/lib/usercopy_64.c         |    8 ++++----
 lib/iov_iter.c                     |    2 +-
 6 files changed, 17 insertions(+), 17 deletions(-)
arch/arm64/include/asm/uaccess.h +1 -1
@@ -480,7 +480,7 @@ extern __must_check long strnlen_user(co
 #ifdef CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE
 extern unsigned long __must_check __copy_user_flushcache(void *to, const void __user *from, unsigned long n);
 
-static inline int __copy_from_user_flushcache(void *dst, const void __user *src, unsigned size)
+static inline size_t copy_from_user_flushcache(void *dst, const void __user *src, size_t size)
 {
 	kasan_check_write(dst, size);
 	return __copy_user_flushcache(dst, __uaccess_mask_ptr(src), size);
arch/powerpc/include/asm/uaccess.h +1 -2
@@ -407,8 +407,7 @@ copy_mc_to_user(void __user *to, const v
 }
 #endif
 
-extern long __copy_from_user_flushcache(void *dst, const void __user *src,
-		unsigned size);
+extern size_t copy_from_user_flushcache(void *dst, const void __user *src, size_t size);
 
 static __must_check __always_inline bool user_access_begin(const void __user *ptr, size_t len)
 {
arch/powerpc/lib/pmem.c +6 -5
@@ -66,15 +66,16 @@ EXPORT_SYMBOL_GPL(arch_invalidate_pmem);
 /*
  * CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE symbols
  */
-long __copy_from_user_flushcache(void *dest, const void __user *src,
-		unsigned size)
+size_t copy_from_user_flushcache(void *dest, const void __user *src,
+				 size_t size)
 {
-	unsigned long copied, start = (unsigned long) dest;
+	unsigned long not_copied, start = (unsigned long) dest;
 
-	copied = __copy_from_user(dest, src, size);
+	src = mask_user_address(src);
+	not_copied = __copy_from_user(dest, src, size);
 	clean_pmem_range(start, start + size);
 
-	return copied;
+	return not_copied;
 }
 
 void memcpy_flushcache(void *dest, const void *src, size_t size)
arch/x86/include/asm/uaccess_64.h +4 -4
@@ -149,7 +149,7 @@ raw_copy_to_user(void __user *dst, const
 
 #define copy_to_nontemporal copy_to_nontemporal
 extern size_t copy_to_nontemporal(void *dst, const void *src, size_t size);
-extern long __copy_user_flushcache(void *dst, const void __user *src, unsigned size);
+extern size_t copy_user_flushcache(void *dst, const void __user *src, size_t size);
 
 static inline int
 copy_from_user_inatomic_nontemporal(void *dst, const void __user *src,
@@ -164,11 +164,11 @@ copy_from_user_inatomic_nontemporal(void
 	return ret;
 }
 
-static inline int
-__copy_from_user_flushcache(void *dst, const void __user *src, unsigned size)
+static inline size_t
+copy_from_user_flushcache(void *dst, const void __user *src, size_t size)
 {
 	kasan_check_write(dst, size);
-	return __copy_user_flushcache(dst, src, size);
+	return copy_user_flushcache(dst, src, size);
 }
 
 /*
arch/x86/lib/usercopy_64.c +4 -4
@@ -43,14 +43,14 @@ void arch_wb_cache_pmem(void *addr, size
 }
 EXPORT_SYMBOL_GPL(arch_wb_cache_pmem);
 
-long __copy_user_flushcache(void *dst, const void __user *src, unsigned size)
+size_t copy_user_flushcache(void *dst, const void __user *src, size_t size)
 {
 	unsigned long flushed, dest = (unsigned long) dst;
-	long rc;
+	unsigned long rc;
 
-	stac();
+	src = masked_user_access_begin(src);
 	rc = copy_to_nontemporal(dst, (__force const void *)src, size);
-	clac();
+	user_access_end();
 
 	/*
 	 * copy_to_nontemporal() uses non-temporal stores for the bulk
lib/iov_iter.c +1 -1
@@ -284,7 +284,7 @@ static __always_inline
 size_t copy_from_user_iter_flushcache(void __user *iter_from, size_t progress,
 				      size_t len, void *to, void *priv2)
 {
-	return __copy_from_user_flushcache(to + progress, iter_from, len);
+	return copy_from_user_flushcache(to + progress, iter_from, len);
 }
 
 static __always_inline
author maintainer
#143 lore raw

PATCH 142/162 KVM: x86: Use scratch field in MMIO fragment to hold small write values

In reply to Greg Kroah-Hartman

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

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

From: Sean Christopherson <[email protected]>

commit 0b16e69d17d8c35c5c9d5918bf596c75a44655d3 upstream.

When exiting to userspace to service an emulated MMIO write, copy the to-be-written value to a scratch field in the MMIO fragment if the size of the data payload is 8 bytes or less, i.e. can fit in a single chunk, instead of pointing the fragment directly at the source value.

This fixes a class of use-after-free bugs that occur when the emulator initiates a write using an on-stack, local variable as the source, the write splits a page boundary, *and* both pages are MMIO pages. Because KVM's ABI only allows for physically contiguous MMIO requests, accesses that split MMIO pages are separated into two fragments, and are sent to userspace one at a time. When KVM attempts to complete userspace MMIO in response to KVM_RUN after the first fragment, KVM will detect the second fragment and generate a second userspace exit, and reference the on-stack variable.

The issue is most visible if the second KVM_RUN is performed by a separate task, in which case the stack of the initiating task can show up as truly freed data.

==================================================================

  BUG: KASAN: use-after-free in complete_emulated_mmio+0x305/0x420
  Read of size 1 at addr ffff888009c378d1 by task syz-executor417/984

  CPU: 1 PID: 984 Comm: syz-executor417 Not tainted 5.10.0-182.0.0.95.h2627.eulerosv2r13.x86_64 #3
  Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.15.0-0-g2dd4b9b3f840-prebuilt.qemu.org 04/01/2014 Call Trace:
  dump_stack+0xbe/0xfd
  print_address_description.constprop.0+0x19/0x170
  __kasan_report.cold+0x6c/0x84
  kasan_report+0x3a/0x50
  check_memory_region+0xfd/0x1f0
  memcpy+0x20/0x60
  complete_emulated_mmio+0x305/0x420
  kvm_arch_vcpu_ioctl_run+0x63f/0x6d0
  kvm_vcpu_ioctl+0x413/0xb20
  __se_sys_ioctl+0x111/0x160
  do_syscall_64+0x30/0x40
  entry_SYSCALL_64_after_hwframe+0x67/0xd1
  RIP: 0033:0x42477d
  Code: <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48
  RSP: 002b:00007faa8e6890e8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
  RAX: ffffffffffffffda RBX: 00000000004d7338 RCX: 000000000042477d
  RDX: 0000000000000000 RSI: 000000000000ae80 RDI: 0000000000000005
  RBP: 00000000004d7330 R08: 00007fff28d546df R09: 0000000000000000
  R10: 0000000000000000 R11: 0000000000000246 R12: 00000000004d733c
  R13: 0000000000000000 R14: 000000000040a200 R15: 00007fff28d54720

  The buggy address belongs to the page:
  page:0000000029f6a428 refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x9c37
  flags: 0xfffffc0000000(node=0|zone=1|lastcpupid=0x1fffff)
  raw: 000fffffc0000000 0000000000000000 ffffea0000270dc8 0000000000000000
  raw: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000 page dumped because: kasan: bad access detected

  Memory state around the buggy address:
  ffff888009c37780: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
  ffff888009c37800: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
  >ffff888009c37880: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
                                                   ^
  ffff888009c37900: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
  ffff888009c37980: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
  ==================================================================

The bug can also be reproduced with a targeted KVM-Unit-Test by hacking KVM to fill a large on-stack variable in complete_emulated_mmio(), i.e. by overwrite the data value with garbage.

Limit the use of the scratch fields to 8-byte or smaller accesses, and to just writes, as larger accesses and reads are not affected thanks to implementation details in the emulator, but add a sanity check to ensure those details don't change in the future. Specifically, KVM never uses on-stack variables for accesses larger that 8 bytes, e.g. uses an operand in the emulator context, and *all* reads are buffered through the mem_read cache.

Note! Using the scratch field for reads is not only unnecessary, it's also extremely difficult to handle correctly. As above, KVM buffers all reads through the mem_read cache, and heavily relies on that behavior when re-emulating the instruction after a userspace MMIO read exit. If a read splits a page, the first page is NOT an MMIO page, and the second page IS an MMIO page, then the MMIO fragment needs to point at _just_ the second chunk of the destination, i.e. its position in the mem_read cache. Taking the "obvious" approach of copying the fragment value into the destination when re-emulating the instruction would clobber the first chunk of the destination, i.e. would clobber the data that was read from guest memory.

---
 arch/x86/kvm/x86.c       |   14 +++++++++++++-
 include/linux/kvm_host.h |    3 ++-
 2 files changed, 15 insertions(+), 2 deletions(-)
arch/x86/kvm/x86.c +13 -1
@@ -7976,7 +7976,13 @@ static int emulator_read_write_onepage(u
 	WARN_ON(vcpu->mmio_nr_fragments >= KVM_MAX_MMIO_FRAGMENTS);
 	frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++];
 	frag->gpa = gpa;
-	frag->data = val;
+	if (write && bytes <= 8u) {
+		frag->val = 0;
+		frag->data = &frag->val;
+		memcpy(&frag->val, val, bytes);
+	} else {
+		frag->data = val;
+	}
 	frag->len = bytes;
 	return X86EMUL_CONTINUE;
 }
@@ -7991,6 +7997,9 @@ static int emulator_read_write(struct x8
 	gpa_t gpa;
 	int rc;
 
+	if (WARN_ON_ONCE((bytes > 8u || !ops->write) && object_is_on_stack(val)))
+		return X86EMUL_UNHANDLEABLE;
+
 	if (ops->read_write_prepare &&
 		  ops->read_write_prepare(vcpu, val, bytes))
 		return X86EMUL_CONTINUE;
@@ -11508,6 +11517,9 @@ static int complete_emulated_mmio(struct
 		frag++;
 		vcpu->mmio_cur_fragment++;
 	} else {
+		if (WARN_ON_ONCE(frag->data == &frag->val))
+			return -EIO;
+
 		/* Go forward to the next mmio piece. */
 		frag->data += len;
 		frag->gpa += len;
include/linux/kvm_host.h +2 -1
@@ -323,7 +323,8 @@ static inline bool kvm_vcpu_can_poll(kti
 struct kvm_mmio_fragment {
 	gpa_t gpa;
 	void *data;
-	unsigned len;
+	u64 val;
+	unsigned int len;
 };
 
 struct kvm_vcpu {
author maintainer
#144 lore raw

PATCH 143/162 ASoC: qcom: q6apm: move component registration to unmanaged version

In reply to Greg Kroah-Hartman

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

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

From: Srinivas Kandagatla <[email protected]>

commit 6ec1235fc941dac6c011b30ee01d9220ff87e0cd upstream.

q6apm component registers dais dynamically from ASoC toplology, which are allocated using device managed version apis. Allocating both component and dynamic dais using managed version could lead to incorrect free ordering, dai will be freed while component still holding references to it.

Fix this issue by moving component to unmanged version so that the dai pointers are only freeded after the component is removed.

==================================================================

BUG: KASAN: slab-use-after-free in snd_soc_del_component_unlocked+0x3d4/0x400 [snd_soc_core]
Read of size 8 at addr ffff00084493a6e8 by task kworker/u48:0/3426
Tainted: [W]=WARN
Hardware name: LENOVO 21N2ZC5PUS/21N2ZC5PUS, BIOS N42ET57W (1.31 ) 08/08/2024
Workqueue: pdr_notifier_wq pdr_notifier_work [pdr_interface]
Call trace:
 show_stack+0x28/0x7c (C)
 dump_stack_lvl+0x60/0x80
 print_report+0x160/0x4b4
 kasan_report+0xac/0xfc
 __asan_report_load8_noabort+0x20/0x34
 snd_soc_del_component_unlocked+0x3d4/0x400 [snd_soc_core]
 snd_soc_unregister_component_by_driver+0x50/0x88 [snd_soc_core]
 devm_component_release+0x30/0x5c [snd_soc_core]
 devres_release_all+0x13c/0x210
 device_unbind_cleanup+0x20/0x190
 device_release_driver_internal+0x350/0x468
 device_release_driver+0x18/0x30
 bus_remove_device+0x1a0/0x35c
 device_del+0x314/0x7f0
 device_unregister+0x20/0xbc
 apr_remove_device+0x5c/0x7c [apr]
 device_for_each_child+0xd8/0x160
 apr_pd_status+0x7c/0xa8 [apr]
 pdr_notifier_work+0x114/0x240 [pdr_interface]
 process_one_work+0x500/0xb70
 worker_thread+0x630/0xfb0
 kthread+0x370/0x6c0
 ret_from_fork+0x10/0x20

Allocated by task 77:
 kasan_save_stack+0x40/0x68
 kasan_save_track+0x20/0x40
 kasan_save_alloc_info+0x44/0x58
 __kasan_kmalloc+0xbc/0xdc
 __kmalloc_node_track_caller_noprof+0x1f4/0x620
 devm_kmalloc+0x7c/0x1c8
 snd_soc_register_dai+0x50/0x4f0 [snd_soc_core]
 soc_tplg_pcm_elems_load+0x55c/0x1eb8 [snd_soc_core]
 snd_soc_tplg_component_load+0x4f8/0xb60 [snd_soc_core]
 audioreach_tplg_init+0x124/0x1fc [snd_q6apm]
 q6apm_audio_probe+0x10/0x1c [snd_q6apm]
 snd_soc_component_probe+0x5c/0x118 [snd_soc_core]
 soc_probe_component+0x44c/0xaf0 [snd_soc_core]
 snd_soc_bind_card+0xad0/0x2370 [snd_soc_core]
 snd_soc_register_card+0x3b0/0x4c0 [snd_soc_core]
 devm_snd_soc_register_card+0x50/0xc8 [snd_soc_core]
 x1e80100_platform_probe+0x208/0x368 [snd_soc_x1e80100]
 platform_probe+0xc0/0x188
 really_probe+0x188/0x804
 __driver_probe_device+0x158/0x358
 driver_probe_device+0x60/0x190
 __device_attach_driver+0x16c/0x2a8
 bus_for_each_drv+0x100/0x194
 __device_attach+0x174/0x380
 device_initial_probe+0x14/0x20
 bus_probe_device+0x124/0x154
 deferred_probe_work_func+0x140/0x220
 process_one_work+0x500/0xb70
 worker_thread+0x630/0xfb0
 kthread+0x370/0x6c0
 ret_from_fork+0x10/0x20

Freed by task 3426:
 kasan_save_stack+0x40/0x68
 kasan_save_track+0x20/0x40
 __kasan_save_free_info+0x4c/0x80
 __kasan_slab_free+0x78/0xa0
 kfree+0x100/0x4a4
 devres_release_all+0x144/0x210
 device_unbind_cleanup+0x20/0x190
 device_release_driver_internal+0x350/0x468
 device_release_driver+0x18/0x30
 bus_remove_device+0x1a0/0x35c
 device_del+0x314/0x7f0
 device_unregister+0x20/0xbc
 apr_remove_device+0x5c/0x7c [apr]
 device_for_each_child+0xd8/0x160
 apr_pd_status+0x7c/0xa8 [apr]
 pdr_notifier_work+0x114/0x240 [pdr_interface]
 process_one_work+0x500/0xb70
 worker_thread+0x630/0xfb0
 kthread+0x370/0x6c0
 ret_from_fork+0x10/0x20
---
 sound/soc/qcom/qdsp6/q6apm.c |   14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)
sound/soc/qcom/qdsp6/q6apm.c +12 -2
@@ -764,13 +764,22 @@ static int apm_probe(gpr_device_t *gdev)
 
 	q6apm_get_apm_state(apm);
 
-	ret = devm_snd_soc_register_component(dev, &q6apm_audio_component, NULL, 0);
+	ret = snd_soc_register_component(dev, &q6apm_audio_component, NULL, 0);
 	if (ret < 0) {
 		dev_err(dev, "failed to register q6apm: %d\n", ret);
 		return ret;
 	}
 
-	return of_platform_populate(dev->of_node, NULL, NULL, dev);
+	ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
+	if (ret)
+		snd_soc_unregister_component(dev);
+
+	return ret;
+}
+
+static void apm_remove(gpr_device_t *gdev)
+{
+	snd_soc_unregister_component(&gdev->dev);
 }
 
 struct audioreach_module *q6apm_find_module_by_mid(struct q6apm_graph *graph, uint32_t mid)
@@ -837,6 +846,7 @@ MODULE_DEVICE_TABLE(of, apm_device_id);
 
 static gpr_driver_t apm_driver = {
 	.probe = apm_probe,
+	.remove = apm_remove,
 	.gpr_callback = apm_callback,
 	.driver = {
 		.name = "qcom-apm",
author maintainer
#145 lore raw

PATCH 144/162 mm/kasan: fix double free for kasan pXds

In reply to Greg Kroah-Hartman

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

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

From: Ritesh Harjani (IBM) <[email protected]>

commit 51d8c78be0c27ddb91bc2c0263941d8b30a47d3b upstream.

kasan_free_pxd() assumes the page table is always struct page aligned. But that's not always the case for all architectures. E.g. In case of powerpc with 64K pagesize, PUD table (of size 4096) comes from slab cache named pgtable-2^9. Hence instead of page_to_virt(pxd_page()) let's just directly pass the start of the pxd table which is passed as the 1st argument.

This fixes the below double free kasan issue seen with PMEM:

radix-mmu: Mapped 0x0000047d10000000-0x0000047f90000000 with 2.00 MiB pages
==================================================================

BUG: KASAN: double-free in kasan_remove_zero_shadow+0x9c4/0xa20

Free of addr c0000003c38e0000 by task ndctl/2164

CPU: 34 UID: 0 PID: 2164 Comm: ndctl Not tainted 6.19.0-rc1-00048-gea1013c15392 #157 VOLUNTARY
Hardware name: IBM,9080-HEX POWER10 (architected) 0x800200 0xf000006 of:IBM,FW1060.00 (NH1060_012) hv:phyp pSeries
Call Trace:
 dump_stack_lvl+0x88/0xc4 (unreliable)
 print_report+0x214/0x63c
 kasan_report_invalid_free+0xe4/0x110
 check_slab_allocation+0x100/0x150
 kmem_cache_free+0x128/0x6e0
 kasan_remove_zero_shadow+0x9c4/0xa20
 memunmap_pages+0x2b8/0x5c0
 devm_action_release+0x54/0x70
 release_nodes+0xc8/0x1a0
 devres_release_all+0xe0/0x140
 device_unbind_cleanup+0x30/0x120
 device_release_driver_internal+0x3e4/0x450
 unbind_store+0xfc/0x110
 drv_attr_store+0x78/0xb0
 sysfs_kf_write+0x114/0x140
 kernfs_fop_write_iter+0x264/0x3f0
 vfs_write+0x3bc/0x7d0
 ksys_write+0xa4/0x190
 system_call_exception+0x190/0x480
 system_call_vectored_common+0x15c/0x2ec
---- interrupt: 3000 at 0x7fff93b3d3f4
NIP:  00007fff93b3d3f4 LR: 00007fff93b3d3f4 CTR: 0000000000000000
REGS: c0000003f1b07e80 TRAP: 3000   Not tainted  (6.19.0-rc1-00048-gea1013c15392)
MSR:  800000000280f033 <SF,VEC,VSX,EE,PR,FP,ME,IR,DR,RI,LE>  CR: 48888208  XER: 00000000

<...>
NIP [00007fff93b3d3f4] 0x7fff93b3d3f4
LR [00007fff93b3d3f4] 0x7fff93b3d3f4
---- interrupt: 3000

 The buggy address belongs to the object at c0000003c38e0000
  which belongs to the cache pgtable-2^9 of size 4096
 The buggy address is located 0 bytes inside of
  4096-byte region [c0000003c38e0000, c0000003c38e1000)

 The buggy address belongs to the physical page:
 page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x3c38c
 head: order:2 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
 memcg:c0000003bfd63e01
 flags: 0x63ffff800000040(head|node=6|zone=0|lastcpupid=0x7ffff)
 page_type: f5(slab)
 raw: 063ffff800000040 c000000140058980 5deadbeef0000122 0000000000000000
 raw: 0000000000000000 0000000080200020 00000000f5000000 c0000003bfd63e01
 head: 063ffff800000040 c000000140058980 5deadbeef0000122 0000000000000000
 head: 0000000000000000 0000000080200020 00000000f5000000 c0000003bfd63e01
 head: 063ffff800000002 c00c000000f0e301 00000000ffffffff 00000000ffffffff
 head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000004
 page dumped because: kasan: bad access detected
[  138.953636] [   T2164] Memory state around the buggy address:
[  138.953643] [   T2164]  c0000003c38dff00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  138.953652] [   T2164]  c0000003c38dff80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  138.953661] [   T2164] >c0000003c38e0000: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  138.953669] [   T2164]                    ^
[  138.953675] [   T2164]  c0000003c38e0080: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  138.953684] [   T2164]  c0000003c38e0100: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  138.953692] [   T2164] ==================================================================
[  138.953701] [   T2164] Disabling lock debugging due to kernel taint
---
 mm/kasan/init.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
mm/kasan/init.c +4 -4
@@ -306,7 +306,7 @@ static void kasan_free_pte(pte_t *pte_st
 			return;
 	}
 
-	pte_free_kernel(&init_mm, (pte_t *)page_to_virt(pmd_page(*pmd)));
+	pte_free_kernel(&init_mm, pte_start);
 	pmd_clear(pmd);
 }
 
@@ -321,7 +321,7 @@ static void kasan_free_pmd(pmd_t *pmd_st
 			return;
 	}
 
-	pmd_free(&init_mm, (pmd_t *)page_to_virt(pud_page(*pud)));
+	pmd_free(&init_mm, pmd_start);
 	pud_clear(pud);
 }
 
@@ -336,7 +336,7 @@ static void kasan_free_pud(pud_t *pud_st
 			return;
 	}
 
-	pud_free(&init_mm, (pud_t *)page_to_virt(p4d_page(*p4d)));
+	pud_free(&init_mm, pud_start);
 	p4d_clear(p4d);
 }
 
@@ -351,7 +351,7 @@ static void kasan_free_p4d(p4d_t *p4d_st
 			return;
 	}
 
-	p4d_free(&init_mm, (p4d_t *)page_to_virt(pgd_page(*pgd)));
+	p4d_free(&init_mm, p4d_start);
 	pgd_clear(pgd);
 }
 
author maintainer
#146 lore raw

PATCH 145/162 mm: blk-cgroup: fix use-after-free in cgwb_release_workfn()

In reply to Greg Kroah-Hartman

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

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

From: Breno Leitao <[email protected]>

commit 8f5857be99f1ed1fa80991c72449541f634626ee upstream.

cgwb_release_workfn() calls css_put(wb->blkcg_css) and then later accesses wb->blkcg_css again via blkcg_unpin_online(). If css_put() drops the last reference, the blkcg can be freed asynchronously (css_free_rwork_fn -> blkcg_css_free -> kfree) before blkcg_unpin_online() dereferences the pointer to access blkcg->online_pin, resulting in a use-after-free:

  BUG: KASAN: slab-use-after-free in blkcg_unpin_online (./include/linux/instrumented.h:112 ./include/linux/atomic/atomic-instrumented.h:400 ./include/linux/refcount.h:389 ./include/linux/refcount.h:432 ./include/linux/refcount.h:450 block/blk-cgroup.c:1367)
  Write of size 4 at addr ff11000117aa6160 by task kworker/71:1/531
   Workqueue: cgwb_release cgwb_release_workfn
   Call Trace:
    <TASK>
     blkcg_unpin_online (./include/linux/instrumented.h:112 ./include/linux/atomic/atomic-instrumented.h:400 ./include/linux/refcount.h:389 ./include/linux/refcount.h:432 ./include/linux/refcount.h:450 block/blk-cgroup.c:1367)
     cgwb_release_workfn (mm/backing-dev.c:629)
     process_scheduled_works (kernel/workqueue.c:3278 kernel/workqueue.c:3385)

   Freed by task 1016:
    kfree (./include/linux/kasan.h:235 mm/slub.c:2689 mm/slub.c:6246 mm/slub.c:6561)
    css_free_rwork_fn (kernel/cgroup/cgroup.c:5542)
    process_scheduled_works (kernel/workqueue.c:3302 kernel/workqueue.c:3385)

** Stack based on commit 66672af7a095 ("Add linux-next specific files for 20260410")

I am seeing this crash sporadically in Meta fleet across multiple kernel versions. A full reproducer is available at:
https://github.com/leitao/debug/blob/main/reproducers/repro_blkcg_uaf.sh

(The race window is narrow. To make it easily reproducible, inject a msleep(100) between css_put() and blkcg_unpin_online() in cgwb_release_workfn(). With that delay and a KASAN-enabled kernel, the reproducer triggers the splat reliably in less than a second.)

Fix this by moving blkcg_unpin_online() before css_put(), so the cgwb's CSS reference keeps the blkcg alive while blkcg_unpin_online() accesses it.

Fixes 59b57717fff8 ("blkcg: delay blkg destruction until after writeback has finished")
Cc David Hildenbrand <[email protected]>
Cc Jens Axboe <[email protected]>
Cc Johannes Weiner <[email protected]>
Cc Josef Bacik <[email protected]>
Cc JP Kobryn <[email protected]>
Cc Liam Howlett <[email protected]>
Cc Lorenzo Stoakes (Oracle) <[email protected]>
Cc Martin KaFai Lau <[email protected]>
Cc Michal Hocko <[email protected]>
Cc Mike Rapoport <[email protected]>
Cc Suren Baghdasaryan <[email protected]>
Cc Tejun Heo <[email protected]>
---
 mm/backing-dev.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
mm/backing-dev.c +3 -2
@@ -618,12 +618,13 @@ static void cgwb_release_workfn(struct w
 	wb_shutdown(wb);
 
 	css_put(wb->memcg_css);
-	css_put(wb->blkcg_css);
-	mutex_unlock(&wb->bdi->cgwb_release_mutex);
 
 	/* triggers blkg destruction if no online users left */
 	blkcg_unpin_online(wb->blkcg_css);
 
+	css_put(wb->blkcg_css);
+	mutex_unlock(&wb->bdi->cgwb_release_mutex);
+
 	fprop_local_destroy_percpu(&wb->memcg_completions);
 
 	spin_lock_irq(&cgwb_lock);
author maintainer
#147 lore raw

PATCH 146/162 media: vidtv: fix nfeeds state corruption on start_streaming failure

In reply to Greg Kroah-Hartman

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

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

From: Ruslan Valiyev <[email protected]>

commit a0e5a598fe9a4612b852406b51153b881592aede upstream.

syzbot reported a memory leak in vidtv_psi_service_desc_init [1].

When vidtv_start_streaming() fails inside vidtv_start_feed(), the nfeeds counter is left incremented even though no feed was actually started. This corrupts the driver state: subsequent start_feed calls see nfeeds > 1 and skip starting the mux, while stop_feed calls eventually try to stop a non-existent stream.

This state corruption can also lead to memory leaks, since the mux and channel resources may be partially allocated during a failed start_streaming but never cleaned up, as the stop path finds dvb->streaming == false and returns early.

Fix by decrementing nfeeds back when start_streaming fails, keeping the counter in sync with the actual number of active feeds.

[1]

BUG: memory leak
unreferenced object 0xffff888145b50820 (size 32):
 comm "syz.0.17", pid 6068, jiffies 4294944486
 backtrace (crc 90a0c7d4):
  vidtv_psi_service_desc_init+0x74/0x1b0 drivers/media/test-drivers/vidtv/vidtv_psi.c:288
  vidtv_channel_s302m_init+0xb1/0x2a0 drivers/media/test-drivers/vidtv/vidtv_channel.c:83
  vidtv_channels_init+0x1b/0x40 drivers/media/test-drivers/vidtv/vidtv_channel.c:524
  vidtv_mux_init+0x516/0xbe0 drivers/media/test-drivers/vidtv/vidtv_mux.c:518
  vidtv_start_streaming drivers/media/test-drivers/vidtv/vidtv_bridge.c:194 [inline]
  vidtv_start_feed+0x33e/0x4d0 drivers/media/test-drivers/vidtv/vidtv_bridge.c:239
---
 drivers/media/test-drivers/vidtv/vidtv_bridge.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/media/test-drivers/vidtv/vidtv_bridge.c +3 -1
@@ -237,8 +237,10 @@ static int vidtv_start_feed(struct dvb_d
 
 	if (dvb->nfeeds == 1) {
 		ret = vidtv_start_streaming(dvb);
-		if (ret < 0)
+		if (ret < 0) {
+			dvb->nfeeds--;
 			rc = ret;
+		}
 	}
 
 	mutex_unlock(&dvb->feed_lock);
author maintainer
#148 lore raw

PATCH 147/162 media: mediatek: vcodec: fix use-after-free in encoder release path

In reply to Greg Kroah-Hartman

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

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

From: Fan Wu <[email protected]>

commit 76e35091ffc722ba39b303e48bc5d08abb59dd56 upstream.

The fops_vcodec_release() function frees the context structure (ctx) without first cancelling any pending or running work in ctx->encode_work. This creates a race window where the workqueue handler (mtk_venc_worker) may still be accessing the context memory after it has been freed.

Race condition:

    CPU 0 (release path)               CPU 1 (workqueue)
    ---------------------               ------------------
    fops_vcodec_release()
      v4l2_m2m_ctx_release()
        v4l2_m2m_cancel_job()
        // waits for m2m job "done"
                                        mtk_venc_worker()
                                          v4l2_m2m_job_finish()
                                          // m2m job "done"
                                          // BUT worker still running!
                                          // post-job_finish access:
                                        other ctx dereferences
                                          // UAF if ctx already freed
        // returns (job "done")
      kfree(ctx)  // ctx freed

Root cause: The v4l2_m2m_ctx_release() only waits for the m2m job lifecycle (via TRANS_RUNNING flag), not the workqueue lifecycle. After v4l2_m2m_job_finish() is called, the m2m framework considers the job complete and v4l2_m2m_ctx_release() returns, but the worker function continues executing and may still access ctx.

The work is queued during encode operations via:
queue_work(ctx->dev->encode_workqueue, &ctx->encode_work)
The worker function accesses ctx->m2m_ctx, ctx->dev, and other ctx fields even after calling v4l2_m2m_job_finish().

This vulnerability was confirmed with KASAN by running an instrumented test module that widens the post-job_finish race window. KASAN detected:

  BUG: KASAN: slab-use-after-free in mtk_venc_worker+0x159/0x180
  Read of size 4 at addr ffff88800326e000 by task kworker/u8:0/12

  Workqueue: mtk_vcodec_enc_wq mtk_venc_worker

  Allocated by task 47:
    __kasan_kmalloc+0x7f/0x90
    fops_vcodec_open+0x85/0x1a0

  Freed by task 47:
    __kasan_slab_free+0x43/0x70
    kfree+0xee/0x3a0
    fops_vcodec_release+0xb7/0x190

Fix this by calling cancel_work_sync(&ctx->encode_work) before kfree(ctx). This ensures the workqueue handler is both cancelled (if pending) and synchronized (waits for any running handler to complete) before the context is freed.

Placement rationale: The fix is placed after v4l2_ctrl_handler_free() and before list_del_init(&ctx->list). At this point, all m2m operations are done (v4l2_m2m_ctx_release() has returned), and we need to ensure the workqueue is synchronized before removing ctx from the list and freeing it.

Note: The open error path does NOT need cancel_work_sync() because INIT_WORK() only initializes the work structure - it does not schedule it. Work is only scheduled later during device_run() operations.

Fixes 0934d3759615 ("media: mediatek: vcodec: separate decoder and encoder")
---
 drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c |    9 +++++++++
 1 file changed, 9 insertions(+)
drivers/media/platform/mediatek/vcodec/encoder/mtk_vcodec_enc_drv.c +9 -0
@@ -216,6 +216,15 @@ static int fops_vcodec_release(struct fi
 	v4l2_fh_exit(&ctx->fh);
 	v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
 
+	/*
+	 * Cancel any pending encode work before freeing the context.
+	 * Although v4l2_m2m_ctx_release() waits for m2m job completion,
+	 * the workqueue handler (mtk_venc_worker) may still be accessing
+	 * the context after v4l2_m2m_job_finish() returns. Without this,
+	 * a use-after-free occurs when the worker accesses ctx after kfree.
+	 */
+	cancel_work_sync(&ctx->encode_work);
+
 	spin_lock_irqsave(&dev->dev_ctx_lock, flags);
 	list_del_init(&ctx->list);
 	spin_unlock_irqrestore(&dev->dev_ctx_lock, flags);
author maintainer
#149 lore raw

PATCH 148/162 media: em28xx: fix use-after-free in em28xx_v4l2_open()

In reply to Greg Kroah-Hartman

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

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

From: Abhishek Kumar <[email protected]>

commit a66485a934c7187ae8e36517d40615fa2e961cff upstream.

em28xx_v4l2_open() reads dev->v4l2 without holding dev->lock, creating a race with em28xx_v4l2_init()'s error path and em28xx_v4l2_fini(), both of which free the em28xx_v4l2 struct and set dev->v4l2 to NULL under dev->lock.

This race leads to two issues:
- use-after-free in v4l2_fh_init() when accessing vdev->ctrl_handler, since the video_device is embedded in the freed em28xx_v4l2 struct.
- NULL pointer dereference in em28xx_resolution_set() when accessing v4l2->norm, since dev->v4l2 has been set to NULL.

Fix this by moving the mutex_lock() before the dev->v4l2 read and adding a NULL check for dev->v4l2 under the lock.

Reported-by [email protected]
Fixes 8139a4d583ab ("[media] em28xx: move v4l2 user counting fields from struct em28xx to struct v4l2")
---
 drivers/media/usb/em28xx/em28xx-video.c |   14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)
drivers/media/usb/em28xx/em28xx-video.c +10 -4
@@ -2128,7 +2128,7 @@ static int em28xx_v4l2_open(struct file
 {
 	struct video_device *vdev = video_devdata(filp);
 	struct em28xx *dev = video_drvdata(filp);
-	struct em28xx_v4l2 *v4l2 = dev->v4l2;
+	struct em28xx_v4l2 *v4l2;
 	enum v4l2_buf_type fh_type = 0;
 	int ret;
 
@@ -2145,13 +2145,19 @@ static int em28xx_v4l2_open(struct file
 		return -EINVAL;
 	}
 
+	if (mutex_lock_interruptible(&dev->lock))
+		return -ERESTARTSYS;
+
+	v4l2 = dev->v4l2;
+	if (!v4l2) {
+		mutex_unlock(&dev->lock);
+		return -ENODEV;
+	}
+
 	em28xx_videodbg("open dev=%s type=%s users=%d\n",
 			video_device_node_name(vdev), v4l2_type_names[fh_type],
 			v4l2->users);
 
-	if (mutex_lock_interruptible(&dev->lock))
-		return -ERESTARTSYS;
-
 	ret = v4l2_fh_open(filp);
 	if (ret) {
 		dev_err(&dev->intf->dev,
author maintainer
#150 lore raw

PATCH 149/162 hwmon: (powerz) Fix use-after-free on USB disconnect

In reply to Greg Kroah-Hartman

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

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

From: Sanman Pradhan <[email protected]>

commit 08e57f5e1a9067d5fbf33993aa7f51d60b3d13a4 upstream.

After powerz_disconnect() frees the URB and releases the mutex, a subsequent powerz_read() call can acquire the mutex and call powerz_read_data(), which dereferences the freed URB pointer.

Fix by:
- Setting priv->urb to NULL in powerz_disconnect() so that powerz_read_data() can detect the disconnected state.
- Adding a !priv->urb check at the start of powerz_read_data() to return -ENODEV on a disconnected device.
- Moving usb_set_intfdata() before hwmon registration so the disconnect handler can always find the priv pointer.

---
 drivers/hwmon/powerz.c |    8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/hwmon/powerz.c +6 -2
@@ -114,6 +114,9 @@ static int powerz_read_data(struct usb_d
 {
 	int ret;
 
+	if (!priv->urb)
+		return -ENODEV;
+
 	priv->status = -ETIMEDOUT;
 	reinit_completion(&priv->completion);
 
@@ -230,6 +233,8 @@ static int powerz_probe(struct usb_inter
 	mutex_init(&priv->mutex);
 	init_completion(&priv->completion);
 
+	usb_set_intfdata(intf, priv);
+
 	hwmon_dev =
 	    devm_hwmon_device_register_with_info(parent, DRIVER_NAME, priv,
 						 &powerz_chip_info, NULL);
@@ -238,8 +243,6 @@ static int powerz_probe(struct usb_inter
 		return PTR_ERR(hwmon_dev);
 	}
 
-	usb_set_intfdata(intf, priv);
-
 	return 0;
 }
 
@@ -250,6 +253,7 @@ static void powerz_disconnect(struct usb
 	mutex_lock(&priv->mutex);
 	usb_kill_urb(priv->urb);
 	usb_free_urb(priv->urb);
+	priv->urb = NULL;
 	mutex_unlock(&priv->mutex);
 }
 
author maintainer
#151 lore raw

PATCH 150/162 ALSA: 6fire: fix use-after-free on disconnect

In reply to Greg Kroah-Hartman

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

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

From: Berk Cem Goksel <[email protected]>

commit b9c826916fdce6419b94eb0cd8810fdac18c2386 upstream.

In usb6fire_chip_abort(), the chip struct is allocated as the card's private data (via snd_card_new with sizeof(struct sfire_chip)). When snd_card_free_when_closed() is called and no file handles are open, the card and embedded chip are freed synchronously. The subsequent chip->card = NULL write then hits freed slab memory.

Call trace:
  usb6fire_chip_abort sound/usb/6fire/chip.c:59 [inline]
  usb6fire_chip_disconnect+0x348/0x358 sound/usb/6fire/chip.c:182
  usb_unbind_interface+0x1a8/0x88c drivers/usb/core/driver.c:458
  ...
  hub_event+0x1a04/0x4518 drivers/usb/core/hub.c:5953

Fix by moving the card lifecycle out of usb6fire_chip_abort() and into usb6fire_chip_disconnect(). The card pointer is saved in a local before any teardown, snd_card_disconnect() is called first to prevent new opens, URBs are aborted while chip is still valid, and snd_card_free_when_closed() is called last so chip is never accessed after the card may be freed.

Fixes a0810c3d6dd2 ("ALSA: 6fire: Release resources at card release")
Cc Andrey Konovalov <[email protected]>
---
 sound/usb/6fire/chip.c |   17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)
sound/usb/6fire/chip.c +12 -5
@@ -53,11 +53,6 @@ static void usb6fire_chip_abort(struct s
 			usb6fire_comm_abort(chip);
 		if (chip->control)
 			usb6fire_control_abort(chip);
-		if (chip->card) {
-			snd_card_disconnect(chip->card);
-			snd_card_free_when_closed(chip->card);
-			chip->card = NULL;
-		}
 	}
 }
 
@@ -170,6 +165,7 @@ destroy_chip:
 static void usb6fire_chip_disconnect(struct usb_interface *intf)
 {
 	struct sfire_chip *chip;
+	struct snd_card *card;
 
 	chip = usb_get_intfdata(intf);
 	if (chip) { /* if !chip, fw upload has been performed */
@@ -180,8 +176,19 @@ static void usb6fire_chip_disconnect(str
 			chips[chip->regidx] = NULL;
 			mutex_unlock(&register_mutex);
 
+			/*
+			 * Save card pointer before teardown.
+			 * snd_card_free_when_closed() may free card (and
+			 * the embedded chip) immediately, so it must be
+			 * called last and chip must not be accessed after.
+			 */
+			card = chip->card;
 			chip->shutdown = true;
+			if (card)
+				snd_card_disconnect(card);
 			usb6fire_chip_abort(chip);
+			if (card)
+				snd_card_free_when_closed(card);
 		}
 	}
 }
author maintainer
#152 lore raw

PATCH 151/162 bcache: fix cached_dev.sb_bio use-after-free and crash

In reply to Greg Kroah-Hartman

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

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

From: Mingzhe Zou <[email protected]>

commit fec114a98b8735ee89c75216c45a78e28be0f128 upstream.

In our production environment, we have received multiple crash reports regarding libceph, which have caught our attention:

```
[6888366.280350] Call Trace:
[6888366.280452]  blk_update_request+0x14e/0x370
[6888366.280561]  blk_mq_end_request+0x1a/0x130
[6888366.280671]  rbd_img_handle_request+0x1a0/0x1b0 [rbd]
[6888366.280792]  rbd_obj_handle_request+0x32/0x40 [rbd]
[6888366.280903]  __complete_request+0x22/0x70 [libceph]
[6888366.281032]  osd_dispatch+0x15e/0xb40 [libceph]
[6888366.281164]  ? inet_recvmsg+0x5b/0xd0
[6888366.281272]  ? ceph_tcp_recvmsg+0x6f/0xa0 [libceph]
[6888366.281405]  ceph_con_process_message+0x79/0x140 [libceph]
[6888366.281534]  ceph_con_v1_try_read+0x5d7/0xf30 [libceph]
[6888366.281661]  ceph_con_workfn+0x329/0x680 [libceph]
```

After analyzing the coredump file, we found that the address of dc->sb_bio has been freed. We know that cached_dev is only freed when it is stopped.

Since sb_bio is a part of struct cached_dev, rather than an alloc every time. If the device is stopped while writing to the superblock, the released address will be accessed at endio.

This patch hopes to wait for sb_write to complete in cached_dev_free.

It should be noted that we analyzed the cause of the problem, then tell all details to the QWEN and adopted the modifications it made.

---
 drivers/md/bcache/super.c |    7 +++++++
 1 file changed, 7 insertions(+)
drivers/md/bcache/super.c +7 -0
@@ -1373,6 +1373,13 @@ static CLOSURE_CALLBACK(cached_dev_free)
 
 	mutex_unlock(&bch_register_lock);
 
+	/*
+	 * Wait for any pending sb_write to complete before free.
+	 * The sb_bio is embedded in struct cached_dev, so we must
+	 * ensure no I/O is in progress.
+	 */
+	closure_sync(&dc->sb_write);
+
 	if (dc->sb_disk)
 		put_page(virt_to_page(dc->sb_disk));