Skip to contentSkip to conversation

6.19.10-rc1 review

PATCH In review Greg Kroah-Hartman 17 participants 238 messages Mar 23 – Mar 25 Page 1 of 2

Subsystems (7)
lore
Share & tools
lore

Greg Kroah-Hartman

author maintainer
#0 lore raw

cover 6.19.10-rc1 review

This is the start of the stable review cycle for the 6.19.10 release. There are 220 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, 25 Mar 2026 13:44:33 +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.19.10-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.19.y
and the diffstat can be found below.

thanks,

greg k-h

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

Greg Kroah-Hartman <[email protected]>

    Linux 6.19.10-rc1

Guenter Roeck <[email protected]>
hwmon: (max6639) Fix pulses-per-revolution implementation

Daniele Ceraolo Spurio <[email protected]>
drm/xe/guc: Fail immediately on GuC load error

Suzuki K Poulose <[email protected]>
arm64: realm: Fix PTE_NS_SHARED for 52bit PA support

Josh Law <[email protected]>
tools/bootconfig: fix fd leak in load_xbc_file() on fstat failure

Josh Law <[email protected]>
lib/bootconfig: check xbc_init_node() return in override path

Kees Cook <[email protected]>
fs/tests: exec: Remove bad test vector

Rahul Bukte <[email protected]>
drm/i915/gt: Check set_default_submission() before deferencing

Hyunwoo Kim <[email protected]>
ksmbd: fix use-after-free in durable v2 replay of active file handles

Hyunwoo Kim <[email protected]>
ksmbd: fix use-after-free of share_conf in compound request

Jonas Karlman <[email protected]>
drm/bridge: dw-hdmi-qp: fix multi-channel audio output

Andy Nguyen <[email protected]>
drm/amd: fix dcn 2.01 check

Srinivasan Shanmugam <[email protected]>
drm/amd/display: Fix DisplayID not-found handling in parse_edid_displayid_vrr()

Joe Damato <[email protected]>
iommu/amd: Block identity domain when SNP enabled

Lizhi Hou <[email protected]>
iommu/sva: Fix crash in iommu_sva_unbind_device()

Antheas Kapenekakis <[email protected]>

    iommu: Fix mapping check for 0x0 to avoid re-mapping it

Ian Forbes <[email protected]>
drm/vmwgfx: Don't overwrite KMS surface dirty tracker

Felix Gu <[email protected]>
spi: amlogic-spisg: Fix memory leak in aml_spisg_probe()

Felix Gu <[email protected]>
spi: amlogic: spifc-a4: Remove redundant clock cleanup

Stanislav Kinsburskii <[email protected]>
mshv: Fix use-after-free in mshv_map_user_memory error path

Ben Horgan <[email protected]>
arm_mpam: Fix null pointer dereference when restoring bandwidth counters

Ard Biesheuvel <[email protected]>
x86/hyperv: Use __naked attribute to fix stackless C function

Kamal Dasu <[email protected]>
mtd: rawnand: brcmnand: skip DMA during panic write

Kamal Dasu <[email protected]>
mtd: rawnand: serialize lock/unlock against other NAND operations

Andrei Vagin <[email protected]>
binfmt_elf_fdpic: fix AUXV size calculation for ELF_HWCAP3 and ELF_HWCAP4

Kyle Meyer <[email protected]>
x86/platform/uv: Handle deconfigured sockets

William Roche <[email protected]>
x86/mce/amd: Check SMCA feature bit before accessing SMCA MSRs

Steven Rostedt <[email protected]>
tracing: Fix trace_marker copy link list updates

Steven Rostedt <[email protected]>
tracing: Fix failure to read user space from system call trace events

Masami Hiramatsu (Google) <[email protected]>
ring-buffer: Fix to update per-subbuf entries of persistent ring buffer

Breno Leitao <[email protected]>
perf/x86: Move event pointer setup earlier in x86_pmu_enable()

Dapeng Mi <[email protected]>
perf/x86/intel: Add missing branch counters constraint apply

Felix Gu <[email protected]>
irqchip/riscv-rpmi-sysmsi: Fix mailbox channel leak in rpmi_sysmsi_probe()

Gabor Juhos <[email protected]>
i2c: pxa: defer reset on Armada 3700 when recovery is used

Christophe JAILLET <[email protected]>
i2c: fsi: Fix a potential leak in fsi_i2c_probe()

Johan Hovold <[email protected]>
i2c: cp2615: fix serial string NULL-deref at probe

Sanman Pradhan <[email protected]>
hwmon: (pmbus/isl68137) Fix unchecked return value and use sysfs_emit()

Sanman Pradhan <[email protected]>
hwmon: (pmbus/mp2869) Check pmbus_read_byte_data() before using its return value

Sanman Pradhan <[email protected]>
hwmon: (pmbus/mp2975) Add error check for pmbus_read_word_data() return value

Sanman Pradhan <[email protected]>
hwmon: (pmbus/ina233) Add error check for pmbus_read_word_data() return value

Li Xiasong <[email protected]>
MPTCP: fix lock class name family in pm_nl_create_listen_socket

Weiming Shi <[email protected]>
icmp: fix NULL pointer dereference in icmp_tag_validation()

Anas Iqbal <[email protected]>
net: dsa: bcm_sf2: fix missing clk_disable_unprepare() in error paths

Jakub Kicinski <[email protected]>
net: shaper: protect from late creation of hierarchy

Jakub Kicinski <[email protected]>
net: shaper: protect late read accesses to the hierarchy

Muhammad Hammad Ijaz <[email protected]>
net: mvpp2: guard flow control update with global_tx_fc in buffer switching

Weiming Shi <[email protected]>
nfnetlink_osf: validate individual option lengths in fingerprints

Pablo Neira Ayuso <[email protected]>
netfilter: nf_tables: release flowtable after rcu grace period on error

Florian Westphal <[email protected]>
netfilter: bpf: defer hook memory release until rcu readers are done

Xiang Mei <[email protected]>
net: bonding: fix NULL deref in bond_debug_rlb_hash_show

Xiang Mei <[email protected]>
udp_tunnel: fix NULL deref caused by udp_sock_create6 when CONFIG_IPV6=n

Jianbo Liu <[email protected]>
net/mlx5e: Fix race condition during IPSec ESN update

Jianbo Liu <[email protected]>
net/mlx5e: Prevent concurrent access to IPSec ASO context

Cosmin Ratiu <[email protected]>
net/mlx5: qos: Restrict RTNL area to avoid a lock cycle

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

Fedor Pchelkin <[email protected]>
net: macb: fix uninitialized rx_fs_lock

Wesley Atwell <[email protected]>
netdevsim: drop PSP ext ref on forward failure

Rafael J. Wysocki <[email protected]>
ACPI: processor: Fix previous acpi_processor_errata_piix4() fix

Felix Fietkau <[email protected]>
wifi: mac80211: always free skb on ieee80211_tx_prepare_skb() failure

Guenter Roeck <[email protected]>
wifi: wlcore: Return -ENOMEM instead of -EAGAIN if there is not enough headroom

Xiang Mei <[email protected]>
wifi: mac80211: fix NULL deref in mesh_matches_local()

Michal Swiatkowski <[email protected]>
libie: prevent memleak in fwlog code

Petr Oros <[email protected]>
iavf: fix VLAN filter lost on add/delete race

Zdenek Bouska <[email protected]>
igc: fix page fault in XDP TX timestamps handling

Kohei Enju <[email protected]>

    igc: fix missing update of skb->tail in igc_xmit_frame()

Saket Dumbre <[email protected]>
ACPICA: Update the format of Arg3 of _DSM

Nikola Z. Ivanov <[email protected]>
net: usb: aqc111: Do not perform PM inside suspend callback

Daniel Borkmann <[email protected]>
clsact: Fix use-after-free in init/destroy rollback asymmetry

Tobi Gaertner <[email protected]>
net: usb: cdc_ncm: add ndpoffset to NDP32 nframes bounds check

Tobi Gaertner <[email protected]>
net: usb: cdc_ncm: add ndpoffset to NDP16 nframes bounds check

Lorenzo Bianconi <[email protected]>
net: airoha: Remove airoha_dev_stop() in airoha_remove()

Jamal Hadi Salim <[email protected]>
net/sched: teql: Fix double-free in teql_master_xmit

Jiayuan Chen <[email protected]>
net/smc: fix NULL dereference and UAF in smc_tcp_syn_recv_sock()

Eric Dumazet <[email protected]>
bonding: prevent potential infinite loop in bond_header_parse()

Bart Van Assche <[email protected]>
PM: runtime: Fix a race condition related to device removal

Rafael J. Wysocki <[email protected]>
sched: idle: Consolidate the handling of two special cases

Meghana Malladi <[email protected]>
net: ti: icssg-prueth: Fix memory leak in XDP_DROP for non-zero-copy mode

Dipayaan Roy <[email protected]>
net: mana: fix use-after-free in mana_hwc_destroy_channel() by reordering teardown

Justin Chen <[email protected]>
net: bcmgenet: increase WoL poll timeout

Guenter Roeck <[email protected]>
crypto: ccp - Fix leaking the same page twice

Jenny Guanni Qu <[email protected]>
netfilter: nf_conntrack_h323: check for zero length in DecodeQ931()

Jenny Guanni Qu <[email protected]>
netfilter: xt_time: use unsigned int for monthday bit shift

Pablo Neira Ayuso <[email protected]>
netfilter: xt_CT: drop pending enqueued packets on template removal

Pablo Neira Ayuso <[email protected]>
netfilter: nft_ct: drop pending enqueued packets on removal

Pablo Neira Ayuso <[email protected]>
nf_tables: nft_dynset: fix possible stateful expression memleak in error path

Jenny Guanni Qu <[email protected]>
netfilter: nf_conntrack_h323: fix OOB read in decode_int() CONS case

Eric Woudstra <[email protected]>
netfilter: nf_flow_table_ip: reset mac header before vlan push

Lukas Johannes Möller <[email protected]>
netfilter: nf_conntrack_sip: fix Content-Length u32 truncation in sip_help_tcp()

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

Hyunwoo Kim <[email protected]>
netfilter: ctnetlink: fix use-after-free in ctnetlink_dump_exp_ct()

Sabrina Dubroca <[email protected]>
mpls: add missing unregister_netdevice_notifier to mpls_init

Eric Dumazet <[email protected]>
ip_tunnel: adapt iptunnel_xmit_stats() to NETDEV_PCPU_STAT_DSTATS

Jiayuan Chen <[email protected]>
net/rose: fix NULL pointer dereference in rose_transmit_link on reconnect

Hyunwoo Kim <[email protected]>
bridge: cfm: Fix race condition in peer_mep deletion

Kuniyuki Iwashima <[email protected]>
af_unix: Give up GC if MSG_PEEK intervened.

Dmitry Baryshkov <[email protected]>
Bluetooth: qca: fix ROM version reading on WCN3998 chips

Shaurya Rane <[email protected]>
Bluetooth: L2CAP: Fix use-after-free in l2cap_unregister_user

Luiz Augusto von Dentz <[email protected]>
Bluetooth: HIDP: Fix possible UAF

Wang Tao <[email protected]>
Bluetooth: MGMT: Fix list corruption and UAF in command complete handlers

Michael Grzeschik <[email protected]>
Bluetooth: hci_sync: Fix hci_le_create_conn_sync

Luiz Augusto von Dentz <[email protected]>
Bluetooth: ISO: Fix defer tests being unstable

Christian Eggers <[email protected]>
Bluetooth: SMP: make SM/PER/KDU/BI-04-C happy

Christian Eggers <[email protected]>
Bluetooth: LE L2CAP: Disconnect if sum of payload sizes exceed SDU

Christian Eggers <[email protected]>
Bluetooth: LE L2CAP: Disconnect if received packet's SDU exceeds IMTU

Cristian Marussi <[email protected]>
firmware: arm_scmi: Fix NULL dereference on notify error path

Felix Gu <[email protected]>
firmware: arm_scpi: Fix device_node reference leak in probe path

Yeoreum Yun <[email protected]>
firmware: arm_ffa: Remove vm_id argument in ffa_rxtx_unmap()

Geert Uytterhoeven <[email protected]>
arm64: dts: renesas: r8a78000: Fix out-of-range SPI interrupt numbers

Claudiu Beznea <[email protected]>
arm64: dts: renesas: rzg3s-smarc-som: Set bypass for Versa3 PLL2

Lad Prabhakar <[email protected]>
arm64: dts: renesas: r9a09g087: Fix CPG register region sizes

Lad Prabhakar <[email protected]>
arm64: dts: renesas: r9a09g077: Fix CPG register region sizes

Fabrizio Castro <[email protected]>

    arm64: dts: renesas: r9a09g057: Remove wdt{0,2,3} nodes

Lad Prabhakar <[email protected]>
arm64: dts: renesas: rzv2-evk-cn15-sd: Add ramp delay for SD0 regulator

Lad Prabhakar <[email protected]>
arm64: dts: renesas: rzt2h-n2h-evk: Add ramp delay for SD0 card regulator

Peddolla Harshavardhan Reddy <[email protected]>

    wifi: cfg80211: cancel pmsr_free_wk in cfg80211_pmsr_wdev_down

Kuniyuki Iwashima <[email protected]>
wifi: mac80211: Fix static_branch_dec() underflow for aql_disable.

Nicolas Cavallari <[email protected]>
wifi: mac80211: use jiffies_delta_to_msecs() for sta_info inactive times

Johannes Berg <[email protected]>
wifi: mac80211: remove keys after disabling beaconing

Matthew Wilcox <[email protected]>
tee: shm: Remove refcounting of kernel pages

Chen Ni <[email protected]>
soc: fsl: cpm1: qmc: Fix error check for devm_ioremap_resource() in qmc_qe_init_resources()

Richard Genoud <[email protected]>
soc: fsl: qbman: fix race condition in qman_destroy_fq

Shawn Lin <[email protected]>
soc: rockchip: grf: Add missing of_node_put() when returning

Felix Gu <[email protected]>
cache: ax45mp: Fix device node reference leak in ax45mp_cache_init()

Felix Gu <[email protected]>
cache: starfive: fix device node leak in starlink_cache_init()

Zilin Guan <[email protected]>
soc: microchip: mpfs: Fix memory leak in mpfs_sys_controller_probe()

ZhengYuan Huang <[email protected]>
btrfs: tree-checker: fix misleading root drop_level error message

Filipe Manana <[email protected]>
btrfs: log new dentries when logging parent dir of a conflicting inode

Luiz Augusto von Dentz <[email protected]>
Bluetooth: L2CAP: Fix accepting multiple L2CAP_ECRED_CONN_REQ

Matthew Brost <[email protected]>
drm/xe: Open-code GGTT MMIO access protection

Sanjay Yadav <[email protected]>
drm/xe: Fix missing runtime PM reference in ccs_mode_store

Matthew Brost <[email protected]>
drm/xe: Always kill exec queues in xe_guc_submit_pause_abort

Ashutosh Dixit <[email protected]>
drm/xe/oa: Allow reading after disabling OA stream

Zhanjun Dong <[email protected]>
drm/xe/guc: Ensure CT state transitions via STOP before DISABLED

Jouni Högander <[email protected]>
drm/i915/psr: Disable PSR on update_m_n and update_lrr

Jouni Högander <[email protected]>
drm/i915/psr: Compute PSR entry_setup_frames into intel_crtc_state

Imre Deak <[email protected]>
drm/i915/dmc: Fix an unlikely NULL pointer deference at probe

Alex Deucher <[email protected]>
drm/amdgpu: rework how we handle TLB fences

Jesse.Zhang <[email protected]>
drm/amdgpu: Limit BO list entry count to prevent resource exhaustion

Alex Deucher <[email protected]>
drm/amdgpu: apply state adjust rules to some additional HAINAN vairants

Alex Deucher <[email protected]>
drm/radeon: apply state adjust rules to some additional HAINAN vairants

Alessio Belle <[email protected]>
drm/imagination: Synchronize interrupts before suspending the GPU

Alessio Belle <[email protected]>
drm/imagination: Fix deadlock in soft reset sequence

Alex Deucher <[email protected]>
drm/amdgpu/mmhub4.1.0: add bounds checking for cid

Alex Deucher <[email protected]>
drm/amdgpu/mmhub3.0: add bounds checking for cid

Alex Deucher <[email protected]>
drm/amdgpu/mmhub3.0.2: add bounds checking for cid

Alex Deucher <[email protected]>
drm/amdgpu/mmhub3.0.1: add bounds checking for cid

Alex Deucher <[email protected]>
drm/amdgpu/mmhub2.3: add bounds checking for cid

Alex Deucher <[email protected]>
drm/amdgpu/mmhub2.0: add bounds checking for cid

Alex Deucher <[email protected]>
drm/amdgpu/gmc9.0: add bounds checking for cid

Xi Ruoyao <[email protected]>

    drm/amd/display: Wrap dcn32_override_min_req_memclk() in DC_FP_{START, END}

Maarten Lankhorst <[email protected]>
drm: Fix use-after-free on framebuffers and property blobs when calling drm_dev_unplug

Maciej Andrzejewski ICEYE <[email protected]>
serial: uartlite: fix PM runtime usage count underflow on probe

Jiayuan Chen <[email protected]>
serial: core: fix infinite loop in handle_tx() for PORT_UNKNOWN

Ilpo Järvinen <[email protected]>
serial: 8250_dw: Ensure BUSY is deasserted

Ilpo Järvinen <[email protected]>
serial: 8250: Add late synchronize_irq() to shutdown to handle DW UART BUSY

Ilpo Järvinen <[email protected]>
serial: 8250_dw: Rework IIR_NO_INT handling to stop interrupt storm

Ilpo Järvinen <[email protected]>
serial: 8250_dw: Rework dw8250_handle_irq() locking and IIR handling

Ilpo Järvinen <[email protected]>

    serial: 8250: Add serial8250_handle_irq_locked()

Ilpo Järvinen <[email protected]>
serial: 8250_dw: Avoid unnecessary LCR writes

Ilpo Järvinen <[email protected]>
serial: 8250: Protect LCR write in shutdown

Peng Zhang <[email protected]>
serial: 8250: always disable IRQ during THRE test

Raul E Rangel <[email protected]>
serial: 8250: Fix TX deadlock when using DMA

Martin Roukala (né Peres) <[email protected]>

    serial: 8250_pci: add support for the AX99100

Nicolas Pitre <[email protected]>
vt: save/restore unicode screen buffer for alternate screen

Jens Axboe <[email protected]>
io_uring/kbuf: propagate BUF_MORE through early buffer commit path

Jens Axboe <[email protected]>
io_uring/kbuf: fix missing BUF_MORE for incremental buffers at EOF

Jens Axboe <[email protected]>
io_uring/poll: fix multishot recv missing EOF on wakeup race

Lu Baolu <[email protected]>
iommu/vt-d: Only handle IOPF for SVA when PRI is supported

Guanghui Feng <[email protected]>
iommu/vt-d: Fix intel iommu iotlb sync hardlockup and retry

Finn Thain <[email protected]>
mtd: Avoid boot crash in RedBoot partition table parser

Chen Ni <[email protected]>
mtd: rawnand: cadence: Fix error check for dma_alloc_coherent() in cadence_nand_init()

Olivier Sobrie <[email protected]>
mtd: rawnand: pl353: make sure optimal timings are applied

Miquel Raynal <[email protected]>
mtd: spi-nor: Fix RDCR controller capability core check

Johan Hovold <[email protected]>
spi: fix statistics allocation

Johan Hovold <[email protected]>
spi: fix use-after-free on controller registration failure

Maíra Canal <[email protected]>
pmdomain: bcm: bcm2835-power: Increase ASB control timeout

Adam Ford <[email protected]>
pmdomain: mediatek: Fix power domain count

Luke Wang <[email protected]>
mmc: sdhci: fix timing selection for 1-bit bus width

Matthew Schwartz <[email protected]>
mmc: sdhci-pci-gli: fix GL9750 DMA write corruption

Damien Le Moal <[email protected]>
ata: libata-scsi: report correct sense field pointer in ata_scsiop_maint_in()

Damien Le Moal <[email protected]>
ata: libata-core: disable LPM on ADATA SU680 SSD

Corey Minyard <[email protected]>
ipmi:msghandler: Handle error returns from the SMI sender

Corey Minyard <[email protected]>
ipmi: Consolidate the run to completion checking for xmit msgs lock

Varun Gupta <[email protected]>
drm/xe: Fix memory leak in xe_vm_madvise_ioctl

Shyam Prasad N <[email protected]>
cifs: open files should not hold ref on superblock

Thorsten Blum <[email protected]>

    crypto: atmel-sha204a - Fix OOM ->tfm_count leak

Breno Leitao <[email protected]>
netconsole: fix sysdata_release_enabled_show checking wrong flag

Muhammad Amirul Asyraf Mohamad Jamian <[email protected]>
firmware: stratix10-svc: Add Multi SVC clients support

Dan Carpenter <[email protected]>
firmware: stratix10-svc: Delete some stray tabs

Kevin Hao <[email protected]>
net: macb: Reinitialize tx/rx queue pointer registers and rx ring during resume

Kevin Hao <[email protected]>
net: macb: Introduce gem_init_rx_ring()

Tiezhu Yang <[email protected]>

    LoongArch: Check return values for set_memory_{rw,rox}

Jouni Högander <[email protected]>
drm/i915/psr: Write DSC parameters on Selective Update in ET mode

Jouni Högander <[email protected]>
drm/i915/dsc: Add helper for writing DSC Selective Update ET parameters

Jouni Högander <[email protected]>
drm/i915/dsc: Add Selective Update register definitions

Namjae Jeon <[email protected]>
ksmbd: use volume UUID in FS_OBJECT_ID_INFORMATION

Namjae Jeon <[email protected]>

    ksmbd: unset conn->binding on failed binding request

Paulo Alcantara <[email protected]>
smb: client: fix krb5 mount with username option

Mario Limonciello <[email protected]>
drm/amd: Fix hang on amdgpu unload by using pci_dev_is_disconnected()

Lukas Johannes Möller <[email protected]>
Bluetooth: L2CAP: Validate L2CAP_INFO_RSP payload length before access

Lukas Johannes Möller <[email protected]>
Bluetooth: L2CAP: Fix type confusion in l2cap_ecred_reconf_rsp()

AlanSong-oc <[email protected]>
crypto: padlock-sha - Disable for Zhaoxin processor

Felix Fietkau <[email protected]>
mac80211: fix crash in ieee80211_chan_bw_change for AP_VLAN stations

Yang Yang <[email protected]>
batman-adv: avoid OGM aggregation when skb tailroom is insufficient

Helge Deller <[email protected]>
parisc: Flush correct cache in cacheflush() syscall

Junrui Luo <[email protected]>
bnxt_en: fix OOB access in DBG_BUF_PRODUCER async event handler

Fedor Pchelkin <[email protected]>
net: macb: fix use-after-free access to PTP clock

Ian Ray <[email protected]>
NFC: nxp-nci: allow GPIOs to sleep

Tiezhu Yang <[email protected]>
LoongArch: No need to flush icache if text copy failed

Tiezhu Yang <[email protected]>
LoongArch: Give more information if kmem access failed

Wei Yang <[email protected]>
mm/huge_memory: fix early failure try_to_migrate() when split huge pmd for shared THP

Chris Down <[email protected]>
mm/huge_memory: fix use of NULL folio in move_pages_huge_pmd()

Dev Jain <[email protected]>
mm/rmap: fix incorrect pte restoration for lazyfree folios

Thorsten Blum <[email protected]>
crash_dump: don't log dm-crypt key bytes in read_key_from_user_keying

Ira Weiny <[email protected]>
nvdimm/bus: Fix potential use after free in asynchronous initialization

Jeff Layton <[email protected]>
sunrpc: fix cache_request leak in cache_release

Benjamin Tissoires <[email protected]>
HID: bpf: prevent buffer overflow in hid_hw_request

Benjamin Tissoires <[email protected]>
selftests/hid: fix compilation when bpf_wq and hid_device are not exported

Jeff Layton <[email protected]>
nfsd: fix heap overflow in NFSv4.0 LOCK replay cache

Chuck Lever <[email protected]>
NFSD: Hold net reference for the lifetime of /proc/fs/nfs/exports fd

Chuck Lever <[email protected]>
NFSD: Defer sub-object cleanup in export put callbacks

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

Diffstat:

 Documentation/netlink/specs/net_shaper.yaml        |  12 +-
 Makefile                                           |   4 +-
 arch/arm64/boot/dts/renesas/r8a78000.dtsi          |  16 +-
 arch/arm64/boot/dts/renesas/r9a09g057.dtsi         |  30 --
 arch/arm64/boot/dts/renesas/r9a09g077.dtsi         |   4 +-
 arch/arm64/boot/dts/renesas/r9a09g087.dtsi         |   4 +-
 arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi   |   2 +-
 .../boot/dts/renesas/rzt2h-n2h-evk-common.dtsi     |   1 +
 arch/arm64/boot/dts/renesas/rzv2-evk-cn15-sd.dtso  |   1 +
 arch/arm64/kernel/rsi.c                            |   3 +-
 arch/loongarch/include/asm/uaccess.h               |  14 +-
 arch/loongarch/kernel/inst.c                       |  21 +-
 arch/parisc/kernel/cache.c                         |   4 +-
 arch/x86/events/core.c                             |   3 +-
 arch/x86/events/intel/core.c                       |  31 ++-
 arch/x86/hyperv/hv_crash.c                         | 100 +++----
 arch/x86/kernel/apic/x2apic_uv_x.c                 |  18 +-
 arch/x86/kernel/cpu/mce/amd.c                      |  17 +-
 drivers/acpi/acpi_processor.c                      |  15 +-
 drivers/acpi/acpica/acpredef.h                     |   2 +-
 drivers/ata/libata-core.c                          |   3 +
 drivers/ata/libata-scsi.c                          |   2 +-
 drivers/base/power/runtime.c                       |   1 +
 drivers/bluetooth/btqca.c                          |   2 +
 drivers/cache/ax45mp_cache.c                       |   4 +-
 drivers/cache/starfive_starlink_cache.c            |   4 +-
 drivers/char/ipmi/ipmi_msghandler.c                | 144 ++++++----
 drivers/crypto/atmel-sha204a.c                     |   5 +-
 drivers/crypto/ccp/sev-dev.c                       |   4 +-
 drivers/crypto/padlock-sha.c                       |   7 +
 drivers/firewire/net.c                             |   5 +-
 drivers/firmware/arm_ffa/driver.c                  |   8 +-
 drivers/firmware/arm_scmi/notify.c                 |   4 +-
 drivers/firmware/arm_scpi.c                        |   5 +-
 drivers/firmware/stratix10-svc.c                   | 240 ++++++++--------
 drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c        |   4 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c         |   4 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c             |   7 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h             |   2 +
 drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c              |  21 +-
 drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c            |   9 +-
 drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c            |   3 +-
 drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c            |   3 +-
 drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c          |   3 +-
 drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_2.c          |   3 +-
 drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c          |   3 +-
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c  |   4 +-
 drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c   |   8 +-
 .../amd/display/dc/resource/dcn32/dcn32_resource.c |   3 +
 drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c         |   4 +-
 drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c       |   2 +-
 drivers/gpu/drm/drm_file.c                         |   5 +-
 drivers/gpu/drm/drm_mode_config.c                  |   9 +-
 .../drm/i915/display/intel_display_power_well.c    |   2 +-
 drivers/gpu/drm/i915/display/intel_display_types.h |   1 +
 drivers/gpu/drm/i915/display/intel_dmc.c           |   3 +-
 drivers/gpu/drm/i915/display/intel_psr.c           |  17 +-
 drivers/gpu/drm/i915/display/intel_vdsc.c          |  23 ++
 drivers/gpu/drm/i915/display/intel_vdsc.h          |   3 +
 drivers/gpu/drm/i915/display/intel_vdsc_regs.h     |  12 +
 drivers/gpu/drm/i915/gt/intel_engine_cs.c          |   3 +-
 drivers/gpu/drm/imagination/pvr_device.c           |  17 --
 drivers/gpu/drm/imagination/pvr_power.c            |  22 +-
 drivers/gpu/drm/radeon/si_dpm.c                    |   4 +-
 drivers/gpu/drm/vmwgfx/vmwgfx_kms.c                |   3 +-
 drivers/gpu/drm/xe/xe_ggtt.c                       |  10 +-
 drivers/gpu/drm/xe/xe_ggtt_types.h                 |   5 +-
 drivers/gpu/drm/xe/xe_gt_ccs_mode.c                |   2 +
 drivers/gpu/drm/xe/xe_guc.c                        |   6 +-
 drivers/gpu/drm/xe/xe_guc_ct.c                     |   1 +
 drivers/gpu/drm/xe/xe_guc_submit.c                 |   3 +-
 drivers/gpu/drm/xe/xe_oa.c                         |   7 +-
 drivers/gpu/drm/xe/xe_vm_madvise.c                 |   3 +-
 drivers/hid/bpf/hid_bpf_dispatch.c                 |   2 +
 drivers/hv/mshv_root_main.c                        |   2 +-
 drivers/hwmon/max6639.c                            |  10 +-
 drivers/hwmon/pmbus/ina233.c                       |   2 +
 drivers/hwmon/pmbus/isl68137.c                     |   7 +-
 drivers/hwmon/pmbus/mp2869.c                       |  35 ++-
 drivers/hwmon/pmbus/mp2975.c                       |   2 +
 drivers/i2c/busses/i2c-cp2615.c                    |   3 +
 drivers/i2c/busses/i2c-fsi.c                       |   1 +
 drivers/i2c/busses/i2c-pxa.c                       |  17 +-
 drivers/iommu/amd/iommu.c                          |  15 +-
 drivers/iommu/intel/dmar.c                         |   3 +-
 drivers/iommu/intel/svm.c                          |  12 +-
 drivers/iommu/iommu-sva.c                          |  12 +-
 drivers/iommu/iommu.c                              |   6 +-
 drivers/irqchip/irq-riscv-rpmi-sysmsi.c            |   1 +
 drivers/mmc/host/sdhci-pci-gli.c                   |   9 +
 drivers/mmc/host/sdhci.c                           |   9 +-
 drivers/mtd/nand/raw/brcmnand/brcmnand.c           |   6 +-
 drivers/mtd/nand/raw/cadence-nand-controller.c     |   2 +-
 drivers/mtd/nand/raw/nand_base.c                   |  14 +-
 drivers/mtd/nand/raw/pl35x-nand-controller.c       |   3 +
 drivers/mtd/parsers/redboot.c                      |   6 +-
 drivers/mtd/spi-nor/core.c                         |   2 +-
 drivers/net/bonding/bond_debugfs.c                 |  16 +-
 drivers/net/bonding/bond_main.c                    |   8 +-
 drivers/net/dsa/bcm_sf2.c                          |   8 +-
 drivers/net/ethernet/airoha/airoha_eth.c           |   1 -
 drivers/net/ethernet/broadcom/bnxt/bnxt.c          |   2 +
 drivers/net/ethernet/broadcom/bnxt/bnxt.h          |   2 +-
 drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c |   2 +-
 drivers/net/ethernet/cadence/macb_main.c           |  26 +-
 drivers/net/ethernet/cadence/macb_ptp.c            |   4 +-
 drivers/net/ethernet/intel/iavf/iavf_main.c        |   9 +-
 drivers/net/ethernet/intel/igc/igc.h               |   2 +
 drivers/net/ethernet/intel/igc/igc_main.c          |  14 +-
 drivers/net/ethernet/intel/igc/igc_ptp.c           |  33 +++
 drivers/net/ethernet/intel/libie/fwlog.c           |  49 +++-
 drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c    |   4 +-
 .../ethernet/mellanox/mlx5/core/en_accel/ipsec.h   |   1 +
 .../mellanox/mlx5/core/en_accel/ipsec_offload.c    |  52 ++--
 drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c  |  23 +-
 drivers/net/ethernet/microsoft/mana/hw_channel.c   |   6 +-
 drivers/net/ethernet/ti/icssg/icssg_common.c       |   5 +
 drivers/net/netconsole.c                           |   2 +-
 drivers/net/netdevsim/netdev.c                     |   5 +-
 drivers/net/usb/aqc111.c                           |  12 +-
 drivers/net/usb/cdc_ncm.c                          |  10 +-
 drivers/net/wireless/ath/ath9k/channel.c           |   6 +-
 drivers/net/wireless/mediatek/mt76/scan.c          |   4 +-
 drivers/net/wireless/ti/wlcore/tx.c                |   2 +-
 drivers/net/wireless/virtual/mac80211_hwsim.c      |   1 -
 drivers/nfc/nxp-nci/i2c.c                          |   4 +-
 drivers/nvdimm/bus.c                               |   5 +-
 drivers/pmdomain/bcm/bcm2835-power.c               |  12 +-
 drivers/pmdomain/mediatek/mtk-pm-domains.c         |   2 +-
 drivers/resctrl/mpam_devices.c                     |   2 +
 drivers/soc/fsl/qbman/qman.c                       |  24 +-
 drivers/soc/fsl/qe/qmc.c                           |   4 +-
 drivers/soc/microchip/mpfs-sys-controller.c        |  13 +-
 drivers/soc/rockchip/grf.c                         |   1 +
 drivers/spi/spi-amlogic-spifc-a4.c                 |  46 +---
 drivers/spi/spi-amlogic-spisg.c                    |  12 +-
 drivers/spi/spi.c                                  |  25 +-
 drivers/tee/tee_shm.c                              |  27 --
 drivers/tty/serial/8250/8250.h                     |  25 ++
 drivers/tty/serial/8250/8250_dma.c                 |  15 +
 drivers/tty/serial/8250/8250_dw.c                  | 304 ++++++++++++++++-----
 drivers/tty/serial/8250/8250_pci.c                 |  17 ++
 drivers/tty/serial/8250/8250_port.c                |  75 +++--
 drivers/tty/serial/serial_core.c                   |   5 +-
 drivers/tty/serial/uartlite.c                      |   1 +
 drivers/tty/vt/vt.c                                |   8 +
 fs/binfmt_elf_fdpic.c                              |   6 +
 fs/btrfs/tree-checker.c                            |   2 +-
 fs/btrfs/tree-log.c                                |   6 +
 fs/nfsd/export.c                                   |  63 ++++-
 fs/nfsd/export.h                                   |   7 +-
 fs/nfsd/nfs4xdr.c                                  |   9 +-
 fs/nfsd/nfsctl.c                                   |  22 +-
 fs/nfsd/state.h                                    |  17 +-
 fs/smb/client/cifsfs.c                             |   7 +-
 fs/smb/client/cifsproto.h                          |   1 +
 fs/smb/client/connect.c                            |   4 +
 fs/smb/client/file.c                               |  11 -
 fs/smb/client/misc.c                               |  42 +++
 fs/smb/client/trace.h                              |   2 +
 fs/smb/server/smb2pdu.c                            |  17 +-
 fs/tests/exec_kunit.c                              |   3 -
 include/linux/auxvec.h                             |   2 +-
 include/linux/console_struct.h                     |   1 +
 include/linux/etherdevice.h                        |   3 +-
 .../linux/firmware/intel/stratix10-svc-client.h    |   8 +-
 include/linux/if_ether.h                           |   3 +-
 include/linux/io_uring_types.h                     |   3 +
 include/linux/netdevice.h                          |   9 +-
 include/linux/serial_8250.h                        |   1 +
 include/net/ip_tunnels.h                           |  28 +-
 include/net/mac80211.h                             |   4 +-
 include/net/netfilter/nf_tables.h                  |   2 +
 include/net/sch_generic.h                          |  33 +++
 include/net/udp_tunnel.h                           |   2 +-
 io_uring/kbuf.c                                    |  14 +-
 io_uring/poll.c                                    |   9 +-
 kernel/crash_dump_dm_crypt.c                       |   4 +-
 kernel/sched/idle.c                                |  30 +-
 kernel/trace/ring_buffer.c                         |   2 +-
 kernel/trace/trace.c                               |  36 ++-
 lib/bootconfig.c                                   |   3 +-
 mm/huge_memory.c                                   |   3 +-
 mm/rmap.c                                          |  21 +-
 net/batman-adv/bat_iv_ogm.c                        |   3 +
 net/bluetooth/hci_conn.c                           |   4 +-
 net/bluetooth/hci_sync.c                           |   2 +-
 net/bluetooth/hidp/core.c                          |  16 +-
 net/bluetooth/l2cap_core.c                         |  51 ++--
 net/bluetooth/mgmt.c                               |   7 +-
 net/bluetooth/smp.c                                |   2 +-
 net/bridge/br_cfm.c                                |   4 +-
 net/ethernet/eth.c                                 |   9 +-
 net/ipv4/icmp.c                                    |   4 +-
 net/ipv4/ip_gre.c                                  |   3 +-
 net/ipv6/exthdrs.c                                 |   4 +
 net/ipv6/seg6_hmac.c                               |   2 +
 net/mac80211/cfg.c                                 |  12 +-
 net/mac80211/chan.c                                |   6 +-
 net/mac80211/debugfs.c                             |  14 +-
 net/mac80211/mesh.c                                |   3 +
 net/mac80211/sta_info.c                            |   7 +-
 net/mac80211/tx.c                                  |   4 +-
 net/mac802154/iface.c                              |   4 +-
 net/mpls/af_mpls.c                                 |   1 +
 net/mptcp/pm_kernel.c                              |   2 +-
 net/netfilter/nf_bpf_link.c                        |   2 +-
 net/netfilter/nf_conntrack_h323_asn1.c             |   4 +
 net/netfilter/nf_conntrack_netlink.c               |  28 +-
 net/netfilter/nf_conntrack_proto_sctp.c            |   3 +-
 net/netfilter/nf_conntrack_sip.c                   |   6 +-
 net/netfilter/nf_flow_table_ip.c                   |   1 +
 net/netfilter/nf_tables_api.c                      |   5 +-
 net/netfilter/nfnetlink_osf.c                      |  13 +
 net/netfilter/nft_ct.c                             |   4 +
 net/netfilter/nft_dynset.c                         |  10 +-
 net/netfilter/xt_CT.c                              |   4 +
 net/netfilter/xt_time.c                            |   4 +-
 net/phonet/af_phonet.c                             |   5 +-
 net/rose/af_rose.c                                 |   5 +
 net/sched/sch_generic.c                            |  27 --
 net/sched/sch_ingress.c                            |  14 +-
 net/sched/sch_teql.c                               |   7 +-
 net/shaper/shaper.c                                | 160 ++++++-----
 net/shaper/shaper_nl_gen.c                         |  12 +-
 net/shaper/shaper_nl_gen.h                         |   5 +
 net/smc/af_smc.c                                   |  23 +-
 net/smc/smc.h                                      |   5 +
 net/smc/smc_close.c                                |   2 +-
 net/sunrpc/cache.c                                 |  26 +-
 net/unix/af_unix.c                                 |   2 +
 net/unix/af_unix.h                                 |   1 +
 net/unix/garbage.c                                 |  79 ++++--
 net/wireless/pmsr.c                                |   1 +
 tools/bootconfig/main.c                            |   7 +-
 .../testing/selftests/hid/progs/hid_bpf_helpers.h  |  12 +
 236 files changed, 2113 insertions(+), 1069 deletions(-)
author maintainer
#1 lore raw

PATCH 1/220 NFSD: Defer sub-object cleanup in export put callbacks

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

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

From: Chuck Lever <[email protected]>

commit 48db892356d6cb80f6942885545de4a6dd8d2a29 upstream.

svc_export_put() calls path_put() and auth_domain_put() immediately when the last reference drops, before the RCU grace period. RCU readers in e_show() and c_show() access both ex_path (via seq_path/d_path) and ex_client->name (via seq_escape) without holding a reference. If cache_clean removes the entry and drops the last reference concurrently, the sub-objects are freed while still in use, producing a NULL pointer dereference in d_path.

Commit 2530766492ec ("nfsd: fix UAF when access ex_uuid or ex_stats") moved kfree of ex_uuid and ex_stats into the call_rcu callback, but left path_put() and auth_domain_put() running before the grace period because both may sleep and call_rcu callbacks execute in softirq context.

Replace call_rcu/kfree_rcu with queue_rcu_work(), which defers the callback until after the RCU grace period and executes it in process context where sleeping is permitted. This allows path_put() and auth_domain_put() to be moved into the deferred callback alongside the other resource releases. Apply the same fix to expkey_put(), which has the identical pattern with ek_path and ek_client.

A dedicated workqueue scopes the shutdown drain to only NFSD export release work items; flushing the shared system_unbound_wq would stall on unrelated work from other subsystems. nfsd_export_shutdown() uses rcu_barrier() followed by flush_workqueue() to ensure all deferred release callbacks complete before the export caches are destroyed.

Fixes c224edca7af0 ("nfsd: no need get cache ref when protected by rcu")
Fixes 1b10f0b603c0 ("SUNRPC: no need get cache ref when protected by rcu")
---
 fs/nfsd/export.c |   63 +++++++++++++++++++++++++++++++++++++++++++++++--------
 fs/nfsd/export.h |    7 ++++--
 fs/nfsd/nfsctl.c |    8 ++++++
 3 files changed, 66 insertions(+), 12 deletions(-)
fs/nfsd/export.c +54 -9
@@ -36,19 +36,30 @@
  * second map contains a reference to the entry in the first map.
  */
 
+static struct workqueue_struct *nfsd_export_wq;
+
 #define	EXPKEY_HASHBITS		8
 #define	EXPKEY_HASHMAX		(1 << EXPKEY_HASHBITS)
 #define	EXPKEY_HASHMASK		(EXPKEY_HASHMAX -1)
 
-static void expkey_put(struct kref *ref)
+static void expkey_release(struct work_struct *work)
 {
-	struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref);
+	struct svc_expkey *key = container_of(to_rcu_work(work),
+					      struct svc_expkey, ek_rwork);
 
 	if (test_bit(CACHE_VALID, &key->h.flags) &&
 	    !test_bit(CACHE_NEGATIVE, &key->h.flags))
 		path_put(&key->ek_path);
 	auth_domain_put(key->ek_client);
-	kfree_rcu(key, ek_rcu);
+	kfree(key);
+}
+
+static void expkey_put(struct kref *ref)
+{
+	struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref);
+
+	INIT_RCU_WORK(&key->ek_rwork, expkey_release);
+	queue_rcu_work(nfsd_export_wq, &key->ek_rwork);
 }
 
 static int expkey_upcall(struct cache_detail *cd, struct cache_head *h)
@@ -353,11 +364,13 @@ static void export_stats_destroy(struct
 					    EXP_STATS_COUNTERS_NUM);
 }
 
-static void svc_export_release(struct rcu_head *rcu_head)
+static void svc_export_release(struct work_struct *work)
 {
-	struct svc_export *exp = container_of(rcu_head, struct svc_export,
-			ex_rcu);
+	struct svc_export *exp = container_of(to_rcu_work(work),
+					      struct svc_export, ex_rwork);
 
+	path_put(&exp->ex_path);
+	auth_domain_put(exp->ex_client);
 	nfsd4_fslocs_free(&exp->ex_fslocs);
 	export_stats_destroy(exp->ex_stats);
 	kfree(exp->ex_stats);
@@ -369,9 +382,8 @@ static void svc_export_put(struct kref *
 {
 	struct svc_export *exp = container_of(ref, struct svc_export, h.ref);
 
-	path_put(&exp->ex_path);
-	auth_domain_put(exp->ex_client);
-	call_rcu(&exp->ex_rcu, svc_export_release);
+	INIT_RCU_WORK(&exp->ex_rwork, svc_export_release);
+	queue_rcu_work(nfsd_export_wq, &exp->ex_rwork);
 }
 
 static int svc_export_upcall(struct cache_detail *cd, struct cache_head *h)
@@ -1480,6 +1492,36 @@ const struct seq_operations nfs_exports_
 	.show	= e_show,
 };
 
+/**
+ * nfsd_export_wq_init - allocate the export release workqueue
+ *
+ * Called once at module load. The workqueue runs deferred svc_export and
+ * svc_expkey release work scheduled by queue_rcu_work() in the cache put
+ * callbacks.
+ *
+ * Return values:
+ *   %0: workqueue allocated
+ *   %-ENOMEM: allocation failed
+ */
+int nfsd_export_wq_init(void)
+{
+	nfsd_export_wq = alloc_workqueue("nfsd_export", WQ_UNBOUND, 0);
+	if (!nfsd_export_wq)
+		return -ENOMEM;
+	return 0;
+}
+
+/**
+ * nfsd_export_wq_shutdown - drain and free the export release workqueue
+ *
+ * Called once at module unload. Per-namespace teardown in
+ * nfsd_export_shutdown() has already drained all deferred work.
+ */
+void nfsd_export_wq_shutdown(void)
+{
+	destroy_workqueue(nfsd_export_wq);
+}
+
 /*
  * Initialize the exports module.
  */
@@ -1541,6 +1583,9 @@ nfsd_export_shutdown(struct net *net)
 
 	cache_unregister_net(nn->svc_expkey_cache, net);
 	cache_unregister_net(nn->svc_export_cache, net);
+	/* Drain deferred export and expkey release work. */
+	rcu_barrier();
+	flush_workqueue(nfsd_export_wq);
 	cache_destroy_net(nn->svc_expkey_cache, net);
 	cache_destroy_net(nn->svc_export_cache, net);
 	svcauth_unix_purge(net);
fs/nfsd/export.h +5 -2
@@ -7,6 +7,7 @@
 
 #include <linux/sunrpc/cache.h>
 #include <linux/percpu_counter.h>
+#include <linux/workqueue.h>
 #include <uapi/linux/nfsd/export.h>
 #include <linux/nfs4.h>
 
@@ -75,7 +76,7 @@ struct svc_export {
 	u32			ex_layout_types;
 	struct nfsd4_deviceid_map *ex_devid_map;
 	struct cache_detail	*cd;
-	struct rcu_head		ex_rcu;
+	struct rcu_work		ex_rwork;
 	unsigned long		ex_xprtsec_modes;
 	struct export_stats	*ex_stats;
 };
@@ -92,7 +93,7 @@ struct svc_expkey {
 	u32			ek_fsid[6];
 
 	struct path		ek_path;
-	struct rcu_head		ek_rcu;
+	struct rcu_work		ek_rwork;
 };
 
 #define EX_ISSYNC(exp)		(!((exp)->ex_flags & NFSEXP_ASYNC))
@@ -110,6 +111,8 @@ __be32 check_nfsd_access(struct svc_expo
 /*
  * Function declarations
  */
+int			nfsd_export_wq_init(void);
+void			nfsd_export_wq_shutdown(void);
 int			nfsd_export_init(struct net *);
 void			nfsd_export_shutdown(struct net *);
 void			nfsd_export_flush(struct net *);
fs/nfsd/nfsctl.c +7 -1
@@ -2252,9 +2252,12 @@ static int __init init_nfsd(void)
 	if (retval)
 		goto out_free_pnfs;
 	nfsd_lockd_init();	/* lockd->nfsd callbacks */
+	retval = nfsd_export_wq_init();
+	if (retval)
+		goto out_free_lockd;
 	retval = register_pernet_subsys(&nfsd_net_ops);
 	if (retval < 0)
-		goto out_free_lockd;
+		goto out_free_export_wq;
 	retval = register_cld_notifier();
 	if (retval)
 		goto out_free_subsys;
@@ -2283,6 +2286,8 @@ out_free_cld:
 	unregister_cld_notifier();
 out_free_subsys:
 	unregister_pernet_subsys(&nfsd_net_ops);
+out_free_export_wq:
+	nfsd_export_wq_shutdown();
 out_free_lockd:
 	nfsd_lockd_shutdown();
 	nfsd_drc_slab_free();
@@ -2303,6 +2308,7 @@ static void __exit exit_nfsd(void)
 	nfsd4_destroy_laundry_wq();
 	unregister_cld_notifier();
 	unregister_pernet_subsys(&nfsd_net_ops);
+	nfsd_export_wq_shutdown();
 	nfsd_drc_slab_free();
 	nfsd_lockd_shutdown();
 	nfsd4_free_slabs();
author maintainer
#2 lore raw

PATCH 2/220 NFSD: Hold net reference for the lifetime of /proc/fs/nfs/exports fd

In reply to Greg Kroah-Hartman

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

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

From: Chuck Lever <[email protected]>

commit e7fcf179b82d3a3730fd8615da01b087cc654d0b upstream.

The /proc/fs/nfs/exports proc entry is created at module init and persists for the module's lifetime. exports_proc_open() captures the caller's current network namespace and stores its svc_export_cache in seq->private, but takes no reference on the namespace. If the namespace is subsequently torn down (e.g. container destruction after the opener does setns() to a different namespace), nfsd_net_exit() calls nfsd_export_shutdown() which frees the cache. Subsequent reads on the still-open fd dereference the freed cache_detail, walking a freed hash table.

Hold a reference on the struct net for the lifetime of the open file descriptor. This prevents nfsd_net_exit() from running -- and thus prevents nfsd_export_shutdown() from freeing the cache -- while any exports fd is open. cache_detail already stores its net pointer (cd->net, set by cache_create_net()), so exports_release() can retrieve it without additional per-file storage.

---
 fs/nfsd/nfsctl.c |   14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)
fs/nfsd/nfsctl.c +12 -2
@@ -149,9 +149,19 @@ static int exports_net_open(struct net *
 
 	seq = file->private_data;
 	seq->private = nn->svc_export_cache;
+	get_net(net);
 	return 0;
 }
 
+static int exports_release(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq = file->private_data;
+	struct cache_detail *cd = seq->private;
+
+	put_net(cd->net);
+	return seq_release(inode, file);
+}
+
 static int exports_nfsd_open(struct inode *inode, struct file *file)
 {
 	return exports_net_open(inode->i_sb->s_fs_info, file);
@@ -161,7 +171,7 @@ static const struct file_operations expo
 	.open		= exports_nfsd_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
-	.release	= seq_release,
+	.release	= exports_release,
 };
 
 static int export_features_show(struct seq_file *m, void *v)
@@ -1375,7 +1385,7 @@ static const struct proc_ops exports_pro
 	.proc_open	= exports_proc_open,
 	.proc_read	= seq_read,
 	.proc_lseek	= seq_lseek,
-	.proc_release	= seq_release,
+	.proc_release	= exports_release,
 };
 
 static int create_proc_exports_entry(void)
author maintainer
#3 lore raw

PATCH 3/220 nfsd: fix heap overflow in NFSv4.0 LOCK replay cache

In reply to Greg Kroah-Hartman

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

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

From: Jeff Layton <[email protected]>

commit 5133b61aaf437e5f25b1b396b14242a6bb0508e2 upstream.

The NFSv4.0 replay cache uses a fixed 112-byte inline buffer (rp_ibuf[NFSD4_REPLAY_ISIZE]) to store encoded operation responses. This size was calculated based on OPEN responses and does not account for LOCK denied responses, which include the conflicting lock owner as a variable-length field up to 1024 bytes (NFS4_OPAQUE_LIMIT).

When a LOCK operation is denied due to a conflict with an existing lock that has a large owner, nfsd4_encode_operation() copies the full encoded response into the undersized replay buffer via read_bytes_from_xdr_buf() with no bounds check. This results in a slab-out-of-bounds write of up to 944 bytes past the end of the buffer, corrupting adjacent heap memory.

This can be triggered remotely by an unauthenticated attacker with two cooperating NFSv4.0 clients: one sets a lock with a large owner string, then the other requests a conflicting lock to provoke the denial.

We could fix this by increasing NFSD4_REPLAY_ISIZE to allow for a full opaque, but that would increase the size of every stateowner, when most lockowners are not that large.

Instead, fix this by checking the encoded response length against NFSD4_REPLAY_ISIZE before copying into the replay buffer. If the response is too large, set rp_buflen to 0 to skip caching the replay payload. The status is still cached, and the client already received the correct response on the original request.

---
 fs/nfsd/nfs4xdr.c |    9 +++++++--
 fs/nfsd/state.h   |   17 ++++++++++++-----
 2 files changed, 19 insertions(+), 7 deletions(-)
fs/nfsd/nfs4xdr.c +7 -2
@@ -5946,9 +5946,14 @@ nfsd4_encode_operation(struct nfsd4_comp
 		int len = xdr->buf->len - (op_status_offset + XDR_UNIT);
 
 		so->so_replay.rp_status = op->status;
-		so->so_replay.rp_buflen = len;
-		read_bytes_from_xdr_buf(xdr->buf, op_status_offset + XDR_UNIT,
+		if (len <= NFSD4_REPLAY_ISIZE) {
+			so->so_replay.rp_buflen = len;
+			read_bytes_from_xdr_buf(xdr->buf,
+						op_status_offset + XDR_UNIT,
 						so->so_replay.rp_buf, len);
+		} else {
+			so->so_replay.rp_buflen = 0;
+		}
 	}
 status:
 	op->status = nfsd4_map_status(op->status,
fs/nfsd/state.h +12 -5
@@ -541,11 +541,18 @@ struct nfs4_client_reclaim {
 	struct xdr_netobj	cr_princhash;
 };
 
-/* A reasonable value for REPLAY_ISIZE was estimated as follows:  
- * The OPEN response, typically the largest, requires 
- *   4(status) + 8(stateid) + 20(changeinfo) + 4(rflags) +  8(verifier) + 
- *   4(deleg. type) + 8(deleg. stateid) + 4(deleg. recall flag) + 
- *   20(deleg. space limit) + ~32(deleg. ace) = 112 bytes 
+/*
+ * REPLAY_ISIZE is sized for an OPEN response with delegation:
+ *   4(status) + 8(stateid) + 20(changeinfo) + 4(rflags) +
+ *   8(verifier) + 4(deleg. type) + 8(deleg. stateid) +
+ *   4(deleg. recall flag) + 20(deleg. space limit) +
+ *   ~32(deleg. ace) = 112 bytes
+ *
+ * Some responses can exceed this. A LOCK denial includes the conflicting
+ * lock owner, which can be up to 1024 bytes (NFS4_OPAQUE_LIMIT). Responses
+ * larger than REPLAY_ISIZE are not cached in rp_ibuf; only rp_status is
+ * saved. Enlarging this constant increases the size of every
+ * nfs4_stateowner.
  */
 
 #define NFSD4_REPLAY_ISIZE       112 
author maintainer
#4 lore raw

PATCH 4/220 selftests/hid: fix compilation when bpf_wq and hid_device are not exported

In reply to Greg Kroah-Hartman

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

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

From: Benjamin Tissoires <[email protected]>

commit 5d4c6c132ea9a967d48890dd03e6a786c060e968 upstream.

This can happen in situations when CONFIG_HID_SUPPORT is set to no, or some complex situations where struct bpf_wq is not exported.

So do the usual dance of hiding them before including vmlinux.h, and then redefining them and make use of CO-RE to have the correct offsets.

---
 tools/testing/selftests/hid/progs/hid_bpf_helpers.h |   12 ++++++++++++
 1 file changed, 12 insertions(+)
tools/testing/selftests/hid/progs/hid_bpf_helpers.h +12 -0
@@ -6,8 +6,10 @@
 #define __HID_BPF_HELPERS_H
 
 /* "undefine" structs and enums in vmlinux.h, because we "override" them below */
+#define bpf_wq bpf_wq___not_used
 #define hid_bpf_ctx hid_bpf_ctx___not_used
 #define hid_bpf_ops hid_bpf_ops___not_used
+#define hid_device hid_device___not_used
 #define hid_report_type hid_report_type___not_used
 #define hid_class_request hid_class_request___not_used
 #define hid_bpf_attach_flags hid_bpf_attach_flags___not_used
@@ -27,8 +29,10 @@
 
 #include "vmlinux.h"
 
+#undef bpf_wq
 #undef hid_bpf_ctx
 #undef hid_bpf_ops
+#undef hid_device
 #undef hid_report_type
 #undef hid_class_request
 #undef hid_bpf_attach_flags
@@ -55,6 +59,14 @@ enum hid_report_type {
 	HID_REPORT_TYPES,
 };
 
+struct hid_device {
+	unsigned int id;
+} __attribute__((preserve_access_index));
+
+struct bpf_wq {
+	__u64 __opaque[2];
+};
+
 struct hid_bpf_ctx {
 	struct hid_device *hid;
 	__u32 allocated_size;
author maintainer
#5 lore raw

PATCH 5/220 HID: bpf: prevent buffer overflow in hid_hw_request

In reply to Greg Kroah-Hartman

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

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

From: Benjamin Tissoires <[email protected]>

commit 2b658c1c442ec1cd9eec5ead98d68662c40fe645 upstream.

right now the returned value is considered to be always valid. However, when playing with HID-BPF, the return value can be arbitrary big, because it's the return value of dispatch_hid_bpf_raw_requests(), which calls the struct_ops and we have no guarantees that the value makes sense.

Fixes 8bd0488b5ea5 ("HID: bpf: add HID-BPF hooks for hid_hw_raw_requests")
---
 drivers/hid/bpf/hid_bpf_dispatch.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/hid/bpf/hid_bpf_dispatch.c +2 -0
@@ -447,6 +447,8 @@ hid_bpf_hw_request(struct hid_bpf_ctx *c
 					      (u64)(long)ctx,
 					      true); /* prevent infinite recursions */
 
+	if (ret > size)
+		ret = size;
 	if (ret > 0)
 		memcpy(buf, dma_data, ret);
 
author maintainer
#6 lore raw

PATCH 6/220 sunrpc: fix cache_request leak in cache_release

In reply to Greg Kroah-Hartman

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

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

From: Jeff Layton <[email protected]>

commit 17ad31b3a43b72aec3a3d83605891e1397d0d065 upstream.

When a reader's file descriptor is closed while in the middle of reading a cache_request (rp->offset != 0), cache_release() decrements the request's readers count but never checks whether it should free the request.

In cache_read(), when readers drops to 0 and CACHE_PENDING is clear, the cache_request is removed from the queue and freed along with its buffer and cache_head reference. cache_release() lacks this cleanup.

The only other path that frees requests with readers == 0 is cache_dequeue(), but it runs only when CACHE_PENDING transitions from set to clear. If that transition already happened while readers was still non-zero, cache_dequeue() will have skipped the request, and no subsequent call will clean it up.

Add the same cleanup logic from cache_read() to cache_release(): after decrementing readers, check if it reached 0 with CACHE_PENDING clear, and if so, dequeue and free the cache_request.

---
 net/sunrpc/cache.c |   26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)
net/sunrpc/cache.c +21 -5
@@ -1061,14 +1061,25 @@ static int cache_release(struct inode *i
 	struct cache_reader *rp = filp->private_data;
 
 	if (rp) {
+		struct cache_request *rq = NULL;
+
 		spin_lock(&queue_lock);
 		if (rp->offset) {
 			struct cache_queue *cq;
-			for (cq= &rp->q; &cq->list != &cd->queue;
-			     cq = list_entry(cq->list.next, struct cache_queue, list))
+			for (cq = &rp->q; &cq->list != &cd->queue;
+			     cq = list_entry(cq->list.next,
+					     struct cache_queue, list))
 				if (!cq->reader) {
-					container_of(cq, struct cache_request, q)
-						->readers--;
+					struct cache_request *cr =
+						container_of(cq,
+						struct cache_request, q);
+					cr->readers--;
+					if (cr->readers == 0 &&
+					    !test_bit(CACHE_PENDING,
+						      &cr->item->flags)) {
+						list_del(&cr->q.list);
+						rq = cr;
+					}
 					break;
 				}
 			rp->offset = 0;
@@ -1076,9 +1087,14 @@ static int cache_release(struct inode *i
 		list_del(&rp->q.list);
 		spin_unlock(&queue_lock);
 
+		if (rq) {
+			cache_put(rq->item, cd);
+			kfree(rq->buf);
+			kfree(rq);
+		}
+
 		filp->private_data = NULL;
 		kfree(rp);
-
 	}
 	if (filp->f_mode & FMODE_WRITE) {
 		atomic_dec(&cd->writers);
author maintainer
#7 lore raw

PATCH 7/220 nvdimm/bus: Fix potential use after free in asynchronous initialization

In reply to Greg Kroah-Hartman

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

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

From: Ira Weiny <[email protected]>

commit a8aec14230322ed8f1e8042b6d656c1631d41163 upstream.

Dingisoul with KASAN reports a use after free if device_add() fails in nd_async_device_register().

Commit b6eae0f61db2 ("libnvdimm: Hold reference on parent while scheduling async init") correctly added a reference on the parent device to be held until asynchronous initialization was complete. However, if device_add() results in an allocation failure the ref count of the device drops to 0 prior to the parent pointer being accessed. Thus resulting in use after free.

The bug bot AI correctly identified the fix. Save a reference to the parent pointer to be used to drop the parent reference regardless of the outcome of device_add().

---
 drivers/nvdimm/bus.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/nvdimm/bus.c +3 -2
@@ -486,14 +486,15 @@ EXPORT_SYMBOL_GPL(nd_synchronize);
 static void nd_async_device_register(void *d, async_cookie_t cookie)
 {
 	struct device *dev = d;
+	struct device *parent = dev->parent;
 
 	if (device_add(dev) != 0) {
 		dev_err(dev, "%s: failed\n", __func__);
 		put_device(dev);
 	}
 	put_device(dev);
-	if (dev->parent)
-		put_device(dev->parent);
+	if (parent)
+		put_device(parent);
 }
 
 static void nd_async_device_unregister(void *d, async_cookie_t cookie)
author maintainer
#8 lore raw

PATCH 8/220 crash_dump: dont log dm-crypt key bytes in read_key_from_user_keying

In reply to Greg Kroah-Hartman

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

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

From: Thorsten Blum <[email protected]>

commit 36f46b0e36892eba08978eef7502ff3c94ddba77 upstream.

When debug logging is enabled, read_key_from_user_keying() logs the first 8 bytes of the key payload and partially exposes the dm-crypt key. Stop logging any key bytes.

Fixes 479e58549b0f ("crash_dump: store dm crypt keys in kdump reserved memory")
Cc Baoquan He <[email protected]>
Cc Coiby Xu <[email protected]>
Cc Dave Young <[email protected]>
Cc Vivek Goyal <[email protected]>
---
 kernel/crash_dump_dm_crypt.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/crash_dump_dm_crypt.c +2 -2
@@ -168,8 +168,8 @@ static int read_key_from_user_keying(str
 
 	memcpy(dm_key->data, ukp->data, ukp->datalen);
 	dm_key->key_size = ukp->datalen;
-	kexec_dprintk("Get dm crypt key (size=%u) %s: %8ph\n", dm_key->key_size,
-		      dm_key->key_desc, dm_key->data);
+	kexec_dprintk("Get dm crypt key (size=%u) %s\n", dm_key->key_size,
+		      dm_key->key_desc);
 
 out:
 	up_read(&key->sem);
author maintainer
#9 lore raw

PATCH 9/220 mm/rmap: fix incorrect pte restoration for lazyfree folios

In reply to Greg Kroah-Hartman

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

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

From: Dev Jain <[email protected]>

commit 29f40594a28114b9a9bc87f6cf7bbee9609628f2 upstream.

We batch unmap anonymous lazyfree folios by folio_unmap_pte_batch. If the batch has a mix of writable and non-writable bits, we may end up setting the entire batch writable. Fix this by respecting writable bit during batching.

Although on a successful unmap of a lazyfree folio, the soft-dirty bit is lost, preserve it on pte restoration by respecting the bit during batching, to make the fix consistent w.r.t both writable bit and soft-dirty bit.

I was able to write the below reproducer and crash the kernel. Explanation of reproducer (set 64K mTHP to always):

Fault in a 64K large folio. Split the VMA at mid-point with MADV_DONTFORK. fork() - parent points to the folio with 8 writable ptes and 8 non-writable ptes. Merge the VMAs with MADV_DOFORK so that folio_unmap_pte_batch() can determine all the 16 ptes as a batch. Do MADV_FREE on the range to mark the folio as lazyfree. Write to the memory to dirty the pte, eventually rmap will dirty the folio. Then trigger reclaim, we will hit the pte restoration path, and the kernel will crash with the trace given below.

The BUG happens at:

	BUG_ON(atomic_inc_return(&ptc->anon_map_count) > 1 && rw);

The code path is asking for anonymous page to be mapped writable into the pagetable. The BUG_ON() firing implies that such a writable page has been mapped into the pagetables of more than one process, which breaks anonymous memory/CoW semantics.

[   21.134473] kernel BUG at mm/page_table_check.c:118!
[   21.134497] Internal error: Oops - BUG: 00000000f2000800 [#1]  SMP
[   21.135917] Modules linked in:
[   21.136085] CPU: 1 UID: 0 PID: 1735 Comm: dup-lazyfree Not tainted 7.0.0-rc1-00116-g018018a17770 #1028 PREEMPT
[   21.136858] Hardware name: linux,dummy-virt (DT)
[   21.137019] pstate: 21400005 (nzCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
[   21.137308] pc : page_table_check_set+0x28c/0x2a8
[   21.137607] lr : page_table_check_set+0x134/0x2a8
[   21.137885] sp : ffff80008a3b3340
[   21.138124] x29: ffff80008a3b3340 x28: fffffdffc3d14400 x27: ffffd1a55e03d000
[   21.138623] x26: 0040000000000040 x25: ffffd1a55f7dd000 x24: 0000000000000001
[   21.139045] x23: 0000000000000001 x22: 0000000000000001 x21: ffffd1a55f217f30
[   21.139629] x20: 0000000000134521 x19: 0000000000134519 x18: 005c43e000040000
[   21.140027] x17: 0001400000000000 x16: 0001700000000000 x15: 000000000000ffff
[   21.140578] x14: 000000000000000c x13: 005c006000000000 x12: 0000000000000020
[   21.140828] x11: 0000000000000000 x10: 005c000000000000 x9 : ffffd1a55c079ee0
[   21.141077] x8 : 0000000000000001 x7 : 005c03e000040000 x6 : 000000004000ffff
[   21.141490] x5 : ffff00017fffce00 x4 : 0000000000000001 x3 : 0000000000000002
[   21.141741] x2 : 0000000000134510 x1 : 0000000000000000 x0 : ffff0000c08228c0
[   21.141991] Call trace:
[   21.142093]  page_table_check_set+0x28c/0x2a8 (P)
[   21.142265]  __page_table_check_ptes_set+0x144/0x1e8
[   21.142441]  __set_ptes_anysz.constprop.0+0x160/0x1a8
[   21.142766]  contpte_set_ptes+0xe8/0x140
[   21.142907]  try_to_unmap_one+0x10c4/0x10d0
[   21.143177]  rmap_walk_anon+0x100/0x250
[   21.143315]  try_to_unmap+0xa0/0xc8
[   21.143441]  shrink_folio_list+0x59c/0x18a8
[   21.143759]  shrink_lruvec+0x664/0xbf0
[   21.144043]  shrink_node+0x218/0x878
[   21.144285]  __node_reclaim.constprop.0+0x98/0x338
[   21.144763]  user_proactive_reclaim+0x2a4/0x340
[   21.145056]  reclaim_store+0x3c/0x60
[   21.145216]  dev_attr_store+0x20/0x40
[   21.145585]  sysfs_kf_write+0x84/0xa8
[   21.145835]  kernfs_fop_write_iter+0x130/0x1c8
[   21.145994]  vfs_write+0x2b8/0x368
[   21.146119]  ksys_write+0x70/0x110
[   21.146240]  __arm64_sys_write+0x24/0x38
[   21.146380]  invoke_syscall+0x50/0x120
[   21.146513]  el0_svc_common.constprop.0+0x48/0xf8
[   21.146679]  do_el0_svc+0x28/0x40
[   21.146798]  el0_svc+0x34/0x110
[   21.146926]  el0t_64_sync_handler+0xa0/0xe8
[   21.147074]  el0t_64_sync+0x198/0x1a0
[   21.147225] Code: f9400441 b4fff241 17ffff94 d4210000 (d4210000)
[   21.147440] ---[ end trace 0000000000000000 ]---

#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <string.h>
#include <sys/wait.h>
#include <sched.h>
#include <fcntl.h>

void write_to_reclaim() {
    const char *path = "/sys/devices/system/node/node0/reclaim";
    const char *value = "409600000000";
    int fd = open(path, O_WRONLY);
    if (fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    if (write(fd, value, sizeof("409600000000") - 1) == -1) {
        perror("write");
        close(fd);
        exit(EXIT_FAILURE);
    }

    printf("Successfully wrote %s to %s\n", value, path);
    close(fd);
}

int main()

{
	char *ptr = mmap((void *)(1UL << 30), 1UL << 16, PROT_READ | PROT_WRITE,
			 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
	if ((unsigned long)ptr != (1UL << 30)) {
		perror("mmap");
		return 1;
	}

	/* a 64K folio gets faulted in */
	memset(ptr, 0, 1UL << 16);

	/* 32K half will not be shared into child */
	if (madvise(ptr, 1UL << 15, MADV_DONTFORK)) {
		perror("madvise madv dontfork");
		return 1;
	}

	pid_t pid = fork();

	if (pid < 0) {
		perror("fork");
		return 1;
	} else if (pid == 0) {
		sleep(15);
	} else {
		/* merge VMAs. now first half of the 16 ptes are writable, the other half not. */
		if (madvise(ptr, 1UL << 15, MADV_DOFORK)) {
			perror("madvise madv fork");
			return 1;
		}
		if (madvise(ptr, (1UL << 16), MADV_FREE)) {
			perror("madvise madv free");
			return 1;
		}

		/* dirty the large folio */
		(*ptr) += 10;

		write_to_reclaim();
		// sleep(10);
		waitpid(pid, NULL, 0);

	}
}
Fixes 354dffd29575 ("mm: support batched unmap for lazyfree large folios during reclamation")
Cc Anshuman Khandual <[email protected]>
Cc Harry Yoo <[email protected]>
Cc Jann Horn <[email protected]>
Cc Liam Howlett <[email protected]>
Cc Rik van Riel <[email protected]>
Cc Ryan Roberts <[email protected]>
Cc Vlastimil Babka <[email protected]>
---
 mm/rmap.c |    9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
mm/rmap.c +8 -1
@@ -1843,7 +1843,14 @@ static inline unsigned int folio_unmap_p
 	if (pte_unused(pte))
 		return 1;
 
-	return folio_pte_batch(folio, pvmw->pte, pte, max_nr);
+	/*
+	 * If unmap fails, we need to restore the ptes. To avoid accidentally
+	 * upgrading write permissions for ptes that were not originally
+	 * writable, and to avoid losing the soft-dirty bit, use the
+	 * appropriate FPB flags.
+	 */
+	return folio_pte_batch_flags(folio, vma, pvmw->pte, &pte, max_nr,
+				     FPB_RESPECT_WRITE | FPB_RESPECT_SOFT_DIRTY);
 }
 
 /*
author maintainer
#10 lore raw

PATCH 10/220 mm/huge_memory: fix use of NULL folio in move_pages_huge_pmd()

In reply to Greg Kroah-Hartman

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

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

From: Chris Down <[email protected]>

commit fae654083bfa409bb2244f390232e2be47f05bfc upstream.

move_pages_huge_pmd() handles UFFDIO_MOVE for both normal THPs and huge zero pages. For the huge zero page path, src_folio is explicitly set to NULL, and is used as a sentinel to skip folio operations like lock and rmap.

In the huge zero page branch, src_folio is NULL, so folio_mk_pmd(NULL, pgprot) passes NULL through folio_pfn() and page_to_pfn(). With SPARSEMEM_VMEMMAP this silently produces a bogus PFN, installing a PMD pointing to non-existent physical memory. On other memory models it is a NULL dereference.

Use page_folio(src_page) to obtain the valid huge zero folio from the page, which was obtained from pmd_page() and remains valid throughout.

After commit d82d09e48219 ("mm/huge_memory: mark PMD mappings of the huge zero folio special"), moved huge zero PMDs must remain special so vm_normal_page_pmd() continues to treat them as special mappings.

move_pages_huge_pmd() currently reconstructs the destination PMD in the huge zero page branch, which drops PMD state such as pmd_special() on architectures with CONFIG_ARCH_HAS_PTE_SPECIAL. As a result, vm_normal_page_pmd() can treat the moved huge zero PMD as a normal page and corrupt its refcount.

Instead of reconstructing the PMD from the folio, derive the destination entry from src_pmdval after pmdp_huge_clear_flush(), then handle the PMD metadata the same way move_huge_pmd() does for moved entries by marking it soft-dirty and clearing uffd-wp.

---
 mm/huge_memory.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
mm/huge_memory.c +2 -1
@@ -2797,7 +2797,8 @@ int move_pages_huge_pmd(struct mm_struct
 		_dst_pmd = pmd_mkwrite(pmd_mkdirty(_dst_pmd), dst_vma);
 	} else {
 		src_pmdval = pmdp_huge_clear_flush(src_vma, src_addr, src_pmd);
-		_dst_pmd = folio_mk_pmd(src_folio, dst_vma->vm_page_prot);
+		_dst_pmd = move_soft_dirty_pmd(src_pmdval);
+		_dst_pmd = clear_uffd_wp_pmd(_dst_pmd);
 	}
 	set_pmd_at(mm, dst_addr, dst_pmd, _dst_pmd);
 
author maintainer
#11 lore raw

PATCH 11/220 mm/huge_memory: fix early failure try_to_migrate() when split huge pmd for shared THP

In reply to Greg Kroah-Hartman

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

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

From: Wei Yang <[email protected]>

commit 939080834fef3ce42fdbcfef33fd29c9ffe5bbed upstream.

Commit 60fbb14396d5 ("mm/huge_memory: adjust try_to_migrate_one() and split_huge_pmd_locked()") return false unconditionally after split_huge_pmd_locked(). This may fail try_to_migrate() early when TTU_SPLIT_HUGE_PMD is specified.

The reason is the above commit adjusted try_to_migrate_one() to, when a PMD-mapped THP entry is found, and TTU_SPLIT_HUGE_PMD is specified (for example, via unmap_folio()), return false unconditionally. This breaks the rmap walk and fail try_to_migrate() early, if this PMD-mapped THP is mapped in multiple processes.

The user sensible impact of this bug could be:

* On memory pressure, shrink_folio_list() may split partially mapped folio with split_folio_to_list(). Then free unmapped pages without IO. If failed, it may not be reclaimed.
* On memory failure, memory_failure() would call try_to_split_thp_page() to split folio contains the bad page. If succeed, the PG_has_hwpoisoned bit is only set in the after-split folio contains @split_at. By doing so, we limit bad memory. If failed to split, the whole folios is not usable.

One way to reproduce:

Create an anonymous THP range and fork 512 children, so we have a THP shared mapped in 513 processes. Then trigger folio split with /sys/kernel/debug/split_huge_pages debugfs to split the THP folio to order 0.

Without the above commit, we can successfully split to order 0. With the above commit, the folio is still a large folio.

And currently there are two core users of TTU_SPLIT_HUGE_PMD:

* try_to_unmap_one()
* try_to_migrate_one()

try_to_unmap_one() would restart the rmap walk, so only try_to_migrate_one() is affected.

We can't simply revert commit 60fbb14396d5 ("mm/huge_memory: adjust try_to_migrate_one() and split_huge_pmd_locked()"), since it removed some duplicated check covered by page_vma_mapped_walk().

This patch fixes this by restart page_vma_mapped_walk() after split_huge_pmd_locked(). Since we cannot simply return "true" to fix the problem, as that would affect another case:

When invoking folio_try_share_anon_rmap_pmd() from split_huge_pmd_locked(), the latter can fail and leave a large folio mapped through PTEs, in which case we ought to return true from try_to_migrate_one(). This might result in unnecessary walking of the rmap but is relatively harmless.

---
 mm/rmap.c |   12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)
mm/rmap.c +9 -3
@@ -2338,11 +2338,17 @@ static bool try_to_migrate_one(struct fo
 			__maybe_unused pmd_t pmdval;
 
 			if (flags & TTU_SPLIT_HUGE_PMD) {
+				/*
+				 * split_huge_pmd_locked() might leave the
+				 * folio mapped through PTEs. Retry the walk
+				 * so we can detect this scenario and properly
+				 * abort the walk.
+				 */
 				split_huge_pmd_locked(vma, pvmw.address,
 						      pvmw.pmd, true);
-				ret = false;
-				page_vma_mapped_walk_done(&pvmw);
-				break;
+				flags &= ~TTU_SPLIT_HUGE_PMD;
+				page_vma_mapped_walk_restart(&pvmw);
+				continue;
 			}
 #ifdef CONFIG_ARCH_ENABLE_THP_MIGRATION
 			pmdval = pmdp_get(pvmw.pmd);
author maintainer
#12 lore raw

PATCH 12/220 LoongArch: Give more information if kmem access failed

In reply to Greg Kroah-Hartman

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

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

From: Tiezhu Yang <[email protected]>

commit a47f0754bdd01f971c9715acdbdd3a07515c8f83 upstream.

If memory access such as copy_{from, to}_kernel_nofault() failed, its users do not know what happened, so it is very useful to print the exception code for such cases. Furthermore, it is better to print the caller function to know where is the entry.

Here are the low level call chains:

copy_from_kernel_nofault()

    copy_from_kernel_nofault_loop()
      __get_kernel_nofault()

copy_to_kernel_nofault()

    copy_to_kernel_nofault_loop()
      __put_kernel_nofault()
---
 arch/loongarch/include/asm/uaccess.h |   14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)
arch/loongarch/include/asm/uaccess.h +12 -2
@@ -253,8 +253,13 @@ do {									\
 									\
 	__get_kernel_common(*((type *)(dst)), sizeof(type),		\
 			    (__force type *)(src));			\
-	if (unlikely(__gu_err))						\
+	if (unlikely(__gu_err))	{					\
+		pr_info("%s: memory access failed, ecode 0x%x\n",	\
+			__func__, read_csr_excode());			\
+		pr_info("%s: the caller is %pS\n",			\
+			__func__, __builtin_return_address(0));		\
 		goto err_label;						\
+	}								\
 } while (0)
 
 #define __put_kernel_nofault(dst, src, type, err_label)			\
@@ -264,8 +269,13 @@ do {									\
 									\
 	__pu_val = *(__force type *)(src);				\
 	__put_kernel_common(((type *)(dst)), sizeof(type));		\
-	if (unlikely(__pu_err))						\
+	if (unlikely(__pu_err))	{					\
+		pr_info("%s: memory access failed, ecode 0x%x\n",	\
+			__func__, read_csr_excode());			\
+		pr_info("%s: the caller is %pS\n",			\
+			__func__, __builtin_return_address(0));		\
 		goto err_label;						\
+	}								\
 } while (0)
 
 extern unsigned long __copy_user(void *to, const void *from, __kernel_size_t n);
author maintainer
#13 lore raw

PATCH 13/220 LoongArch: No need to flush icache if text copy failed

In reply to Greg Kroah-Hartman

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

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

From: Tiezhu Yang <[email protected]>

commit d3b8491961207ac967795c34375890407fd51a45 upstream.

If copy_to_kernel_nofault() failed, no need to flush icache and just return immediately.

---
 arch/loongarch/kernel/inst.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
arch/loongarch/kernel/inst.c +4 -2
@@ -246,13 +246,15 @@ static int text_copy_cb(void *data)
 
 	if (smp_processor_id() == copy->cpu) {
 		ret = copy_to_kernel_nofault(copy->dst, copy->src, copy->len);
-		if (ret)
+		if (ret) {
 			pr_err("%s: operation failed\n", __func__);
+			return ret;
+		}
 	}
 
 	flush_icache_range((unsigned long)copy->dst, (unsigned long)copy->dst + copy->len);
 
-	return ret;
+	return 0;
 }
 
 int larch_insn_text_copy(void *dst, void *src, size_t len)
author maintainer
#14 lore raw

PATCH 14/220 NFC: nxp-nci: allow GPIOs to sleep

In reply to Greg Kroah-Hartman

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

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

From: Ian Ray <[email protected]>

commit 55dc632ab2ac2889b15995a9eef56c753d48ebc7 upstream.

Allow the firmware and enable GPIOs to sleep.

This fixes a `WARN_ON' and allows the driver to operate GPIOs which are connected to I2C GPIO expanders.

-- >8 --
kernel: WARNING: CPU: 3 PID: 2636 at drivers/gpio/gpiolib.c:3880 gpiod_set_value+0x88/0x98 -- >8 --

Fixes 43201767b44c ("NFC: nxp-nci: Convert to use GPIO descriptor")
---
 drivers/nfc/nxp-nci/i2c.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/nfc/nxp-nci/i2c.c +2 -2
@@ -47,8 +47,8 @@ static int nxp_nci_i2c_set_mode(void *ph
 {
 	struct nxp_nci_i2c_phy *phy = (struct nxp_nci_i2c_phy *) phy_id;
 
-	gpiod_set_value(phy->gpiod_fw, (mode == NXP_NCI_MODE_FW) ? 1 : 0);
-	gpiod_set_value(phy->gpiod_en, (mode != NXP_NCI_MODE_COLD) ? 1 : 0);
+	gpiod_set_value_cansleep(phy->gpiod_fw, (mode == NXP_NCI_MODE_FW) ? 1 : 0);
+	gpiod_set_value_cansleep(phy->gpiod_en, (mode != NXP_NCI_MODE_COLD) ? 1 : 0);
 	usleep_range(10000, 15000);
 
 	if (mode == NXP_NCI_MODE_COLD)
author maintainer
#15 lore raw

PATCH 15/220 net: macb: fix use-after-free access to PTP clock

In reply to Greg Kroah-Hartman

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

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

From: Fedor Pchelkin <[email protected]>

commit 8da13e6d63c1a97f7302d342c89c4a56a55c7015 upstream.

PTP clock is registered on every opening of the interface and destroyed on every closing. However it may be accessed via get_ts_info ethtool call which is possible while the interface is just present in the kernel.

BUG: KASAN: use-after-free in ptp_clock_index+0x47/0x50 drivers/ptp/ptp_clock.c:426
Read of size 4 at addr ffff8880194345cc by task syz.0.6/948

CPU: 1 PID: 948 Comm: syz.0.6 Not tainted 6.1.164+ #109
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.16.1-0-g3208b098f51a-prebuilt.qemu.org 04/01/2014
Call Trace:
 <TASK>
 __dump_stack lib/dump_stack.c:88 [inline]
 dump_stack_lvl+0x8d/0xba lib/dump_stack.c:106
 print_address_description mm/kasan/report.c:316 [inline]
 print_report+0x17f/0x496 mm/kasan/report.c:420
 kasan_report+0xd9/0x180 mm/kasan/report.c:524
 ptp_clock_index+0x47/0x50 drivers/ptp/ptp_clock.c:426
 gem_get_ts_info+0x138/0x1e0 drivers/net/ethernet/cadence/macb_main.c:3349
 macb_get_ts_info+0x68/0xb0 drivers/net/ethernet/cadence/macb_main.c:3371
 __ethtool_get_ts_info+0x17c/0x260 net/ethtool/common.c:558
 ethtool_get_ts_info net/ethtool/ioctl.c:2367 [inline]
 __dev_ethtool net/ethtool/ioctl.c:3017 [inline]
 dev_ethtool+0x2b05/0x6290 net/ethtool/ioctl.c:3095
 dev_ioctl+0x637/0x1070 net/core/dev_ioctl.c:510
 sock_do_ioctl+0x20d/0x2c0 net/socket.c:1215
 sock_ioctl+0x577/0x6d0 net/socket.c:1320
 vfs_ioctl fs/ioctl.c:51 [inline]
 __do_sys_ioctl fs/ioctl.c:870 [inline]
 __se_sys_ioctl fs/ioctl.c:856 [inline]
 __x64_sys_ioctl+0x18c/0x210 fs/ioctl.c:856
 do_syscall_x64 arch/x86/entry/common.c:46 [inline]
 do_syscall_64+0x35/0x80 arch/x86/entry/common.c:76
 entry_SYSCALL_64_after_hwframe+0x6e/0xd8
 </TASK>

Allocated by task 457:
 kmalloc include/linux/slab.h:563 [inline]
 kzalloc include/linux/slab.h:699 [inline]
 ptp_clock_register+0x144/0x10e0 drivers/ptp/ptp_clock.c:235
 gem_ptp_init+0x46f/0x930 drivers/net/ethernet/cadence/macb_ptp.c:375
 macb_open+0x901/0xd10 drivers/net/ethernet/cadence/macb_main.c:2920
 __dev_open+0x2ce/0x500 net/core/dev.c:1501
 __dev_change_flags+0x56a/0x740 net/core/dev.c:8651
 dev_change_flags+0x92/0x170 net/core/dev.c:8722
 do_setlink+0xaf8/0x3a80 net/core/rtnetlink.c:2833
 __rtnl_newlink+0xbf4/0x1940 net/core/rtnetlink.c:3608
 rtnl_newlink+0x63/0xa0 net/core/rtnetlink.c:3655
 rtnetlink_rcv_msg+0x3c6/0xed0 net/core/rtnetlink.c:6150
 netlink_rcv_skb+0x15d/0x430 net/netlink/af_netlink.c:2511
 netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline]
 netlink_unicast+0x6d7/0xa30 net/netlink/af_netlink.c:1344
 netlink_sendmsg+0x97e/0xeb0 net/netlink/af_netlink.c:1872
 sock_sendmsg_nosec net/socket.c:718 [inline]
 __sock_sendmsg+0x14b/0x180 net/socket.c:730
 __sys_sendto+0x320/0x3b0 net/socket.c:2152
 __do_sys_sendto net/socket.c:2164 [inline]
 __se_sys_sendto net/socket.c:2160 [inline]
 __x64_sys_sendto+0xdc/0x1b0 net/socket.c:2160
 do_syscall_x64 arch/x86/entry/common.c:46 [inline]
 do_syscall_64+0x35/0x80 arch/x86/entry/common.c:76
 entry_SYSCALL_64_after_hwframe+0x6e/0xd8

Freed by task 938:
 kasan_slab_free include/linux/kasan.h:177 [inline]
 slab_free_hook mm/slub.c:1729 [inline]
 slab_free_freelist_hook mm/slub.c:1755 [inline]
 slab_free mm/slub.c:3687 [inline]
 __kmem_cache_free+0xbc/0x320 mm/slub.c:3700
 device_release+0xa0/0x240 drivers/base/core.c:2507
 kobject_cleanup lib/kobject.c:681 [inline]
 kobject_release lib/kobject.c:712 [inline]
 kref_put include/linux/kref.h:65 [inline]
 kobject_put+0x1cd/0x350 lib/kobject.c:729
 put_device+0x1b/0x30 drivers/base/core.c:3805
 ptp_clock_unregister+0x171/0x270 drivers/ptp/ptp_clock.c:391
 gem_ptp_remove+0x4e/0x1f0 drivers/net/ethernet/cadence/macb_ptp.c:404
 macb_close+0x1c8/0x270 drivers/net/ethernet/cadence/macb_main.c:2966
 __dev_close_many+0x1b9/0x310 net/core/dev.c:1585
 __dev_close net/core/dev.c:1597 [inline]
 __dev_change_flags+0x2bb/0x740 net/core/dev.c:8649
 dev_change_flags+0x92/0x170 net/core/dev.c:8722
 dev_ifsioc+0x151/0xe00 net/core/dev_ioctl.c:326
 dev_ioctl+0x33e/0x1070 net/core/dev_ioctl.c:572
 sock_do_ioctl+0x20d/0x2c0 net/socket.c:1215
 sock_ioctl+0x577/0x6d0 net/socket.c:1320
 vfs_ioctl fs/ioctl.c:51 [inline]
 __do_sys_ioctl fs/ioctl.c:870 [inline]
 __se_sys_ioctl fs/ioctl.c:856 [inline]
 __x64_sys_ioctl+0x18c/0x210 fs/ioctl.c:856
 do_syscall_x64 arch/x86/entry/common.c:46 [inline]
 do_syscall_64+0x35/0x80 arch/x86/entry/common.c:76
 entry_SYSCALL_64_after_hwframe+0x6e/0xd8

Set the PTP clock pointer to NULL after unregistering.

Fixes c2594d804d5c ("macb: Common code to enable ptp support for MACB/GEM")
---
 drivers/net/ethernet/cadence/macb_ptp.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/net/ethernet/cadence/macb_ptp.c +3 -1
@@ -357,8 +357,10 @@ void gem_ptp_remove(struct net_device *n
 {
 	struct macb *bp = netdev_priv(ndev);
 
-	if (bp->ptp_clock)
+	if (bp->ptp_clock) {
 		ptp_clock_unregister(bp->ptp_clock);
+		bp->ptp_clock = NULL;
+	}
 
 	gem_ptp_clear_timer(bp);
 
author maintainer
#16 lore raw

PATCH 16/220 bnxt_en: fix OOB access in DBG_BUF_PRODUCER async event handler

In reply to Greg Kroah-Hartman

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

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

From: Junrui Luo <[email protected]>

commit 64dcbde7f8f870a4f2d9daf24ffb06f9748b5dd3 upstream.

The ASYNC_EVENT_CMPL_EVENT_ID_DBG_BUF_PRODUCER handler in bnxt_async_event_process() uses a firmware-supplied 'type' field directly as an index into bp->bs_trace[] without bounds validation.

The 'type' field is a 16-bit value extracted from DMA-mapped completion ring memory that the NIC writes directly to host RAM. A malicious or compromised NIC can supply any value from 0 to 65535, causing an out-of-bounds access into kernel heap memory.

The bnxt_bs_trace_check_wrap() call then dereferences bs_trace->magic_byte and writes to bs_trace->last_offset and bs_trace->wrapped, leading to kernel memory corruption or a crash.

Fix by adding a bounds check and defining BNXT_TRACE_MAX as DBG_LOG_BUFFER_FLUSH_REQ_TYPE_ERR_QPC_TRACE + 1 to cover all currently defined firmware trace types (0x0 through 0xc).

---
 drivers/net/ethernet/broadcom/bnxt/bnxt.c |    2 ++
 drivers/net/ethernet/broadcom/bnxt/bnxt.h |    2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)
drivers/net/ethernet/broadcom/bnxt/bnxt.c +2 -0
@@ -2927,6 +2927,8 @@ static int bnxt_async_event_process(stru
 		u16 type = (u16)BNXT_EVENT_BUF_PRODUCER_TYPE(data1);
 		u32 offset =  BNXT_EVENT_BUF_PRODUCER_OFFSET(data2);
 
+		if (type >= ARRAY_SIZE(bp->bs_trace))
+			goto async_event_process_exit;
 		bnxt_bs_trace_check_wrap(&bp->bs_trace[type], offset);
 		goto async_event_process_exit;
 	}
drivers/net/ethernet/broadcom/bnxt/bnxt.h +1 -1
@@ -2135,7 +2135,7 @@ enum board_idx {
 };
 
 #define BNXT_TRACE_BUF_MAGIC_BYTE ((u8)0xbc)
-#define BNXT_TRACE_MAX 11
+#define BNXT_TRACE_MAX (DBG_LOG_BUFFER_FLUSH_REQ_TYPE_ERR_QPC_TRACE + 1)
 
 struct bnxt_bs_trace_info {
 	u8 *magic_byte;
author maintainer
#17 lore raw

PATCH 17/220 parisc: Flush correct cache in cacheflush() syscall

In reply to Greg Kroah-Hartman

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

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

From: Helge Deller <[email protected]>

commit 2c98a8fbd6aa647414c6248dacf254ebe91c79ad upstream.

The assembly flush instructions were swapped for I- and D-cache flags:

SYSCALL_DEFINE3(cacheflush, ...)

{
	if (cache & DCACHE) {
			"fic ...\n"
	}
	if (cache & ICACHE && error == 0) {
			"fdc ...\n"
	}

Fix it by using fdc for DCACHE, and fic for ICACHE flushing.

Fixes c6d96328fecd ("parisc: Add cacheflush() syscall")
Cc <[email protected]> # v6.5+
---
 arch/parisc/kernel/cache.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/parisc/kernel/cache.c +2 -2
@@ -953,7 +953,7 @@ SYSCALL_DEFINE3(cacheflush, unsigned lon
 #else
 			"1: cmpb,<<,n	%0,%2,1b\n"
 #endif
-			"   fic,m	%3(%4,%0)\n"
+			"   fdc,m	%3(%4,%0)\n"
 			"2: sync\n"
 			ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 2b, "%1")
 			: "+r" (start), "+r" (error)
@@ -968,7 +968,7 @@ SYSCALL_DEFINE3(cacheflush, unsigned lon
 #else
 			"1: cmpb,<<,n	%0,%2,1b\n"
 #endif
-			"   fdc,m	%3(%4,%0)\n"
+			"   fic,m	%3(%4,%0)\n"
 			"2: sync\n"
 			ASM_EXCEPTIONTABLE_ENTRY_EFAULT(1b, 2b, "%1")
 			: "+r" (start), "+r" (error)
author maintainer
#18 lore raw

PATCH 18/220 batman-adv: avoid OGM aggregation when skb tailroom is insufficient

In reply to Greg Kroah-Hartman

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

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

From: Yang Yang <[email protected]>

commit 0d4aef630be9d5f9c1227d07669c26c4383b5ad0 upstream.

When OGM aggregation state is toggled at runtime, an existing forwarded packet may have been allocated with only packet_len bytes, while a later packet can still be selected for aggregation. Appending in this case can hit skb_put overflow conditions.

Reject aggregation when the target skb tailroom cannot accommodate the new packet. The caller then falls back to creating a new forward packet instead of appending.

---
 net/batman-adv/bat_iv_ogm.c |    3 +++
 1 file changed, 3 insertions(+)
net/batman-adv/bat_iv_ogm.c +3 -0
@@ -473,6 +473,9 @@ batadv_iv_ogm_can_aggregate(const struct
 	if (aggregated_bytes > max_bytes)
 		return false;
 
+	if (skb_tailroom(forw_packet->skb) < packet_len)
+		return false;
+
 	if (packet_num >= BATADV_MAX_AGGREGATION_PACKETS)
 		return false;
 
author maintainer
#19 lore raw

PATCH 19/220 mac80211: fix crash in ieee80211_chan_bw_change for AP_VLAN stations

In reply to Greg Kroah-Hartman

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

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

From: Felix Fietkau <[email protected]>

commit 672e5229e1ecfc2a3509b53adcb914d8b024a853 upstream.

ieee80211_chan_bw_change() iterates all stations and accesses link->reserved.oper via sta->sdata->link[link_id]. For stations on AP_VLAN interfaces (e.g. 4addr WDS clients), sta->sdata points to the VLAN sdata, whose link never participates in chanctx reservations. This leaves link->reserved.oper zero-initialized with chan == NULL, causing a NULL pointer dereference in __ieee80211_sta_cap_rx_bw() when accessing chandef->chan->band during CSA.

Resolve the VLAN sdata to its parent AP sdata using get_bss_sdata() before accessing link data.

---
 net/mac80211/chan.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
net/mac80211/chan.c +4 -2
@@ -561,14 +561,16 @@ static void ieee80211_chan_bw_change(str
 	rcu_read_lock();
 	list_for_each_entry_rcu(sta, &local->sta_list,
 				list) {
-		struct ieee80211_sub_if_data *sdata = sta->sdata;
+		struct ieee80211_sub_if_data *sdata;
 		enum ieee80211_sta_rx_bandwidth new_sta_bw;
 		unsigned int link_id;
 
 		if (!ieee80211_sdata_running(sta->sdata))
 			continue;
 
-		for (link_id = 0; link_id < ARRAY_SIZE(sta->sdata->link); link_id++) {
+		sdata = get_bss_sdata(sta->sdata);
+
+		for (link_id = 0; link_id < ARRAY_SIZE(sdata->link); link_id++) {
 			struct ieee80211_link_data *link =
 				rcu_dereference(sdata->link[link_id]);
 			struct ieee80211_bss_conf *link_conf;
author maintainer
#20 lore raw

PATCH 20/220 crypto: padlock-sha - Disable for Zhaoxin processor

In reply to Greg Kroah-Hartman

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

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

From: AlanSong-oc <[email protected]>

commit ebba09f198078b7a2565004104ef762d1148e7f0 upstream.

For Zhaoxin processors, the XSHA1 instruction requires the total memory allocated at %rdi register must be 32 bytes, while the XSHA1 and XSHA256 instruction doesn't perform any operation when %ecx is zero.

Due to these requirements, the current padlock-sha driver does not work correctly with Zhaoxin processors. It cannot pass the self-tests and therefore does not activate the driver on Zhaoxin processors. This issue has been reported in Debian [1]. The self-tests fail with the following messages [2]:

alg: shash: sha1-padlock-nano test failed (wrong result) on test vector 0, cfg="init+update+final aligned buffer"
alg: self-tests for sha1 using sha1-padlock-nano failed (rc=-22)

alg: shash: sha256-padlock-nano test failed (wrong result) on test vector 0, cfg="init+update+final aligned buffer"
alg: self-tests for sha256 using sha256-padlock-nano failed (rc=-22)

Disable the padlock-sha driver on Zhaoxin processors with the CPU family 0x07 and newer. Following the suggestion in [3], support for PHE will be added to lib/crypto/ instead.

[1] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1113996
[2] https://linux-hardware.org/?probe=271fabb7a4&log=dmesg
[3] https://lore.kernel.org/linux-crypto/[email protected]/

Fixes 63dc06cd12f9 ("crypto: padlock-sha - Use API partial block handling")
---
 drivers/crypto/padlock-sha.c |    7 +++++++
 1 file changed, 7 insertions(+)
drivers/crypto/padlock-sha.c +7 -0
@@ -332,6 +332,13 @@ static int __init padlock_init(void)
 	if (!x86_match_cpu(padlock_sha_ids) || !boot_cpu_has(X86_FEATURE_PHE_EN))
 		return -ENODEV;
 
+	/*
+	 * Skip family 0x07 and newer used by Zhaoxin processors,
+	 * as the driver's self-tests fail on these CPUs.
+	 */
+	if (c->x86 >= 0x07)
+		return -ENODEV;
+
 	/* Register the newly added algorithm module if on *
 	* VIA Nano processor, or else just do as before */
 	if (c->x86_model < 0x0f) {
author maintainer
#21 lore raw

PATCH 21/220 Bluetooth: L2CAP: Fix type confusion in l2cap_ecred_reconf_rsp()

In reply to Greg Kroah-Hartman

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

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

From: Lukas Johannes Möller <[email protected]>

commit 15145675690cab2de1056e7ed68e59cbd0452529 upstream.

l2cap_ecred_reconf_rsp() casts the incoming data to struct l2cap_ecred_conn_rsp (the ECRED *connection* response, 8 bytes with result at offset 6) instead of struct l2cap_ecred_reconf_rsp (2 bytes with result at offset 0).

This causes two problems:

- The sizeof(*rsp) length check requires 8 bytes instead of the correct 2, so valid L2CAP_ECRED_RECONF_RSP packets are rejected with -EPROTO.

- rsp->result reads from offset 6 instead of offset 0, returning wrong data when the packet is large enough to pass the check.

Fix by using the correct type. Also pass the already byte-swapped result variable to BT_DBG instead of the raw __le16 field.

Fixes 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
---
 net/bluetooth/l2cap_core.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
net/bluetooth/l2cap_core.c +2 -2
@@ -5408,7 +5408,7 @@ static inline int l2cap_ecred_reconf_rsp
 					 u8 *data)
 {
 	struct l2cap_chan *chan, *tmp;
-	struct l2cap_ecred_conn_rsp *rsp = (void *) data;
+	struct l2cap_ecred_reconf_rsp *rsp = (void *)data;
 	u16 result;
 
 	if (cmd_len < sizeof(*rsp))
@@ -5416,7 +5416,7 @@ static inline int l2cap_ecred_reconf_rsp
 
 	result = __le16_to_cpu(rsp->result);
 
-	BT_DBG("result 0x%4.4x", rsp->result);
+	BT_DBG("result 0x%4.4x", result);
 
 	if (!result)
 		return 0;
author maintainer
#22 lore raw

PATCH 22/220 Bluetooth: L2CAP: Validate L2CAP_INFO_RSP payload length before access

In reply to Greg Kroah-Hartman

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

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

From: Lukas Johannes Möller <[email protected]>

commit dd815e6e3918dc75a49aaabac36e4f024d675101 upstream.

l2cap_information_rsp() checks that cmd_len covers the fixed l2cap_info_rsp header (type + result, 4 bytes) but then reads rsp->data without verifying that the payload is present:

- L2CAP_IT_FEAT_MASK calls get_unaligned_le32(rsp->data), which reads 4 bytes past the header (needs cmd_len >= 8).

- L2CAP_IT_FIXED_CHAN reads rsp->data[0], 1 byte past the header (needs cmd_len >= 5).

A truncated L2CAP_INFO_RSP with result == L2CAP_IR_SUCCESS triggers an out-of-bounds read of adjacent skb data.

Guard each data access with the required payload length check. If the payload is too short, skip the read and let the state machine complete with safe defaults (feat_mask and remote_fixed_chan remain zero from kzalloc), so the info timer cleanup and l2cap_conn_start() still run and the connection is not stalled.

Fixes 4e8402a3f884 ("[Bluetooth] Retrieve L2CAP features mask on connection setup")
---
 net/bluetooth/l2cap_core.c |    6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
net/bluetooth/l2cap_core.c +4 -2
@@ -4622,7 +4622,8 @@ static inline int l2cap_information_rsp(
 
 	switch (type) {
 	case L2CAP_IT_FEAT_MASK:
-		conn->feat_mask = get_unaligned_le32(rsp->data);
+		if (cmd_len >= sizeof(*rsp) + sizeof(u32))
+			conn->feat_mask = get_unaligned_le32(rsp->data);
 
 		if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
 			struct l2cap_info_req req;
@@ -4641,7 +4642,8 @@ static inline int l2cap_information_rsp(
 		break;
 
 	case L2CAP_IT_FIXED_CHAN:
-		conn->remote_fixed_chan = rsp->data[0];
+		if (cmd_len >= sizeof(*rsp) + sizeof(rsp->data[0]))
+			conn->remote_fixed_chan = rsp->data[0];
 		conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
 		conn->info_ident = 0;
 
author maintainer
#23 lore raw

PATCH 23/220 drm/amd: Fix hang on amdgpu unload by using pci_dev_is_disconnected()

In reply to Greg Kroah-Hartman

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

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

From: Mario Limonciello <[email protected]>

commit f7afda7fcd169a9168695247d07ad94cf7b9798f upstream.

The commit 6a23e7b4332c ("drm/amd: Clean up kfd node on surprise disconnect") introduced early KFD cleanup when drm_dev_is_unplugged() returns true. However, this causes hangs during normal module unload (rmmod amdgpu).

The issue occurs because drm_dev_unplug() is called in amdgpu_pci_remove() for all removal scenarios, not just surprise disconnects. This was done intentionally in commit 39934d3ed572 ("Revert "drm/amdgpu: TA unload messages are not actually sent to psp when amdgpu is uninstalled"") to fix IGT PCI software unplug test failures. As a result, drm_dev_is_unplugged() returns true even during normal module unload, triggering the early KFD cleanup inappropriately.

The correct check should distinguish between:
- Actual surprise disconnect (eGPU unplugged): pci_dev_is_disconnected() returns true
- Normal module unload (rmmod): pci_dev_is_disconnected() returns false

Replace drm_dev_is_unplugged() with pci_dev_is_disconnected() to ensure the early cleanup only happens during true hardware disconnect events.

---
 drivers/gpu/drm/amd/amdgpu/amdgpu_device.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +2 -2
@@ -5081,7 +5081,7 @@ void amdgpu_device_fini_hw(struct amdgpu
 	 * before ip_fini_early to prevent kfd locking refcount issues by calling
 	 * amdgpu_amdkfd_suspend()
 	 */
-	if (drm_dev_is_unplugged(adev_to_drm(adev)))
+	if (pci_dev_is_disconnected(adev->pdev))
 		amdgpu_amdkfd_device_fini_sw(adev);
 
 	amdgpu_device_ip_fini_early(adev);
@@ -5093,7 +5093,7 @@ void amdgpu_device_fini_hw(struct amdgpu
 
 	amdgpu_gart_dummy_page_fini(adev);
 
-	if (drm_dev_is_unplugged(adev_to_drm(adev)))
+	if (pci_dev_is_disconnected(adev->pdev))
 		amdgpu_device_unmap_mmio(adev);
 
 }
author maintainer
#24 lore raw

PATCH 24/220 smb: client: fix krb5 mount with username option

In reply to Greg Kroah-Hartman

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

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

From: Paulo Alcantara <[email protected]>

commit 12b4c5d98cd7ca46d5035a57bcd995df614c14e1 upstream.

Customer reported that some of their krb5 mounts were failing against a single server as the client was trying to mount the shares with wrong credentials. It turned out the client was reusing SMB session from first mount to try mounting the other shares, even though a different username= option had been specified to the other mounts.

By using username mount option along with sec=krb5 to search for principals from keytab is supported by cifs.upcall(8) since cifs-utils-4.8. So fix this by matching username mount option in match_session() even with Kerberos.

For example, the second mount below should fail with -ENOKEY as there is no 'foobar' principal in keytab (/etc/krb5.keytab). The client ends up reusing SMB session from first mount to perform the second one, which is wrong.

```
$ ktutil
ktutil:  add_entry -password -p testuser -k 1 -e aes256-cts
Password for [email protected]:
ktutil:  write_kt /etc/krb5.keytab
ktutil:  quit
$ klist -ke
Keytab name: FILE:/etc/krb5.keytab
KVNO Principal
 ---- ----------------------------------------------------------------
   1 [email protected] (aes256-cts-hmac-sha1-96)
$ mount.cifs //w22-root2/scratch /mnt/1 -o sec=krb5,username=testuser
$ mount.cifs //w22-root2/scratch /mnt/2 -o sec=krb5,username=foobar
$ mount -t cifs | grep -Po 'username=\K\w+'
testuser
testuser
```
---
 fs/smb/client/connect.c |    4 ++++
 1 file changed, 4 insertions(+)
fs/smb/client/connect.c +4 -0
@@ -1952,6 +1952,10 @@ static int match_session(struct cifs_ses
 	case Kerberos:
 		if (!uid_eq(ctx->cred_uid, ses->cred_uid))
 			return 0;
+		if (strncmp(ses->user_name ?: "",
+			    ctx->username ?: "",
+			    CIFS_MAX_USERNAME_LEN))
+			return 0;
 		break;
 	case NTLMv2:
 	case RawNTLMSSP:
author maintainer
#25 lore raw

PATCH 25/220 ksmbd: unset conn->binding on failed binding request

In reply to Greg Kroah-Hartman

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

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

From: Namjae Jeon <[email protected]>

commit 282343cf8a4a5a3603b1cb0e17a7083e4a593b03 upstream.

When a multichannel SMB2_SESSION_SETUP request with SMB2_SESSION_REQ_FLAG_BINDING fails ksmbd sets conn->binding = true but never clears it on the error path. This leaves the connection in a binding state where all subsequent ksmbd_session_lookup_all() calls fall back to the global sessions table. This fix it by clearing conn->binding = false in the error path.

---
 fs/smb/server/smb2pdu.c |    1 +
 1 file changed, 1 insertion(+)
fs/smb/server/smb2pdu.c +1 -0
@@ -1947,6 +1947,7 @@ out_err:
 			}
 		}
 		smb2_set_err_rsp(work);
+		conn->binding = false;
 	} else {
 		unsigned int iov_len;
 
author maintainer
#26 lore raw

PATCH 26/220 ksmbd: use volume UUID in FS_OBJECT_ID_INFORMATION

In reply to Greg Kroah-Hartman

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

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

From: Namjae Jeon <[email protected]>

commit 3a64125730cabc34fccfbc230c2667c2e14f7308 upstream.

Use sb->s_uuid for a proper volume identifier as the primary choice. For filesystems that do not provide a UUID, fall back to stfs.f_fsid obtained from vfs_statfs().

---
 fs/smb/server/smb2pdu.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
fs/smb/server/smb2pdu.c +4 -4
@@ -5452,7 +5452,6 @@ static int smb2_get_info_filesystem(stru
 				    struct smb2_query_info_req *req,
 				    struct smb2_query_info_rsp *rsp)
 {
-	struct ksmbd_session *sess = work->sess;
 	struct ksmbd_conn *conn = work->conn;
 	struct ksmbd_share_config *share = work->tcon->share_conf;
 	int fsinfoclass = 0;
@@ -5589,10 +5588,11 @@ static int smb2_get_info_filesystem(stru
 
 		info = (struct object_id_info *)(rsp->Buffer);
 
-		if (!user_guest(sess->user))
-			memcpy(info->objid, user_passkey(sess->user), 16);
+		if (path.mnt->mnt_sb->s_uuid_len == 16)
+			memcpy(info->objid, path.mnt->mnt_sb->s_uuid.b,
+					path.mnt->mnt_sb->s_uuid_len);
 		else
-			memset(info->objid, 0, 16);
+			memcpy(info->objid, &stfs.f_fsid, sizeof(stfs.f_fsid));
 
 		info->extended_info.magic = cpu_to_le32(EXTENDED_INFO_MAGIC);
 		info->extended_info.version = cpu_to_le32(1);
author maintainer
#27 lore raw

PATCH 27/220 drm/i915/dsc: Add Selective Update register definitions

In reply to Greg Kroah-Hartman

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

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

From: Jouni Högander <[email protected]>

commit c2c79c6d5b939ae8a42ddb884f576bddae685672 upstream.

Add definitions for DSC_SU_PARAMETER_SET_0_DSC0 and DSC_SU_PARAMETER_SET_0_DSC1 registers. These are for Selective Update Early Transport configuration.

Bspec: 71709

---
 drivers/gpu/drm/i915/display/intel_vdsc_regs.h |   12 ++++++++++++
 1 file changed, 12 insertions(+)
drivers/gpu/drm/i915/display/intel_vdsc_regs.h +12 -0
@@ -196,6 +196,18 @@
 #define   DSC_PPS18_NSL_BPG_OFFSET(offset)	REG_FIELD_PREP(DSC_PPS18_NSL_BPG_OFFSET_MASK, offset)
 #define   DSC_PPS18_SL_OFFSET_ADJ(offset)	REG_FIELD_PREP(DSC_PPS18_SL_OFFSET_ADJ_MASK, offset)
 
+#define _LNL_DSC0_SU_PARAMETER_SET_0_PA		0x78064
+#define _LNL_DSC1_SU_PARAMETER_SET_0_PA		0x78164
+#define _LNL_DSC0_SU_PARAMETER_SET_0_PB		0x78264
+#define _LNL_DSC1_SU_PARAMETER_SET_0_PB		0x78364
+#define LNL_DSC0_SU_PARAMETER_SET_0(pipe)	_MMIO_PIPE((pipe), _LNL_DSC0_SU_PARAMETER_SET_0_PA, _LNL_DSC0_SU_PARAMETER_SET_0_PB)
+#define LNL_DSC1_SU_PARAMETER_SET_0(pipe)	_MMIO_PIPE((pipe), _LNL_DSC1_SU_PARAMETER_SET_0_PA, _LNL_DSC1_SU_PARAMETER_SET_0_PB)
+
+#define   DSC_SUPS0_SU_SLICE_ROW_PER_FRAME_MASK		REG_GENMASK(31, 20)
+#define   DSC_SUPS0_SU_SLICE_ROW_PER_FRAME(rows)	REG_FIELD_PREP(DSC_SUPS0_SU_SLICE_ROW_PER_FRAME_MASK, (rows))
+#define   DSC_SUPS0_SU_PIC_HEIGHT_MASK			REG_GENMASK(15, 0)
+#define   DSC_SUPS0_SU_PIC_HEIGHT(h)			REG_FIELD_PREP(DSC_SUPS0_SU_PIC_HEIGHT_MASK, (h))
+
 /* Icelake Rate Control Buffer Threshold Registers */
 #define DSCA_RC_BUF_THRESH_0			_MMIO(0x6B230)
 #define DSCA_RC_BUF_THRESH_0_UDW		_MMIO(0x6B230 + 4)
author maintainer
#28 lore raw

PATCH 28/220 drm/i915/dsc: Add helper for writing DSC Selective Update ET parameters

In reply to Greg Kroah-Hartman

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

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

From: Jouni Högander <[email protected]>

commit bb5f1cd10101c2567bff4d0e760b74aee7c42f44 upstream.

There are slice row per frame and pic height configuration in DSC Selective Update Parameter Set 1 register. Add helper for configuring these.

v2:
- Add WARN_ON_ONCE if vdsc instances per pipe > 2
- instead of checking vdsc instances per pipe being > 1 check == 2

Bspec: 71709

(cherry picked from commit c8698d61aeb3f70fe33761ee9d3d0e131b5bc2eb)
[tursulin: fixup forward declaration conflict]
---
 drivers/gpu/drm/i915/display/intel_vdsc.c |   23 +++++++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_vdsc.h |    3 +++
 2 files changed, 26 insertions(+)
drivers/gpu/drm/i915/display/intel_vdsc.c +23 -0
@@ -767,6 +767,29 @@ void intel_dsc_dp_pps_write(struct intel
 				  sizeof(dp_dsc_pps_sdp));
 }
 
+void intel_dsc_su_et_parameters_configure(struct intel_dsb *dsb, struct intel_encoder *encoder,
+					  const struct intel_crtc_state *crtc_state, int su_lines)
+{
+	struct intel_display *display = to_intel_display(crtc_state);
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+	const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config;
+	enum pipe pipe = crtc->pipe;
+	int vdsc_instances_per_pipe = intel_dsc_get_vdsc_per_pipe(crtc_state);
+	int slice_row_per_frame = su_lines / vdsc_cfg->slice_height;
+	u32 val;
+
+	drm_WARN_ON_ONCE(display->drm, su_lines % vdsc_cfg->slice_height);
+	drm_WARN_ON_ONCE(display->drm, vdsc_instances_per_pipe > 2);
+
+	val = DSC_SUPS0_SU_SLICE_ROW_PER_FRAME(slice_row_per_frame);
+	val |= DSC_SUPS0_SU_PIC_HEIGHT(su_lines);
+
+	intel_de_write_dsb(display, dsb, LNL_DSC0_SU_PARAMETER_SET_0(pipe), val);
+
+	if (vdsc_instances_per_pipe == 2)
+		intel_de_write_dsb(display, dsb, LNL_DSC1_SU_PARAMETER_SET_0(pipe), val);
+}
+
 static i915_reg_t dss_ctl1_reg(struct intel_crtc *crtc, enum transcoder cpu_transcoder)
 {
 	return is_pipe_dsc(crtc, cpu_transcoder) ?
drivers/gpu/drm/i915/display/intel_vdsc.h +3 -0
@@ -13,6 +13,7 @@ struct drm_printer;
 enum transcoder;
 struct intel_crtc;
 struct intel_crtc_state;
+struct intel_dsb;
 struct intel_encoder;
 
 bool intel_dsc_source_support(const struct intel_crtc_state *crtc_state);
@@ -31,6 +32,8 @@ void intel_dsc_dsi_pps_write(struct inte
 			     const struct intel_crtc_state *crtc_state);
 void intel_dsc_dp_pps_write(struct intel_encoder *encoder,
 			    const struct intel_crtc_state *crtc_state);
+void intel_dsc_su_et_parameters_configure(struct intel_dsb *dsb, struct intel_encoder *encoder,
+					  const struct intel_crtc_state *crtc_state, int su_lines);
 void intel_vdsc_state_dump(struct drm_printer *p, int indent,
 			   const struct intel_crtc_state *crtc_state);
 int intel_vdsc_min_cdclk(const struct intel_crtc_state *crtc_state);
author maintainer
#29 lore raw

PATCH 29/220 drm/i915/psr: Write DSC parameters on Selective Update in ET mode

In reply to Greg Kroah-Hartman

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

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

From: Jouni Högander <[email protected]>

commit 5923a6e0459fdd3edac4ad5abccb24d777d8f1b6 upstream.

There are slice row per frame and pic height parameters in DSC that needs to be configured on every Selective Update in Early Transport mode. Use helper provided by DSC code to configure these on Selective Update when in Early Transport mode. Also fill crtc_state->psr2_su_area with full frame area on full frame update for DSC calculation.

v2: move psr2_su_area under skip_sel_fetch_set_loop label

Bspec: 68927, 71709

Fixes 467e4e061c44 ("drm/i915/psr: Enable psr2 early transport as possible")
Cc <[email protected]> # v6.9+
(cherry picked from commit 3140af2fab505a4cd47d516284529bf1585628be)
---
 drivers/gpu/drm/i915/display/intel_psr.c |   10 ++++++++++
 1 file changed, 10 insertions(+)
drivers/gpu/drm/i915/display/intel_psr.c +10 -0
@@ -2597,6 +2597,12 @@ void intel_psr2_program_trans_man_trk_ct
 
 	intel_de_write_dsb(display, dsb, PIPE_SRCSZ_ERLY_TPT(crtc->pipe),
 			   crtc_state->pipe_srcsz_early_tpt);
+
+	if (!crtc_state->dsc.compression_enable)
+		return;
+
+	intel_dsc_su_et_parameters_configure(dsb, encoder, crtc_state,
+					     drm_rect_height(&crtc_state->psr2_su_area));
 }
 
 static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state,
@@ -3017,6 +3023,10 @@ int intel_psr2_sel_fetch_update(struct i
 	}
 
 skip_sel_fetch_set_loop:
+	if (full_update)
+		clip_area_update(&crtc_state->psr2_su_area, &crtc_state->pipe_src,
+				 &crtc_state->pipe_src);
+
 	psr2_man_trk_ctl_calc(crtc_state, full_update);
 	crtc_state->pipe_srcsz_early_tpt =
 		psr2_pipe_srcsz_early_tpt_calc(crtc_state, full_update);
author maintainer
#30 lore raw

PATCH 30/220 LoongArch: Check return values for set_memory_{rw,rox}

In reply to Greg Kroah-Hartman

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

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

From: Tiezhu Yang <[email protected]>

[ Upstream commit 431ce839dad66d0d56fb604785452c6a57409f35 ]

set_memory_rw() and set_memory_rox() may fail, so we should check the return values and return immediately in larch_insn_text_copy().

[ kept `stop_machine()` instead of `stop_machine_cpuslocked()` ]
---
 arch/loongarch/kernel/inst.c |   15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)
arch/loongarch/kernel/inst.c +13 -2
@@ -260,6 +260,7 @@ static int text_copy_cb(void *data)
 int larch_insn_text_copy(void *dst, void *src, size_t len)
 {
 	int ret = 0;
+	int err = 0;
 	size_t start, end;
 	struct insn_copy copy = {
 		.dst = dst,
@@ -271,9 +272,19 @@ int larch_insn_text_copy(void *dst, void
 	start = round_down((size_t)dst, PAGE_SIZE);
 	end   = round_up((size_t)dst + len, PAGE_SIZE);
 
-	set_memory_rw(start, (end - start) / PAGE_SIZE);
+	err = set_memory_rw(start, (end - start) / PAGE_SIZE);
+	if (err) {
+		pr_info("%s: set_memory_rw() failed\n", __func__);
+		return err;
+	}
+
 	ret = stop_machine(text_copy_cb, &copy, cpu_online_mask);
-	set_memory_rox(start, (end - start) / PAGE_SIZE);
+
+	err = set_memory_rox(start, (end - start) / PAGE_SIZE);
+	if (err) {
+		pr_info("%s: set_memory_rox() failed\n", __func__);
+		return err;
+	}
 
 	return ret;
 }
author maintainer
#31 lore raw

PATCH 31/220 net: macb: Introduce gem_init_rx_ring()

In reply to Greg Kroah-Hartman

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

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

From: Kevin Hao <[email protected]>

[ Upstream commit 1a7124ecd655bcaf1845197fe416aa25cff4c3ea ]

Extract the initialization code for the GEM RX ring into a new function. This change will be utilized in a subsequent patch. No functional changes are introduced.

Stable-dep-of: 718d0766ce4c ("net: macb: Reinitialize tx/rx queue pointer registers and rx ring during resume")

---
 drivers/net/ethernet/cadence/macb_main.c |   13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)
drivers/net/ethernet/cadence/macb_main.c +9 -4
@@ -2669,6 +2669,14 @@ static void macb_init_tieoff(struct macb
 	desc->ctrl = 0;
 }
 
+static void gem_init_rx_ring(struct macb_queue *queue)
+{
+	queue->rx_tail = 0;
+	queue->rx_prepared_head = 0;
+
+	gem_rx_refill(queue);
+}
+
 static void gem_init_rings(struct macb *bp)
 {
 	struct macb_queue *queue;
@@ -2686,10 +2694,7 @@ static void gem_init_rings(struct macb *
 		queue->tx_head = 0;
 		queue->tx_tail = 0;
 
-		queue->rx_tail = 0;
-		queue->rx_prepared_head = 0;
-
-		gem_rx_refill(queue);
+		gem_init_rx_ring(queue);
 	}
 
 	macb_init_tieoff(bp);
author maintainer
#32 lore raw

PATCH 32/220 net: macb: Reinitialize tx/rx queue pointer registers and rx ring during resume

In reply to Greg Kroah-Hartman

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

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

From: Kevin Hao <[email protected]>

[ Upstream commit 718d0766ce4c7634ce62fa78b526ea7263487edd ]

On certain platforms, such as AMD Versal boards, the tx/rx queue pointer registers are cleared after suspend, and the rx queue pointer register is also disabled during suspend if WOL is enabled. Previously, we assumed that these registers would be restored by macb_mac_link_up(). However, in commit bf9cf80cab81, macb_init_buffers() was moved from macb_mac_link_up() to macb_open(). Therefore, we should call macb_init_buffers() to reinitialize the tx/rx queue pointer registers during resume.

Due to the reset of these two registers, we also need to adjust the tx/rx rings accordingly. The tx ring will be handled by gem_shuffle_tx_rings() in macb_mac_link_up(), so we only need to initialize the rx ring here.

---
 drivers/net/ethernet/cadence/macb_main.c |   10 ++++++++++
 1 file changed, 10 insertions(+)
drivers/net/ethernet/cadence/macb_main.c +10 -0
@@ -5949,8 +5949,18 @@ static int __maybe_unused macb_resume(st
 		rtnl_unlock();
 	}
 
+	if (!(bp->caps & MACB_CAPS_MACB_IS_EMAC))
+		macb_init_buffers(bp);
+
 	for (q = 0, queue = bp->queues; q < bp->num_queues;
 	     ++q, ++queue) {
+		if (!(bp->caps & MACB_CAPS_MACB_IS_EMAC)) {
+			if (macb_is_gem(bp))
+				gem_init_rx_ring(queue);
+			else
+				macb_init_rx_ring(queue);
+		}
+
 		napi_enable(&queue->napi_rx);
 		napi_enable(&queue->napi_tx);
 	}
author maintainer
#33 lore raw

PATCH 33/220 firmware: stratix10-svc: Delete some stray tabs

In reply to Greg Kroah-Hartman

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

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

From: Dan Carpenter <[email protected]>

[ Upstream commit 9e51d1da5b245c9bf97fc49b06cca7e901c0fe94 ]

These lines are indented one tab too far. Delete the extra tabs for readability.

Stable-dep-of: 22fd7f7fed2a ("firmware: stratix10-svc: Add Multi SVC clients support")

---
 drivers/firmware/stratix10-svc.c |   14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/firmware/stratix10-svc.c +7 -7
@@ -1317,7 +1317,7 @@ int stratix10_svc_async_send(struct stra
 		dev_dbg(ctrl->dev,
 			"Async message sent with transaction_id 0x%02x\n",
 			handle->transaction_id);
-			*handler = handle;
+		*handler = handle;
 		return 0;
 	case INTEL_SIP_SMC_STATUS_BUSY:
 		dev_warn(ctrl->dev, "Mailbox is busy, try after some time\n");
@@ -1702,12 +1702,12 @@ int stratix10_svc_send(struct stratix10_
 			kthread_run_on_cpu(svc_normal_to_secure_thread,
 					   (void *)chan->ctrl,
 					   cpu, "svc_smc_hvc_thread");
-			if (IS_ERR(chan->ctrl->task)) {
-				dev_err(chan->ctrl->dev,
-					"failed to create svc_smc_hvc_thread\n");
-				kfree(p_data);
-				return -EINVAL;
-			}
+		if (IS_ERR(chan->ctrl->task)) {
+			dev_err(chan->ctrl->dev,
+				"failed to create svc_smc_hvc_thread\n");
+			kfree(p_data);
+			return -EINVAL;
+		}
 	}
 
 	pr_debug("%s: sent P-va=%p, P-com=%x, P-size=%u\n", __func__,
author maintainer
#34 lore raw

PATCH 34/220 firmware: stratix10-svc: Add Multi SVC clients support

In reply to Greg Kroah-Hartman

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

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

From: Muhammad Amirul Asyraf Mohamad Jamian <[email protected]>

[ Upstream commit 22fd7f7fed2ae3702f90d1985c326354e86b9c75 ]

In the current implementation, SVC client drivers such as socfpga-hwmon, intel_fcs, stratix10-soc, stratix10-rsu each send an SMC command that triggers a single thread in the stratix10-svc driver. Upon receiving a callback, the initiating client driver sends a stratix10-svc-done signal, terminating the thread without waiting for other pending SMC commands to complete. This leads to a timeout issue in the firmware SVC mailbox service when multiple client drivers send SMC commands concurrently.

To resolve this issue, a dedicated thread is now created per channel. The stratix10-svc driver will support up to the number of channels defined by SVC_NUM_CHANNEL. Thread synchronization is handled using a mutex to prevent simultaneous issuance of SMC commands by multiple threads.

SVC_NUM_DATA_IN_FIFO is reduced from 32 to 8, since each channel now has its own dedicated FIFO and the SDM processes commands one at a time. 8 entries per channel is sufficient while keeping the total aggregate capacity the same (4 channels x 8 = 32 entries).

Additionally, a thread task is now validated before invoking kthread_stop when the user aborts, ensuring safe termination.

Timeout values have also been adjusted to accommodate the increased load from concurrent client driver activity.

---
 drivers/firmware/stratix10-svc.c                    |  228 +++++++++++---------
 include/linux/firmware/intel/stratix10-svc-client.h |    8 
 2 files changed, 130 insertions(+), 106 deletions(-)
drivers/firmware/stratix10-svc.c +126 -102
@@ -37,15 +37,14 @@
  * service layer will return error to FPGA manager when timeout occurs,
  * timeout is set to 30 seconds (30 * 1000) at Intel Stratix10 SoC.
  */
-#define SVC_NUM_DATA_IN_FIFO			32
+#define SVC_NUM_DATA_IN_FIFO			8
 #define SVC_NUM_CHANNEL				4
-#define FPGA_CONFIG_DATA_CLAIM_TIMEOUT_MS	200
+#define FPGA_CONFIG_DATA_CLAIM_TIMEOUT_MS	2000
 #define FPGA_CONFIG_STATUS_TIMEOUT_SEC		30
 #define BYTE_TO_WORD_SIZE              4
 
 /* stratix10 service layer clients */
 #define STRATIX10_RSU				"stratix10-rsu"
-#define INTEL_FCS				"intel-fcs"
 
 /* Maximum number of SDM client IDs. */
 #define MAX_SDM_CLIENT_IDS			16
@@ -105,11 +104,9 @@ struct stratix10_svc_chan;
 /**
  * struct stratix10_svc - svc private data
  * @stratix10_svc_rsu: pointer to stratix10 RSU device
- * @intel_svc_fcs: pointer to the FCS device
  */
 struct stratix10_svc {
 	struct platform_device *stratix10_svc_rsu;
-	struct platform_device *intel_svc_fcs;
 };
 
 /**
@@ -251,12 +248,10 @@ struct stratix10_async_ctrl {
  * @num_active_client: number of active service client
  * @node: list management
  * @genpool: memory pool pointing to the memory region
- * @task: pointer to the thread task which handles SMC or HVC call
- * @svc_fifo: a queue for storing service message data
  * @complete_status: state for completion
- * @svc_fifo_lock: protect access to service message data queue
  * @invoke_fn: function to issue secure monitor call or hypervisor call
  * @svc: manages the list of client svc drivers
+ * @sdm_lock: only allows a single command single response to SDM
  * @actrl: async control structure
  *
  * This struct is used to create communication channels for service clients, to
@@ -269,12 +264,10 @@ struct stratix10_svc_controller {
 	int num_active_client;
 	struct list_head node;
 	struct gen_pool *genpool;
-	struct task_struct *task;
-	struct kfifo svc_fifo;
 	struct completion complete_status;
-	spinlock_t svc_fifo_lock;
 	svc_invoke_fn *invoke_fn;
 	struct stratix10_svc *svc;
+	struct mutex sdm_lock;
 	struct stratix10_async_ctrl actrl;
 };
 
@@ -283,6 +276,9 @@ struct stratix10_svc_controller {
  * @ctrl: pointer to service controller which is the provider of this channel
  * @scl: pointer to service client which owns the channel
  * @name: service client name associated with the channel
+ * @task: pointer to the thread task which handles SMC or HVC call
+ * @svc_fifo: a queue for storing service message data (separate fifo for every channel)
+ * @svc_fifo_lock: protect access to service message data queue (locking pending fifo)
  * @lock: protect access to the channel
  * @async_chan: reference to asynchronous channel object for this channel
  *
@@ -293,6 +289,9 @@ struct stratix10_svc_chan {
 	struct stratix10_svc_controller *ctrl;
 	struct stratix10_svc_client *scl;
 	char *name;
+	struct task_struct *task;
+	struct kfifo svc_fifo;
+	spinlock_t svc_fifo_lock;
 	spinlock_t lock;
 	struct stratix10_async_chan *async_chan;
 };
@@ -527,10 +526,10 @@ static void svc_thread_recv_status_ok(st
  */
 static int svc_normal_to_secure_thread(void *data)
 {
-	struct stratix10_svc_controller
-			*ctrl = (struct stratix10_svc_controller *)data;
-	struct stratix10_svc_data *pdata;
-	struct stratix10_svc_cb_data *cbdata;
+	struct stratix10_svc_chan *chan = (struct stratix10_svc_chan *)data;
+	struct stratix10_svc_controller *ctrl = chan->ctrl;
+	struct stratix10_svc_data *pdata = NULL;
+	struct stratix10_svc_cb_data *cbdata = NULL;
 	struct arm_smccc_res res;
 	unsigned long a0, a1, a2, a3, a4, a5, a6, a7;
 	int ret_fifo = 0;
@@ -555,12 +554,12 @@ static int svc_normal_to_secure_thread(v
 	a6 = 0;
 	a7 = 0;
 
-	pr_debug("smc_hvc_shm_thread is running\n");
+	pr_debug("%s: %s: Thread is running!\n", __func__, chan->name);
 
 	while (!kthread_should_stop()) {
-		ret_fifo = kfifo_out_spinlocked(&ctrl->svc_fifo,
+		ret_fifo = kfifo_out_spinlocked(&chan->svc_fifo,
 						pdata, sizeof(*pdata),
-						&ctrl->svc_fifo_lock);
+						&chan->svc_fifo_lock);
 
 		if (!ret_fifo)
 			continue;
@@ -569,9 +568,25 @@ static int svc_normal_to_secure_thread(v
 			 (unsigned int)pdata->paddr, pdata->command,
 			 (unsigned int)pdata->size);
 
+		/* SDM can only process one command at a time */
+		pr_debug("%s: %s: Thread is waiting for mutex!\n",
+			 __func__, chan->name);
+		if (mutex_lock_interruptible(&ctrl->sdm_lock)) {
+			/* item already dequeued; notify client to unblock it */
+			cbdata->status = BIT(SVC_STATUS_ERROR);
+			cbdata->kaddr1 = NULL;
+			cbdata->kaddr2 = NULL;
+			cbdata->kaddr3 = NULL;
+			if (pdata->chan->scl)
+				pdata->chan->scl->receive_cb(pdata->chan->scl,
+							     cbdata);
+			break;
+		}
+
 		switch (pdata->command) {
 		case COMMAND_RECONFIG_DATA_CLAIM:
 			svc_thread_cmd_data_claim(ctrl, pdata, cbdata);
+			mutex_unlock(&ctrl->sdm_lock);
 			continue;
 		case COMMAND_RECONFIG:
 			a0 = INTEL_SIP_SMC_FPGA_CONFIG_START;
@@ -700,10 +715,11 @@ static int svc_normal_to_secure_thread(v
 			break;
 		default:
 			pr_warn("it shouldn't happen\n");
-			break;
+			mutex_unlock(&ctrl->sdm_lock);
+			continue;
 		}
-		pr_debug("%s: before SMC call -- a0=0x%016x a1=0x%016x",
-			 __func__,
+		pr_debug("%s: %s: before SMC call -- a0=0x%016x a1=0x%016x",
+			 __func__, chan->name,
 			 (unsigned int)a0,
 			 (unsigned int)a1);
 		pr_debug(" a2=0x%016x\n", (unsigned int)a2);
@@ -712,8 +728,8 @@ static int svc_normal_to_secure_thread(v
 		pr_debug(" a5=0x%016x\n", (unsigned int)a5);
 		ctrl->invoke_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res);
 
-		pr_debug("%s: after SMC call -- res.a0=0x%016x",
-			 __func__, (unsigned int)res.a0);
+		pr_debug("%s: %s: after SMC call -- res.a0=0x%016x",
+			 __func__, chan->name, (unsigned int)res.a0);
 		pr_debug(" res.a1=0x%016x, res.a2=0x%016x",
 			 (unsigned int)res.a1, (unsigned int)res.a2);
 		pr_debug(" res.a3=0x%016x\n", (unsigned int)res.a3);
@@ -728,6 +744,7 @@ static int svc_normal_to_secure_thread(v
 			cbdata->kaddr2 = NULL;
 			cbdata->kaddr3 = NULL;
 			pdata->chan->scl->receive_cb(pdata->chan->scl, cbdata);
+			mutex_unlock(&ctrl->sdm_lock);
 			continue;
 		}
 
@@ -801,6 +818,8 @@ static int svc_normal_to_secure_thread(v
 			break;
 
 		}
+
+		mutex_unlock(&ctrl->sdm_lock);
 	}
 
 	kfree(cbdata);
@@ -1696,22 +1715,33 @@ int stratix10_svc_send(struct stratix10_
 	if (!p_data)
 		return -ENOMEM;
 
-	/* first client will create kernel thread */
-	if (!chan->ctrl->task) {
-		chan->ctrl->task =
-			kthread_run_on_cpu(svc_normal_to_secure_thread,
-					   (void *)chan->ctrl,
-					   cpu, "svc_smc_hvc_thread");
-		if (IS_ERR(chan->ctrl->task)) {
+	/* first caller creates the per-channel kthread */
+	if (!chan->task) {
+		struct task_struct *task;
+
+		task = kthread_run_on_cpu(svc_normal_to_secure_thread,
+					  (void *)chan,
+					  cpu, "svc_smc_hvc_thread");
+		if (IS_ERR(task)) {
 			dev_err(chan->ctrl->dev,
 				"failed to create svc_smc_hvc_thread\n");
 			kfree(p_data);
 			return -EINVAL;
 		}
+
+		spin_lock(&chan->lock);
+		if (chan->task) {
+			/* another caller won the race; discard our thread */
+			spin_unlock(&chan->lock);
+			kthread_stop(task);
+		} else {
+			chan->task = task;
+			spin_unlock(&chan->lock);
+		}
 	}
 
-	pr_debug("%s: sent P-va=%p, P-com=%x, P-size=%u\n", __func__,
-		 p_msg->payload, p_msg->command,
+	pr_debug("%s: %s: sent P-va=%p, P-com=%x, P-size=%u\n", __func__,
+		 chan->name, p_msg->payload, p_msg->command,
 		 (unsigned int)p_msg->payload_length);
 
 	if (list_empty(&svc_data_mem)) {
@@ -1747,12 +1777,16 @@ int stratix10_svc_send(struct stratix10_
 	p_data->arg[2] = p_msg->arg[2];
 	p_data->size = p_msg->payload_length;
 	p_data->chan = chan;
-	pr_debug("%s: put to FIFO pa=0x%016x, cmd=%x, size=%u\n", __func__,
-	       (unsigned int)p_data->paddr, p_data->command,
-	       (unsigned int)p_data->size);
-	ret = kfifo_in_spinlocked(&chan->ctrl->svc_fifo, p_data,
+	pr_debug("%s: %s: put to FIFO pa=0x%016x, cmd=%x, size=%u\n",
+		 __func__,
+		 chan->name,
+		 (unsigned int)p_data->paddr,
+		 p_data->command,
+		 (unsigned int)p_data->size);
+
+	ret = kfifo_in_spinlocked(&chan->svc_fifo, p_data,
 				  sizeof(*p_data),
-				  &chan->ctrl->svc_fifo_lock);
+				  &chan->svc_fifo_lock);
 
 	kfree(p_data);
 
@@ -1773,11 +1807,12 @@ EXPORT_SYMBOL_GPL(stratix10_svc_send);
  */
 void stratix10_svc_done(struct stratix10_svc_chan *chan)
 {
-	/* stop thread when thread is running AND only one active client */
-	if (chan->ctrl->task && chan->ctrl->num_active_client <= 1) {
-		pr_debug("svc_smc_hvc_shm_thread is stopped\n");
-		kthread_stop(chan->ctrl->task);
-		chan->ctrl->task = NULL;
+	/* stop thread when thread is running */
+	if (chan->task) {
+		pr_debug("%s: %s: svc_smc_hvc_shm_thread is stopping\n",
+			 __func__, chan->name);
+		kthread_stop(chan->task);
+		chan->task = NULL;
 	}
 }
 EXPORT_SYMBOL_GPL(stratix10_svc_done);
@@ -1817,8 +1852,8 @@ void *stratix10_svc_allocate_memory(stru
 	pmem->paddr = pa;
 	pmem->size = s;
 	list_add_tail(&pmem->node, &svc_data_mem);
-	pr_debug("%s: va=%p, pa=0x%016x\n", __func__,
-		 pmem->vaddr, (unsigned int)pmem->paddr);
+	pr_debug("%s: %s: va=%p, pa=0x%016x\n", __func__,
+		 chan->name, pmem->vaddr, (unsigned int)pmem->paddr);
 
 	return (void *)va;
 }
@@ -1855,6 +1890,13 @@ static const struct of_device_id stratix
 	{},
 };
 
+static const char * const chan_names[SVC_NUM_CHANNEL] = {
+	SVC_CLIENT_FPGA,
+	SVC_CLIENT_RSU,
+	SVC_CLIENT_FCS,
+	SVC_CLIENT_HWMON
+};
+
 static int stratix10_svc_drv_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -1862,11 +1904,11 @@ static int stratix10_svc_drv_probe(struc
 	struct stratix10_svc_chan *chans;
 	struct gen_pool *genpool;
 	struct stratix10_svc_sh_memory *sh_memory;
-	struct stratix10_svc *svc;
+	struct stratix10_svc *svc = NULL;
 
 	svc_invoke_fn *invoke_fn;
 	size_t fifo_size;
-	int ret;
+	int ret, i = 0;
 
 	/* get SMC or HVC function */
 	invoke_fn = get_invoke_func(dev);
@@ -1905,8 +1947,8 @@ static int stratix10_svc_drv_probe(struc
 	controller->num_active_client = 0;
 	controller->chans = chans;
 	controller->genpool = genpool;
-	controller->task = NULL;
 	controller->invoke_fn = invoke_fn;
+	INIT_LIST_HEAD(&controller->node);
 	init_completion(&controller->complete_status);
 
 	ret = stratix10_svc_async_init(controller);
@@ -1917,32 +1959,20 @@ static int stratix10_svc_drv_probe(struc
 	}
 
 	fifo_size = sizeof(struct stratix10_svc_data) * SVC_NUM_DATA_IN_FIFO;
-	ret = kfifo_alloc(&controller->svc_fifo, fifo_size, GFP_KERNEL);
-	if (ret) {
-		dev_err(dev, "failed to allocate FIFO\n");
-		goto err_async_exit;
-	}
-	spin_lock_init(&controller->svc_fifo_lock);
+	mutex_init(&controller->sdm_lock);
 
-	chans[0].scl = NULL;
-	chans[0].ctrl = controller;
-	chans[0].name = SVC_CLIENT_FPGA;
-	spin_lock_init(&chans[0].lock);
-
-	chans[1].scl = NULL;
-	chans[1].ctrl = controller;
-	chans[1].name = SVC_CLIENT_RSU;
-	spin_lock_init(&chans[1].lock);
-
-	chans[2].scl = NULL;
-	chans[2].ctrl = controller;
-	chans[2].name = SVC_CLIENT_FCS;
-	spin_lock_init(&chans[2].lock);
-
-	chans[3].scl = NULL;
-	chans[3].ctrl = controller;
-	chans[3].name = SVC_CLIENT_HWMON;
-	spin_lock_init(&chans[3].lock);
+	for (i = 0; i < SVC_NUM_CHANNEL; i++) {
+		chans[i].scl = NULL;
+		chans[i].ctrl = controller;
+		chans[i].name = (char *)chan_names[i];
+		spin_lock_init(&chans[i].lock);
+		ret = kfifo_alloc(&chans[i].svc_fifo, fifo_size, GFP_KERNEL);
+		if (ret) {
+			dev_err(dev, "failed to allocate FIFO %d\n", i);
+			goto err_free_fifos;
+		}
+		spin_lock_init(&chans[i].svc_fifo_lock);
+	}
 
 	list_add_tail(&controller->node, &svc_ctrl);
 	platform_set_drvdata(pdev, controller);
@@ -1951,7 +1981,7 @@ static int stratix10_svc_drv_probe(struc
 	svc = devm_kzalloc(dev, sizeof(*svc), GFP_KERNEL);
 	if (!svc) {
 		ret = -ENOMEM;
-		goto err_free_kfifo;
+		goto err_free_fifos;
 	}
 	controller->svc = svc;
 
@@ -1959,51 +1989,43 @@ static int stratix10_svc_drv_probe(struc
 	if (!svc->stratix10_svc_rsu) {
 		dev_err(dev, "failed to allocate %s device\n", STRATIX10_RSU);
 		ret = -ENOMEM;
-		goto err_free_kfifo;
+		goto err_free_fifos;
 	}
 
 	ret = platform_device_add(svc->stratix10_svc_rsu);
-	if (ret) {
-		platform_device_put(svc->stratix10_svc_rsu);
-		goto err_free_kfifo;
-	}
-
-	svc->intel_svc_fcs = platform_device_alloc(INTEL_FCS, 1);
-	if (!svc->intel_svc_fcs) {
-		dev_err(dev, "failed to allocate %s device\n", INTEL_FCS);
-		ret = -ENOMEM;
-		goto err_unregister_rsu_dev;
-	}
-
-	ret = platform_device_add(svc->intel_svc_fcs);
-	if (ret) {
-		platform_device_put(svc->intel_svc_fcs);
-		goto err_unregister_rsu_dev;
-	}
+	if (ret)
+		goto err_put_device;
 
 	ret = of_platform_default_populate(dev_of_node(dev), NULL, dev);
 	if (ret)
-		goto err_unregister_fcs_dev;
+		goto err_unregister_rsu_dev;
 
 	pr_info("Intel Service Layer Driver Initialized\n");
 
 	return 0;
 
-err_unregister_fcs_dev:
-	platform_device_unregister(svc->intel_svc_fcs);
 err_unregister_rsu_dev:
 	platform_device_unregister(svc->stratix10_svc_rsu);
-err_free_kfifo:
-	kfifo_free(&controller->svc_fifo);
-err_async_exit:
+	goto err_free_fifos;
+err_put_device:
+	platform_device_put(svc->stratix10_svc_rsu);
+err_free_fifos:
+	/* only remove from list if list_add_tail() was reached */
+	if (!list_empty(&controller->node))
+		list_del(&controller->node);
+	/* free only the FIFOs that were successfully allocated */
+	while (i--)
+		kfifo_free(&chans[i].svc_fifo);
 	stratix10_svc_async_exit(controller);
 err_destroy_pool:
 	gen_pool_destroy(genpool);
+
 	return ret;
 }
 
 static void stratix10_svc_drv_remove(struct platform_device *pdev)
 {
+	int i;
 	struct stratix10_svc_controller *ctrl = platform_get_drvdata(pdev);
 	struct stratix10_svc *svc = ctrl->svc;
 
@@ -2011,14 +2033,16 @@ static void stratix10_svc_drv_remove(str
 
 	of_platform_depopulate(ctrl->dev);
 
-	platform_device_unregister(svc->intel_svc_fcs);
 	platform_device_unregister(svc->stratix10_svc_rsu);
 
-	kfifo_free(&ctrl->svc_fifo);
-	if (ctrl->task) {
-		kthread_stop(ctrl->task);
-		ctrl->task = NULL;
+	for (i = 0; i < SVC_NUM_CHANNEL; i++) {
+		if (ctrl->chans[i].task) {
+			kthread_stop(ctrl->chans[i].task);
+			ctrl->chans[i].task = NULL;
+		}
+		kfifo_free(&ctrl->chans[i].svc_fifo);
 	}
+
 	if (ctrl->genpool)
 		gen_pool_destroy(ctrl->genpool);
 	list_del(&ctrl->node);
include/linux/firmware/intel/stratix10-svc-client.h +4 -4
@@ -68,12 +68,12 @@
  * timeout value used in Stratix10 FPGA manager driver.
  * timeout value used in RSU driver
  */
-#define SVC_RECONFIG_REQUEST_TIMEOUT_MS         300
-#define SVC_RECONFIG_BUFFER_TIMEOUT_MS          720
-#define SVC_RSU_REQUEST_TIMEOUT_MS              300
+#define SVC_RECONFIG_REQUEST_TIMEOUT_MS         5000
+#define SVC_RECONFIG_BUFFER_TIMEOUT_MS          5000
+#define SVC_RSU_REQUEST_TIMEOUT_MS              2000
 #define SVC_FCS_REQUEST_TIMEOUT_MS		2000
 #define SVC_COMPLETED_TIMEOUT_MS		30000
-#define SVC_HWMON_REQUEST_TIMEOUT_MS		300
+#define SVC_HWMON_REQUEST_TIMEOUT_MS		2000
 
 struct stratix10_svc_chan;
 
author maintainer
#35 lore raw

PATCH 35/220 netconsole: fix sysdata_release_enabled_show checking wrong flag

In reply to Greg Kroah-Hartman

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

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

From: Breno Leitao <[email protected]>

[ Upstream commit 5af6e8b54927f7a8d3c7fd02b1bdc09e93d5c079 ]

sysdata_release_enabled_show() checks SYSDATA_TASKNAME instead of SYSDATA_RELEASE, causing the configfs release_enabled attribute to reflect the taskname feature state rather than the release feature state. This is a copy-paste error from the adjacent sysdata_taskname_enabled_show() function.

The corresponding _store function already uses the correct SYSDATA_RELEASE flag.

---
 drivers/net/netconsole.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/netconsole.c +1 -1
@@ -508,7 +508,7 @@ static ssize_t sysdata_release_enabled_s
 	bool release_enabled;
 
 	mutex_lock(&dynamic_netconsole_mutex);
-	release_enabled = !!(nt->sysdata_fields & SYSDATA_TASKNAME);
+	release_enabled = !!(nt->sysdata_fields & SYSDATA_RELEASE);
 	mutex_unlock(&dynamic_netconsole_mutex);
 
 	return sysfs_emit(buf, "%d\n", release_enabled);
author maintainer
#36 lore raw

PATCH 36/220 crypto: atmel-sha204a - Fix OOM ->tfm_count leak

In reply to Greg Kroah-Hartman

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

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

From: Thorsten Blum <[email protected]>

[ Upstream commit d240b079a37e90af03fd7dfec94930eb6c83936e ]

If memory allocation fails, decrement ->tfm_count to avoid blocking future reads.

Fixes da001fb651b0 ("crypto: atmel-i2c - add support for SHA204A random number generator")
[ adapted kmalloc_obj() macro to kmalloc(sizeof()) ]
---
 drivers/crypto/atmel-sha204a.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/crypto/atmel-sha204a.c +3 -2
@@ -52,9 +52,10 @@ static int atmel_sha204a_rng_read_nonblo
 		rng->priv = 0;
 	} else {
 		work_data = kmalloc(sizeof(*work_data), GFP_ATOMIC);
-		if (!work_data)
+		if (!work_data) {
+			atomic_dec(&i2c_priv->tfm_count);
 			return -ENOMEM;
-
+		}
 		work_data->ctx = i2c_priv;
 		work_data->client = i2c_priv->client;
 
author maintainer
#37 lore raw

PATCH 37/220 cifs: open files should not hold ref on superblock

In reply to Greg Kroah-Hartman

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

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

From: Shyam Prasad N <[email protected]>

[ Upstream commit 340cea84f691c5206561bb2e0147158fe02070be ]

Today whenever we deal with a file, in addition to holding a reference on the dentry, we also get a reference on the superblock. This happens in two cases:
1. when a new cinode is allocated
2. when an oplock break is being processed

The reasoning for holding the superblock ref was to make sure that when umount happens, if there are users of inodes and dentries, it does not try to clean them up and wait for the last ref to superblock to be dropped by last of such users.

But the side effect of doing that is that umount silently drops a ref on the superblock and we could have deferred closes and lease breaks still holding these refs.

Ideally, we should ensure that all of these users of inodes and dentries are cleaned up at the time of umount, which is what this code is doing.

This code change allows these code paths to use a ref on the dentry (and hence the inode). That way, umount is ensured to clean up SMB client resources when it's the last ref on the superblock (For ex: when same objects are shared).

The code change also moves the call to close all the files in deferred close list to the umount code path. It also waits for oplock_break workers to be flushed before calling kill_anon_super (which eventually frees up those objects).

Fixes 24261fc23db9 ("cifs: delay super block destruction until all cifsFileInfo objects are gone")
Fixes 705c79101ccf ("smb: client: fix use-after-free in cifs_oplock_break")
[ replaced kmalloc_obj() with kmalloc(sizeof(...)) ]
---
 fs/smb/client/cifsfs.c    |    7 +++++--
 fs/smb/client/cifsproto.h |    1 +
 fs/smb/client/file.c      |   11 -----------
 fs/smb/client/misc.c      |   42 ++++++++++++++++++++++++++++++++++++++++++
 fs/smb/client/trace.h     |    2 ++
 5 files changed, 50 insertions(+), 13 deletions(-)
fs/smb/client/cifsfs.c +5 -2
@@ -331,10 +331,14 @@ static void cifs_kill_sb(struct super_bl
 
 	/*
 	 * We need to release all dentries for the cached directories
-	 * before we kill the sb.
+	 * and close all deferred file handles before we kill the sb.
 	 */
 	if (cifs_sb->root) {
 		close_all_cached_dirs(cifs_sb);
+		cifs_close_all_deferred_files_sb(cifs_sb);
+
+		/* Wait for all pending oplock breaks to complete */
+		flush_workqueue(cifsoplockd_wq);
 
 		/* finally release root dentry */
 		dput(cifs_sb->root);
@@ -865,7 +869,6 @@ static void cifs_umount_begin(struct sup
 	spin_unlock(&tcon->tc_lock);
 	spin_unlock(&cifs_tcp_ses_lock);
 
-	cifs_close_all_deferred_files(tcon);
 	/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
 	/* cancel_notify_requests(tcon); */
 	if (tcon->ses && tcon->ses->server) {
fs/smb/client/cifsproto.h +1 -0
@@ -302,6 +302,7 @@ extern void cifs_close_deferred_file(str
 
 extern void cifs_close_all_deferred_files(struct cifs_tcon *cifs_tcon);
 
+void cifs_close_all_deferred_files_sb(struct cifs_sb_info *cifs_sb);
 void cifs_close_deferred_file_under_dentry(struct cifs_tcon *cifs_tcon,
 					   struct dentry *dentry);
 
fs/smb/client/file.c +0 -11
@@ -705,8 +705,6 @@ struct cifsFileInfo *cifs_new_fileinfo(s
 	mutex_init(&cfile->fh_mutex);
 	spin_lock_init(&cfile->file_info_lock);
 
-	cifs_sb_active(inode->i_sb);
-
 	/*
 	 * If the server returned a read oplock and we have mandatory brlocks,
 	 * set oplock level to None.
@@ -761,7 +759,6 @@ static void cifsFileInfo_put_final(struc
 	struct inode *inode = d_inode(cifs_file->dentry);
 	struct cifsInodeInfo *cifsi = CIFS_I(inode);
 	struct cifsLockInfo *li, *tmp;
-	struct super_block *sb = inode->i_sb;
 
 	/*
 	 * Delete any outstanding lock records. We'll lose them when the file
@@ -779,7 +776,6 @@ static void cifsFileInfo_put_final(struc
 
 	cifs_put_tlink(cifs_file->tlink);
 	dput(cifs_file->dentry);
-	cifs_sb_deactive(sb);
 	kfree(cifs_file->symlink_target);
 	kfree(cifs_file);
 }
@@ -3151,12 +3147,6 @@ void cifs_oplock_break(struct work_struc
 	__u64 persistent_fid, volatile_fid;
 	__u16 net_fid;
 
-	/*
-	 * Hold a reference to the superblock to prevent it and its inodes from
-	 * being freed while we are accessing cinode. Otherwise, _cifsFileInfo_put()
-	 * may release the last reference to the sb and trigger inode eviction.
-	 */
-	cifs_sb_active(sb);
 	wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS,
 			TASK_UNINTERRUPTIBLE);
 
@@ -3229,7 +3219,6 @@ oplock_break_ack:
 	cifs_put_tlink(tlink);
 out:
 	cifs_done_oplock_break(cinode);
-	cifs_sb_deactive(sb);
 }
 
 static int cifs_swap_activate(struct swap_info_struct *sis,
fs/smb/client/misc.c +42 -0

54 lines not on this page · raw message

fs/smb/client/trace.h +2 -0
@@ -177,6 +177,7 @@
 	EM(netfs_trace_tcon_ref_get_cached_laundromat,	"GET Ch-Lau") \
 	EM(netfs_trace_tcon_ref_get_cached_lease_break,	"GET Ch-Lea") \
 	EM(netfs_trace_tcon_ref_get_cancelled_close,	"GET Cn-Cls") \
+	EM(netfs_trace_tcon_ref_get_close_defer_files,	"GET Cl-Def") \
 	EM(netfs_trace_tcon_ref_get_dfs_refer,		"GET DfsRef") \
 	EM(netfs_trace_tcon_ref_get_find,		"GET Find  ") \
 	EM(netfs_trace_tcon_ref_get_find_sess_tcon,	"GET FndSes") \
@@ -188,6 +189,7 @@
 	EM(netfs_trace_tcon_ref_put_cancelled_close,	"PUT Cn-Cls") \
 	EM(netfs_trace_tcon_ref_put_cancelled_close_fid, "PUT Cn-Fid") \
 	EM(netfs_trace_tcon_ref_put_cancelled_mid,	"PUT Cn-Mid") \
+	EM(netfs_trace_tcon_ref_put_close_defer_files,	"PUT Cl-Def") \
 	EM(netfs_trace_tcon_ref_put_mnt_ctx,		"PUT MntCtx") \
 	EM(netfs_trace_tcon_ref_put_dfs_refer,		"PUT DfsRfr") \
 	EM(netfs_trace_tcon_ref_put_reconnect_server,	"PUT Reconn") \
author maintainer
#38 lore raw

PATCH 38/220 drm/xe: Fix memory leak in xe_vm_madvise_ioctl

In reply to Greg Kroah-Hartman

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

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

From: Varun Gupta <[email protected]>

[ Upstream commit 0cfe9c4838f1147713f6b5c02094cd4dc0c598fa ]

When check_bo_args_are_sane() validation fails, jump to the new free_vmas cleanup label to properly free the allocated resources. This ensures proper cleanup in this error path.

Fixes 293032eec4ba ("drm/xe/bo: Update atomic_access attribute on madvise")
Cc [email protected] # v6.18+
(cherry picked from commit 29bd06faf727a4b76663e4be0f7d770e2d2a7965)
[ changed old goto target from `madv_fini` to `unlock_vm` ]
---
 drivers/gpu/drm/xe/xe_vm_madvise.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/xe/xe_vm_madvise.c +2 -1
@@ -390,7 +390,7 @@ int xe_vm_madvise_ioctl(struct drm_devic
 						    madvise_range.num_vmas,
 						    args->atomic.val)) {
 				err = -EINVAL;
-				goto unlock_vm;
+				goto free_vmas;
 			}
 		}
 
@@ -426,6 +426,7 @@ int xe_vm_madvise_ioctl(struct drm_devic
 err_fini:
 	if (madvise_range.has_bo_vmas)
 		drm_exec_fini(&exec);
+free_vmas:
 	kfree(madvise_range.vmas);
 	madvise_range.vmas = NULL;
 unlock_vm:
author maintainer
#39 lore raw

PATCH 39/220 ipmi: Consolidate the run to completion checking for xmit msgs lock

In reply to Greg Kroah-Hartman

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

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

From: Corey Minyard <[email protected]>

[ Upstream commit 1d90e6c1a56f6ab83e5c9d30ded19e7ac8155713 ]

It made things hard to read, move the check to a function.

Stable-dep-of: 62cd145453d5 ("ipmi:msghandler: Handle error returns from the SMI sender")

---
 drivers/char/ipmi/ipmi_msghandler.c |   42 ++++++++++++++++++++----------------
 1 file changed, 24 insertions(+), 18 deletions(-)
drivers/char/ipmi/ipmi_msghandler.c +24 -18
@@ -602,6 +602,22 @@ static int __ipmi_bmc_register(struct ip
 static int __scan_channels(struct ipmi_smi *intf,
 				struct ipmi_device_id *id, bool rescan);
 
+static void ipmi_lock_xmit_msgs(struct ipmi_smi *intf, int run_to_completion,
+				unsigned long *flags)
+{
+	if (run_to_completion)
+		return;
+	spin_lock_irqsave(&intf->xmit_msgs_lock, *flags);
+}
+
+static void ipmi_unlock_xmit_msgs(struct ipmi_smi *intf, int run_to_completion,
+				  unsigned long *flags)
+{
+	if (run_to_completion)
+		return;
+	spin_unlock_irqrestore(&intf->xmit_msgs_lock, *flags);
+}
+
 static void free_ipmi_user(struct kref *ref)
 {
 	struct ipmi_user *user = container_of(ref, struct ipmi_user, refcount);
@@ -1878,11 +1894,9 @@ static void smi_send(struct ipmi_smi *in
 	int run_to_completion = READ_ONCE(intf->run_to_completion);
 	unsigned long flags = 0;
 
-	if (!run_to_completion)
-		spin_lock_irqsave(&intf->xmit_msgs_lock, flags);
+	ipmi_lock_xmit_msgs(intf, run_to_completion, &flags);
 	smi_msg = smi_add_send_msg(intf, smi_msg, priority);
-	if (!run_to_completion)
-		spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags);
+	ipmi_unlock_xmit_msgs(intf, run_to_completion, &flags);
 
 	if (smi_msg)
 		handlers->sender(intf->send_info, smi_msg);
@@ -4826,8 +4840,7 @@ static void smi_work(struct work_struct
 	 * message delivery.
 	 */
 restart:
-	if (!run_to_completion)
-		spin_lock_irqsave(&intf->xmit_msgs_lock, flags);
+	ipmi_lock_xmit_msgs(intf, run_to_completion, &flags);
 	if (intf->curr_msg == NULL && !intf->in_shutdown) {
 		struct list_head *entry = NULL;
 
@@ -4843,8 +4856,7 @@ restart:
 			intf->curr_msg = newmsg;
 		}
 	}
-	if (!run_to_completion)
-		spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags);
+	ipmi_unlock_xmit_msgs(intf, run_to_completion, &flags);
 
 	if (newmsg) {
 		cc = intf->handlers->sender(intf->send_info, newmsg);
@@ -4852,13 +4864,9 @@ restart:
 			if (newmsg->recv_msg)
 				deliver_err_response(intf,
 						     newmsg->recv_msg, cc);
-			if (!run_to_completion)
-				spin_lock_irqsave(&intf->xmit_msgs_lock,
-						  flags);
+			ipmi_lock_xmit_msgs(intf, run_to_completion, &flags);
 			intf->curr_msg = NULL;
-			if (!run_to_completion)
-				spin_unlock_irqrestore(&intf->xmit_msgs_lock,
-						       flags);
+			ipmi_unlock_xmit_msgs(intf, run_to_completion, &flags);
 			ipmi_free_smi_msg(newmsg);
 			newmsg = NULL;
 			goto restart;
@@ -4928,16 +4936,14 @@ void ipmi_smi_msg_received(struct ipmi_s
 		spin_unlock_irqrestore(&intf->waiting_rcv_msgs_lock,
 				       flags);
 
-	if (!run_to_completion)
-		spin_lock_irqsave(&intf->xmit_msgs_lock, flags);
+	ipmi_lock_xmit_msgs(intf, run_to_completion, &flags);
 	/*
 	 * We can get an asynchronous event or receive message in addition
 	 * to commands we send.
 	 */
 	if (msg == intf->curr_msg)
 		intf->curr_msg = NULL;
-	if (!run_to_completion)
-		spin_unlock_irqrestore(&intf->xmit_msgs_lock, flags);
+	ipmi_unlock_xmit_msgs(intf, run_to_completion, &flags);
 
 	if (run_to_completion)
 		smi_work(&intf->smi_work);
author maintainer
#40 lore raw

PATCH 40/220 ipmi:msghandler: Handle error returns from the SMI sender

In reply to Greg Kroah-Hartman

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

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

From: Corey Minyard <[email protected]>

[ Upstream commit 62cd145453d577113f993efd025f258dd86aa183 ]

It used to be, until recently, that the sender operation on the low level interfaces would not fail. That's not the case any more with recent changes.

So check the return value from the sender operation, and propagate it back up from there and handle the errors in all places.

Fixes bc3a9d217755 ("ipmi:si: Gracefully handle if the BMC is non-functional")
---
 drivers/char/ipmi/ipmi_msghandler.c |  100 ++++++++++++++++++++++++------------
 1 file changed, 68 insertions(+), 32 deletions(-)
drivers/char/ipmi/ipmi_msghandler.c +68 -32
@@ -1887,19 +1887,32 @@ static struct ipmi_smi_msg *smi_add_send
 	return smi_msg;
 }
 
-static void smi_send(struct ipmi_smi *intf,
+static int smi_send(struct ipmi_smi *intf,
 		     const struct ipmi_smi_handlers *handlers,
 		     struct ipmi_smi_msg *smi_msg, int priority)
 {
 	int run_to_completion = READ_ONCE(intf->run_to_completion);
 	unsigned long flags = 0;
+	int rv = 0;
 
 	ipmi_lock_xmit_msgs(intf, run_to_completion, &flags);
 	smi_msg = smi_add_send_msg(intf, smi_msg, priority);
 	ipmi_unlock_xmit_msgs(intf, run_to_completion, &flags);
 
-	if (smi_msg)
-		handlers->sender(intf->send_info, smi_msg);
+	if (smi_msg) {
+		rv = handlers->sender(intf->send_info, smi_msg);
+		if (rv) {
+			ipmi_lock_xmit_msgs(intf, run_to_completion, &flags);
+			intf->curr_msg = NULL;
+			ipmi_unlock_xmit_msgs(intf, run_to_completion, &flags);
+			/*
+			 * Something may have been added to the transmit
+			 * queue, so schedule a check for that.
+			 */
+			queue_work(system_wq, &intf->smi_work);
+		}
+	}
+	return rv;
 }
 
 static bool is_maintenance_mode_cmd(struct kernel_ipmi_msg *msg)
@@ -2312,6 +2325,7 @@ static int i_ipmi_request(struct ipmi_us
 	struct ipmi_recv_msg *recv_msg;
 	int run_to_completion = READ_ONCE(intf->run_to_completion);
 	int rv = 0;
+	bool in_seq_table = false;
 
 	if (supplied_recv) {
 		recv_msg = supplied_recv;
@@ -2365,33 +2379,50 @@ static int i_ipmi_request(struct ipmi_us
 		rv = i_ipmi_req_ipmb(intf, addr, msgid, msg, smi_msg, recv_msg,
 				     source_address, source_lun,
 				     retries, retry_time_ms);
+		in_seq_table = true;
 	} else if (is_ipmb_direct_addr(addr)) {
 		rv = i_ipmi_req_ipmb_direct(intf, addr, msgid, msg, smi_msg,
 					    recv_msg, source_lun);
 	} else if (is_lan_addr(addr)) {
 		rv = i_ipmi_req_lan(intf, addr, msgid, msg, smi_msg, recv_msg,
 				    source_lun, retries, retry_time_ms);
+		in_seq_table = true;
 	} else {
-	    /* Unknown address type. */
+		/* Unknown address type. */
 		ipmi_inc_stat(intf, sent_invalid_commands);
 		rv = -EINVAL;
 	}
 
-	if (rv) {
-out_err:
-		if (!supplied_smi)
-			ipmi_free_smi_msg(smi_msg);
-		if (!supplied_recv)
-			ipmi_free_recv_msg(recv_msg);
-	} else {
+	if (!rv) {
 		dev_dbg(intf->si_dev, "Send: %*ph\n",
 			smi_msg->data_size, smi_msg->data);
 
-		smi_send(intf, intf->handlers, smi_msg, priority);
+		rv = smi_send(intf, intf->handlers, smi_msg, priority);
+		if (rv != IPMI_CC_NO_ERROR)
+			/* smi_send() returns an IPMI err, return a Linux one. */
+			rv = -EIO;
+		if (rv && in_seq_table) {
+			/*
+			 * If it's in the sequence table, it will be
+			 * retried later, so ignore errors.
+			 */
+			rv = 0;
+			/* But we need to fix the timeout. */
+			intf_start_seq_timer(intf, smi_msg->msgid);
+			ipmi_free_smi_msg(smi_msg);
+			smi_msg = NULL;
+		}
 	}
+out_err:
 	if (!run_to_completion)
 		mutex_unlock(&intf->users_mutex);
 
+	if (rv) {
+		if (!supplied_smi)
+			ipmi_free_smi_msg(smi_msg);
+		if (!supplied_recv)
+			ipmi_free_recv_msg(recv_msg);
+	}
 	return rv;
 }
 
@@ -3965,12 +3996,12 @@ static int handle_ipmb_get_msg_cmd(struc
 		dev_dbg(intf->si_dev, "Invalid command: %*ph\n",
 			msg->data_size, msg->data);
 
-		smi_send(intf, intf->handlers, msg, 0);
-		/*
-		 * We used the message, so return the value that
-		 * causes it to not be freed or queued.
-		 */
-		rv = -1;
+		if (smi_send(intf, intf->handlers, msg, 0) == IPMI_CC_NO_ERROR)
+			/*
+			 * We used the message, so return the value that
+			 * causes it to not be freed or queued.
+			 */
+			rv = -1;
 	} else if (!IS_ERR(recv_msg)) {
 		/* Extract the source address from the data. */
 		ipmb_addr = (struct ipmi_ipmb_addr *) &recv_msg->addr;
@@ -4044,12 +4075,12 @@ static int handle_ipmb_direct_rcv_cmd(st
 		msg->data[4] = IPMI_INVALID_CMD_COMPLETION_CODE;
 		msg->data_size = 5;
 
-		smi_send(intf, intf->handlers, msg, 0);
-		/*
-		 * We used the message, so return the value that
-		 * causes it to not be freed or queued.
-		 */
-		rv = -1;
+		if (smi_send(intf, intf->handlers, msg, 0) == IPMI_CC_NO_ERROR)
+			/*
+			 * We used the message, so return the value that
+			 * causes it to not be freed or queued.
+			 */
+			rv = -1;
 	} else if (!IS_ERR(recv_msg)) {
 		/* Extract the source address from the data. */
 		daddr = (struct ipmi_ipmb_direct_addr *)&recv_msg->addr;
@@ -4189,7 +4220,7 @@ static int handle_lan_get_msg_cmd(struct
 				  struct ipmi_smi_msg *msg)
 {
 	struct cmd_rcvr          *rcvr;
-	int                      rv = 0;
+	int                      rv = 0; /* Free by default */
 	unsigned char            netfn;
 	unsigned char            cmd;
 	unsigned char            chan;
@@ -4242,12 +4273,12 @@ static int handle_lan_get_msg_cmd(struct
 		dev_dbg(intf->si_dev, "Invalid command: %*ph\n",
 			msg->data_size, msg->data);
 
-		smi_send(intf, intf->handlers, msg, 0);
-		/*
-		 * We used the message, so return the value that
-		 * causes it to not be freed or queued.
-		 */
-		rv = -1;
+		if (smi_send(intf, intf->handlers, msg, 0) == IPMI_CC_NO_ERROR)
+			/*
+			 * We used the message, so return the value that
+			 * causes it to not be freed or queued.
+			 */
+			rv = -1;
 	} else if (!IS_ERR(recv_msg)) {
 		/* Extract the source address from the data. */
 		lan_addr = (struct ipmi_lan_addr *) &recv_msg->addr;
@@ -5056,7 +5087,12 @@ static void check_msg_timeout(struct ipm
 				ipmi_inc_stat(intf,
 					      retransmitted_ipmb_commands);
 
-			smi_send(intf, intf->handlers, smi_msg, 0);
+			/* If this fails we'll retry later or timeout. */
+			if (smi_send(intf, intf->handlers, smi_msg, 0) != IPMI_CC_NO_ERROR) {
+				/* But fix the timeout. */
+				intf_start_seq_timer(intf, smi_msg->msgid);
+				ipmi_free_smi_msg(smi_msg);
+			}
 		} else
 			ipmi_free_smi_msg(smi_msg);
 
author maintainer
#41 lore raw

PATCH 41/220 ata: libata-core: disable LPM on ADATA SU680 SSD

In reply to Greg Kroah-Hartman

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

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

From: Damien Le Moal <[email protected]>

commit ce5ae93d1a216680460040c7c0465a6e3b629dec upstream.

ADATA SU680 SSDs suffer from NCQ read and write commands timeouts or bus errors when link power management (LPM) is enabled. Flag these devices with the ATA_QUIRK_NOLPM quirk to prevent the use of LPM and avoid these command failures.

---
 drivers/ata/libata-core.c |    3 +++
 1 file changed, 3 insertions(+)
drivers/ata/libata-core.c +3 -0
@@ -4185,6 +4185,9 @@ static const struct ata_dev_quirks_entry
 	{ "ST3320[68]13AS",	"SD1[5-9]",	ATA_QUIRK_NONCQ |
 						ATA_QUIRK_FIRMWARE_WARN },
 
+	/* ADATA devices with LPM issues. */
+	{ "ADATA SU680",	NULL,		ATA_QUIRK_NOLPM },
+
 	/* Seagate disks with LPM issues */
 	{ "ST1000DM010-2EP102",	NULL,		ATA_QUIRK_NOLPM },
 	{ "ST2000DM008-2FR102",	NULL,		ATA_QUIRK_NOLPM },
author maintainer
#42 lore raw

PATCH 42/220 ata: libata-scsi: report correct sense field pointer in ata_scsiop_maint_in()

In reply to Greg Kroah-Hartman

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

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

From: Damien Le Moal <[email protected]>

commit e6d7eba23b666d85cacee0643be280d6ce1ebffc upstream.

Commit 4ab7bb976343 ("ata: libata-scsi: Refactor ata_scsiop_maint_in()") modified ata_scsiop_maint_in() to directly call ata_scsi_set_invalid_field() to set the field pointer of the sense data of a failed MAINTENANCE IN command. However, in the case of an invalid command format, the sense data field incorrectly indicates byte 1 of the CDB. Fix this to indicate byte 2 of the command.

Fixes 4ab7bb976343 ("ata: libata-scsi: Refactor ata_scsiop_maint_in()")
---
 drivers/ata/libata-scsi.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/ata/libata-scsi.c +1 -1
@@ -3600,7 +3600,7 @@ static unsigned int ata_scsiop_maint_in(
 
 	if (cdb[2] != 1 && cdb[2] != 3) {
 		ata_dev_warn(dev, "invalid command format %d\n", cdb[2]);
-		ata_scsi_set_invalid_field(dev, cmd, 1, 0xff);
+		ata_scsi_set_invalid_field(dev, cmd, 2, 0xff);
 		return 0;
 	}
 
author maintainer
#43 lore raw

PATCH 43/220 mmc: sdhci-pci-gli: fix GL9750 DMA write corruption

In reply to Greg Kroah-Hartman

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

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

From: Matthew Schwartz <[email protected]>

commit 2b76e0cc7803e5ab561c875edaba7f6bbd87fbb0 upstream.

The GL9750 SD host controller has intermittent data corruption during DMA write operations. The GM_BURST register's R_OSRC_Lmt field (bits 17:16), which limits outstanding DMA read requests from system memory, is not being cleared during initialization. The Windows driver sets R_OSRC_Lmt to zero, limiting requests to the smallest unit.

Clear R_OSRC_Lmt to match the Windows driver behavior. This eliminates write corruption verified with f3write/f3read tests while maintaining DMA performance.

---
 drivers/mmc/host/sdhci-pci-gli.c |    9 +++++++++
 1 file changed, 9 insertions(+)
drivers/mmc/host/sdhci-pci-gli.c +9 -0
@@ -68,6 +68,9 @@
 #define   GLI_9750_MISC_TX1_DLY_VALUE    0x5
 #define   SDHCI_GLI_9750_MISC_SSC_OFF    BIT(26)
 
+#define SDHCI_GLI_9750_GM_BURST_SIZE		  0x510
+#define   SDHCI_GLI_9750_GM_BURST_SIZE_R_OSRC_LMT  GENMASK(17, 16)
+
 #define SDHCI_GLI_9750_TUNING_CONTROL	          0x540
 #define   SDHCI_GLI_9750_TUNING_CONTROL_EN          BIT(4)
 #define   GLI_9750_TUNING_CONTROL_EN_ON             0x1
@@ -345,10 +348,16 @@ static void gli_set_9750(struct sdhci_ho
 	u32 misc_value;
 	u32 parameter_value;
 	u32 control_value;
+	u32 burst_value;
 	u16 ctrl2;
 
 	gl9750_wt_on(host);
 
+	/* clear R_OSRC_Lmt to avoid DMA write corruption */
+	burst_value = sdhci_readl(host, SDHCI_GLI_9750_GM_BURST_SIZE);
+	burst_value &= ~SDHCI_GLI_9750_GM_BURST_SIZE_R_OSRC_LMT;
+	sdhci_writel(host, burst_value, SDHCI_GLI_9750_GM_BURST_SIZE);
+
 	driving_value = sdhci_readl(host, SDHCI_GLI_9750_DRIVING);
 	pll_value = sdhci_readl(host, SDHCI_GLI_9750_PLL);
 	sw_ctrl_value = sdhci_readl(host, SDHCI_GLI_9750_SW_CTRL);
author maintainer
#44 lore raw

PATCH 44/220 mmc: sdhci: fix timing selection for 1-bit bus width

In reply to Greg Kroah-Hartman

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

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

From: Luke Wang <[email protected]>

commit 5e3486e64094c28a526543f1e8aa0d5964b7f02d upstream.

When 1-bit bus width is used with HS200/HS400 capabilities set, mmc_select_hs200() returns 0 without actually switching. This causes mmc_select_timing() to skip mmc_select_hs(), leaving eMMC in legacy mode (26MHz) instead of High Speed SDR (52MHz).

Per JEDEC eMMC spec section 5.3.2, 1-bit mode supports High Speed SDR. Drop incompatible HS200/HS400/UHS/DDR caps early so timing selection falls through to mmc_select_hs() correctly.

Fixes f2119df6b764 ("mmc: sd: add support for signal voltage switch procedure")
---
 drivers/mmc/host/sdhci.c |    9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/mmc/host/sdhci.c +8 -1
@@ -4532,8 +4532,15 @@ int sdhci_setup_host(struct sdhci_host *
 	 * their platform code before calling sdhci_add_host(), and we
 	 * won't assume 8-bit width for hosts without that CAP.
 	 */
-	if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA))
+	if (host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA) {
+		host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50);
+		if (host->quirks2 & SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400)
+			host->caps1 &= ~SDHCI_SUPPORT_HS400;
+		mmc->caps2 &= ~(MMC_CAP2_HS200 | MMC_CAP2_HS400 | MMC_CAP2_HS400_ES);
+		mmc->caps &= ~(MMC_CAP_DDR | MMC_CAP_UHS);
+	} else {
 		mmc->caps |= MMC_CAP_4_BIT_DATA;
+	}
 
 	if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23)
 		mmc->caps &= ~MMC_CAP_CMD23;
author maintainer
#45 lore raw

PATCH 45/220 pmdomain: mediatek: Fix power domain count

In reply to Greg Kroah-Hartman

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

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

From: Adam Ford <[email protected]>

commit b22c526569e6af84008b674e66378e771bfbdd94 upstream.

The wrong value of the number of domains is wrong which leads to failures when trying to enumerate nested power domains.

PM: genpd_xlate_onecell: invalid domain index 0
PM: genpd_xlate_onecell: invalid domain index 1
PM: genpd_xlate_onecell: invalid domain index 3
PM: genpd_xlate_onecell: invalid domain index 4
PM: genpd_xlate_onecell: invalid domain index 5
PM: genpd_xlate_onecell: invalid domain index 13
PM: genpd_xlate_onecell: invalid domain index 14

Attempts to use these power domains fail, so fix this by using the correct value of calculated power domains.

Fixes 88914db077b6 ("pmdomain: mediatek: Add support for Hardware Voter power domains")
---
 drivers/pmdomain/mediatek/mtk-pm-domains.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pmdomain/mediatek/mtk-pm-domains.c +1 -1
index f64f24d520dd..e2800aa1bc59 100644
@@ -1203,7 +1203,7 @@ static int scpsys_probe(struct platform_device *pdev)
 	scpsys->soc_data = soc;
 
 	scpsys->pd_data.domains = scpsys->domains;
-	scpsys->pd_data.num_domains = soc->num_domains;
+	scpsys->pd_data.num_domains = num_domains;
 
 	parent = dev->parent;
 	if (!parent) {
Signature · 1 line
2.53.0
author maintainer
#46 lore raw

PATCH 46/220 pmdomain: bcm: bcm2835-power: Increase ASB control timeout

In reply to Greg Kroah-Hartman

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

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

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

commit b826d2c0b0ecb844c84431ba6b502e744f5d919a upstream.

The bcm2835_asb_control() function uses a tight polling loop to wait for the ASB bridge to acknowledge a request. During intensive workloads, this handshake intermittently fails for V3D's master ASB on BCM2711, resulting in "Failed to disable ASB master for v3d" errors during runtime PM suspend. As a consequence, the failed power-off leaves V3D in a broken state, leading to bus faults or system hangs on later accesses.

As the timeout is insufficient in some scenarios, increase the polling timeout from 1us to 5us, which is still negligible in the context of a power domain transition. Also, replace the open-coded ktime_get_ns()/ cpu_relax() polling loop with readl_poll_timeout_atomic().

Fixes 670c672608a1 ("soc: bcm: bcm2835-pm: Add support for power domains under a new binding.")
---
 drivers/pmdomain/bcm/bcm2835-power.c |   12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)
drivers/pmdomain/bcm/bcm2835-power.c +4 -8
@@ -9,6 +9,7 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/iopoll.h>
 #include <linux/mfd/bcm2835-pm.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -153,7 +154,6 @@ struct bcm2835_power {
 static int bcm2835_asb_control(struct bcm2835_power *power, u32 reg, bool enable)
 {
 	void __iomem *base = power->asb;
-	u64 start;
 	u32 val;
 
 	switch (reg) {
@@ -166,8 +166,6 @@ static int bcm2835_asb_control(struct bc
 		break;
 	}
 
-	start = ktime_get_ns();
-
 	/* Enable the module's async AXI bridges. */
 	if (enable) {
 		val = readl(base + reg) & ~ASB_REQ_STOP;
@@ -176,11 +174,9 @@ static int bcm2835_asb_control(struct bc
 	}
 	writel(PM_PASSWORD | val, base + reg);
 
-	while (!!(readl(base + reg) & ASB_ACK) == enable) {
-		cpu_relax();
-		if (ktime_get_ns() - start >= 1000)
-			return -ETIMEDOUT;
-	}
+	if (readl_poll_timeout_atomic(base + reg, val,
+				      !!(val & ASB_ACK) != enable, 0, 5))
+		return -ETIMEDOUT;
 
 	return 0;
 }
author maintainer
#47 lore raw

PATCH 47/220 spi: fix use-after-free on controller registration failure

In reply to Greg Kroah-Hartman

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

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

From: Johan Hovold <[email protected]>

commit 8634e05b08ead636e926022f4a98416e13440df9 upstream.

Make sure to deregister from driver core also in the unlikely event that per-cpu statistics allocation fails during controller registration to avoid use-after-free (of driver resources) and unclocked register accesses.

Fixes 6598b91b5ac3 ("spi: spi.c: Convert statistics to per-cpu u64_stats_t")
Cc David Jander <[email protected]>
---
 drivers/spi/spi.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/spi/spi.c +4 -4
@@ -3344,10 +3344,8 @@ int spi_register_controller(struct spi_c
 		dev_info(dev, "controller is unqueued, this is deprecated\n");
 	} else if (ctlr->transfer_one || ctlr->transfer_one_message) {
 		status = spi_controller_initialize_queue(ctlr);
-		if (status) {
-			device_del(&ctlr->dev);
-			goto free_bus_id;
-		}
+		if (status)
+			goto del_ctrl;
 	}
 	/* Add statistics */
 	ctlr->pcpu_statistics = spi_alloc_pcpu_stats(dev);
@@ -3370,6 +3368,8 @@ int spi_register_controller(struct spi_c
 
 destroy_queue:
 	spi_destroy_queue(ctlr);
+del_ctrl:
+	device_del(&ctlr->dev);
 free_bus_id:
 	mutex_lock(&board_lock);
 	idr_remove(&spi_controller_idr, ctlr->bus_num);
author maintainer
#48 lore raw

PATCH 48/220 spi: fix statistics allocation

In reply to Greg Kroah-Hartman

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

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

From: Johan Hovold <[email protected]>

commit dee0774bbb2abb172e9069ce5ffef579b12b3ae9 upstream.

The controller per-cpu statistics is not allocated until after the controller has been registered with driver core, which leaves a window where accessing the sysfs attributes can trigger a NULL-pointer dereference.

Fix this by moving the statistics allocation to controller allocation while tying its lifetime to that of the controller (rather than using implicit devres).

Fixes 6598b91b5ac3 ("spi: spi.c: Convert statistics to per-cpu u64_stats_t")
Cc David Jander <[email protected]>
---
 drivers/spi/spi.c |   17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)
drivers/spi/spi.c +8 -9
@@ -2914,6 +2914,8 @@ static void spi_controller_release(struc
 	struct spi_controller *ctlr;
 
 	ctlr = container_of(dev, struct spi_controller, dev);
+
+	free_percpu(ctlr->pcpu_statistics);
 	kfree(ctlr);
 }
 
@@ -3057,6 +3059,12 @@ struct spi_controller *__spi_alloc_contr
 	if (!ctlr)
 		return NULL;
 
+	ctlr->pcpu_statistics = spi_alloc_pcpu_stats(NULL);
+	if (!ctlr->pcpu_statistics) {
+		kfree(ctlr);
+		return NULL;
+	}
+
 	device_initialize(&ctlr->dev);
 	INIT_LIST_HEAD(&ctlr->queue);
 	spin_lock_init(&ctlr->queue_lock);
@@ -3347,13 +3355,6 @@ int spi_register_controller(struct spi_c
 		if (status)
 			goto del_ctrl;
 	}
-	/* Add statistics */
-	ctlr->pcpu_statistics = spi_alloc_pcpu_stats(dev);
-	if (!ctlr->pcpu_statistics) {
-		dev_err(dev, "Error allocating per-cpu statistics\n");
-		status = -ENOMEM;
-		goto destroy_queue;
-	}
 
 	mutex_lock(&board_lock);
 	list_add_tail(&ctlr->list, &spi_controller_list);
@@ -3366,8 +3367,6 @@ int spi_register_controller(struct spi_c
 	acpi_register_spi_devices(ctlr);
 	return status;
 
-destroy_queue:
-	spi_destroy_queue(ctlr);
 del_ctrl:
 	device_del(&ctlr->dev);
 free_bus_id:
author maintainer
#49 lore raw

PATCH 49/220 mtd: spi-nor: Fix RDCR controller capability core check

In reply to Greg Kroah-Hartman

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

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

From: Miquel Raynal <[email protected]>

commit ac512cd351f7e4ab4569f6a52c116f4ab3a239cc upstream.

Commit 5008c3ec3f89 ("mtd: spi-nor: core: Check read CR support") adds a controller check to make sure the core will not use CR reads on controllers not supporting them. The approach is valid but the fix is incorrect. Unfortunately, the author could not catch it, because the expected behavior was met. The patch indeed drops the RDCR capability, but it does it for all controllers!

The issue comes from the use of spi_nor_spimem_check_op() which is an internal helper dedicated to check read/write operations only, despite its generic name.

This helper looks for the biggest number of address bytes that can be used for a page operation and tries 4 then 3. It then calls the usual spi-mem helpers to do the checks. These will always fail because there is now an inconsistency: the address cycles are forced to 4 (then 3) bytes, but the bus width during the address cycles rightfully remains
0. There is a non-zero address length but a zero address bus width, which is an invalid combination.

The correct check in this case is to directly call spi_mem_supports_op() which doesn't messes up with the operation content.

---
 drivers/mtd/spi-nor/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/mtd/spi-nor/core.c +1 -1
index 8ffeb41c3e08..13201908a69f 100644
@@ -2466,7 +2466,7 @@ spi_nor_spimem_adjust_hwcaps(struct spi_nor *nor, u32 *hwcaps)
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
-		if (spi_nor_spimem_check_op(nor, &op))
+		if (!spi_mem_supports_op(nor->spimem, &op))
 			nor->flags |= SNOR_F_NO_READ_CR;
 	}
 }
Signature · 1 line
2.53.0
author maintainer
#50 lore raw

PATCH 50/220 mtd: rawnand: pl353: make sure optimal timings are applied

In reply to Greg Kroah-Hartman

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

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

From: Olivier Sobrie <[email protected]>

commit b9465b04de4b90228de03db9a1e0d56b00814366 upstream.

Timings of the nand are adjusted by pl35x_nfc_setup_interface() but actually applied by the pl35x_nand_select_target() function. If there is only one nand chip, the pl35x_nand_select_target() will only apply the timings once since the test at its beginning will always be true after the first call to this function. As a result, the hardware will keep using the default timings set at boot to detect the nand chip, not the optimal ones.

With this patch, we program directly the new timings when pl35x_nfc_setup_interface() is called.

Fixes 08d8c62164a3 ("mtd: rawnand: pl353: Add support for the ARM PL353 SMC NAND controller")
---
 drivers/mtd/nand/raw/pl35x-nand-controller.c |    3 +++
 1 file changed, 3 insertions(+)
drivers/mtd/nand/raw/pl35x-nand-controller.c +3 -0
@@ -862,6 +862,9 @@ static int pl35x_nfc_setup_interface(str
 			  PL35X_SMC_NAND_TAR_CYCLES(tmgs.t_ar) |
 			  PL35X_SMC_NAND_TRR_CYCLES(tmgs.t_rr);
 
+	writel(plnand->timings, nfc->conf_regs + PL35X_SMC_CYCLES);
+	pl35x_smc_update_regs(nfc);
+
 	return 0;
 }
 
author maintainer
#51 lore raw

PATCH 51/220 mtd: rawnand: cadence: Fix error check for dma_alloc_coherent() in cadence_nand_init()

In reply to Greg Kroah-Hartman

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

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

From: Chen Ni <[email protected]>

commit 0410e1a4c545c769c59c6eda897ad5d574d0c865 upstream.

Fix wrong variable used for error checking after dma_alloc_coherent() call. The function checks cdns_ctrl->dma_cdma_desc instead of cdns_ctrl->cdma_desc, which could lead to incorrect error handling.

Fixes ec4ba01e894d ("mtd: rawnand: Add new Cadence NAND driver to MTD subsystem")
---
 drivers/mtd/nand/raw/cadence-nand-controller.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/mtd/nand/raw/cadence-nand-controller.c +1 -1
@@ -3133,7 +3133,7 @@ static int cadence_nand_init(struct cdns
 						  sizeof(*cdns_ctrl->cdma_desc),
 						  &cdns_ctrl->dma_cdma_desc,
 						  GFP_KERNEL);
-	if (!cdns_ctrl->dma_cdma_desc)
+	if (!cdns_ctrl->cdma_desc)
 		return -ENOMEM;
 
 	cdns_ctrl->buf_size = SZ_16K;
author maintainer
#52 lore raw

PATCH 52/220 mtd: Avoid boot crash in RedBoot partition table parser

In reply to Greg Kroah-Hartman

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

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

From: Finn Thain <[email protected]>

commit 8e2f8020270af7777d49c2e7132260983e4fc566 upstream.

Given CONFIG_FORTIFY_SOURCE=y and a recent compiler,
commit 439a1bcac648 ("fortify: Use __builtin_dynamic_object_size() when available") produces the warning below and an oops.

    Searching for RedBoot partition table in 50000000.flash at offset 0x7e0000
    ------------[ cut here ]------------
    WARNING: lib/string_helpers.c:1035 at 0xc029e04c, CPU#0: swapper/0/1
    memcmp: detected buffer overflow: 15 byte read of buffer size 14
    Modules linked in:
    CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.19.0 #1 NONE

As Kees said, "'names' is pointing to the final 'namelen' many bytes of the allocation ... 'namelen' could be basically any length at all. This fortify warning looks legit to me -- this code used to be reading beyond the end of the allocation."

Since the size of the dynamic allocation is calculated with strlen() we can use strcmp() instead of memcmp() and remain within bounds.

---
 drivers/mtd/parsers/redboot.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/mtd/parsers/redboot.c +3 -3
@@ -270,9 +270,9 @@ nogood:
 
 		strcpy(names, fl->img->name);
 #ifdef CONFIG_MTD_REDBOOT_PARTS_READONLY
-		if (!memcmp(names, "RedBoot", 8) ||
-		    !memcmp(names, "RedBoot config", 15) ||
-		    !memcmp(names, "FIS directory", 14)) {
+		if (!strcmp(names, "RedBoot") ||
+		    !strcmp(names, "RedBoot config") ||
+		    !strcmp(names, "FIS directory")) {
 			parts[i].mask_flags = MTD_WRITEABLE;
 		}
 #endif
author maintainer
#53 lore raw

PATCH 53/220 iommu/vt-d: Fix intel iommu iotlb sync hardlockup and retry

In reply to Greg Kroah-Hartman

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

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

From: Guanghui Feng <[email protected]>

commit fe89277c9ceb0d6af0aa665bcf24a41d8b1b79cd upstream.

During the qi_check_fault process after an IOMMU ITE event, requests at odd-numbered positions in the queue are set to QI_ABORT, only satisfying single-request submissions. However, qi_submit_sync now supports multiple simultaneous submissions, and can't guarantee that the wait_desc will be at an odd-numbered position. Therefore, if an item times out, IOMMU can't re-initiate the request, resulting in an infinite polling wait.

This modifies the process by setting the status of all requests already fetched by IOMMU and recorded as QI_IN_USE status (including wait_desc requests) to QI_ABORT, thus enabling multiple requests to be resubmitted.

Fixes 8a1d82462540 ("iommu/vt-d: Multiple descriptors per qi_submit_sync()")
Fixes 8a1d82462540 ("iommu/vt-d: Multiple descriptors per qi_submit_sync()")
---
 drivers/iommu/intel/dmar.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/iommu/intel/dmar.c +1 -2
@@ -1314,7 +1314,6 @@ static int qi_check_fault(struct intel_i
 	if (fault & DMA_FSTS_ITE) {
 		head = readl(iommu->reg + DMAR_IQH_REG);
 		head = ((head >> shift) - 1 + QI_LENGTH) % QI_LENGTH;
-		head |= 1;
 		tail = readl(iommu->reg + DMAR_IQT_REG);
 		tail = ((tail >> shift) - 1 + QI_LENGTH) % QI_LENGTH;
 
@@ -1331,7 +1330,7 @@ static int qi_check_fault(struct intel_i
 		do {
 			if (qi->desc_status[head] == QI_IN_USE)
 				qi->desc_status[head] = QI_ABORT;
-			head = (head - 2 + QI_LENGTH) % QI_LENGTH;
+			head = (head - 1 + QI_LENGTH) % QI_LENGTH;
 		} while (head != tail);
 
 		/*
author maintainer
#54 lore raw

PATCH 54/220 iommu/vt-d: Only handle IOPF for SVA when PRI is supported

In reply to Greg Kroah-Hartman

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

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

From: Lu Baolu <[email protected]>

commit 39c20c4e83b9f78988541d829aa34668904e54a0 upstream.

In intel_svm_set_dev_pasid(), the driver unconditionally manages the IOPF handling during a domain transition. However, commit a86fb7717320 ("iommu/vt-d: Allow SVA with device-specific IOPF") introduced support for SVA on devices that handle page faults internally without utilizing the PCI PRI. On such devices, the IOMMU-side IOPF infrastructure is not required. Calling iopf_for_domain_replace() on these devices is incorrect and can lead to unexpected failures during PASID attachment or unwinding.

Add a check for info->pri_supported to ensure that the IOPF queue logic is only invoked for devices that actually rely on the IOMMU's PRI-based fault handling.

---
 drivers/iommu/intel/svm.c |   12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)
drivers/iommu/intel/svm.c +8 -4
@@ -164,9 +164,12 @@ static int intel_svm_set_dev_pasid(struc
 	if (IS_ERR(dev_pasid))
 		return PTR_ERR(dev_pasid);
 
-	ret = iopf_for_domain_replace(domain, old, dev);
-	if (ret)
-		goto out_remove_dev_pasid;
+	/* SVA with non-IOMMU/PRI IOPF handling is allowed. */
+	if (info->pri_supported) {
+		ret = iopf_for_domain_replace(domain, old, dev);
+		if (ret)
+			goto out_remove_dev_pasid;
+	}
 
 	/* Setup the pasid table: */
 	sflags = cpu_feature_enabled(X86_FEATURE_LA57) ? PASID_FLAG_FL5LP : 0;
@@ -181,7 +184,8 @@ static int intel_svm_set_dev_pasid(struc
 
 	return 0;
 out_unwind_iopf:
-	iopf_for_domain_replace(old, domain, dev);
+	if (info->pri_supported)
+		iopf_for_domain_replace(old, domain, dev);
 out_remove_dev_pasid:
 	domain_remove_dev_pasid(domain, dev, pasid);
 	return ret;
author maintainer
#55 lore raw

PATCH 55/220 io_uring/poll: fix multishot recv missing EOF on wakeup race

In reply to Greg Kroah-Hartman

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

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

From: Jens Axboe <[email protected]>

commit a68ed2df72131447d131531a08fe4dfcf4fa4653 upstream.

When a socket send and shutdown() happen back-to-back, both fire wake-ups before the receiver's task_work has a chance to run. The first wake gets poll ownership (poll_refs=1), and the second bumps it to 2. When io_poll_check_events() runs, it calls io_poll_issue() which does a recv that reads the data and returns IOU_RETRY. The loop then drains all accumulated refs (atomic_sub_return(2) -> 0) and exits, even though only the first event was consumed. Since the shutdown is a persistent state change, no further wakeups will happen, and the multishot recv can hang forever.

Check specifically for HUP in the poll loop, and ensure that another loop is done to check for status if more than a single poll activation is pending. This ensures we don't lose the shutdown event.

---
 io_uring/poll.c |    9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
io_uring/poll.c +7 -2
@@ -272,6 +272,7 @@ static int io_poll_check_events(struct i
 				atomic_andnot(IO_POLL_RETRY_FLAG, &req->poll_refs);
 				v &= ~IO_POLL_RETRY_FLAG;
 			}
+			v &= IO_POLL_REF_MASK;
 		}
 
 		/* the mask was stashed in __io_poll_execute */
@@ -304,8 +305,13 @@ static int io_poll_check_events(struct i
 				return IOU_POLL_REMOVE_POLL_USE_RES;
 			}
 		} else {
-			int ret = io_poll_issue(req, tw);
+			int ret;
 
+			/* multiple refs and HUP, ensure we loop once more */
+			if ((req->cqe.res & (POLLHUP | POLLRDHUP)) && v != 1)
+				v--;
+
+			ret = io_poll_issue(req, tw);
 			if (ret == IOU_COMPLETE)
 				return IOU_POLL_REMOVE_POLL_USE_RES;
 			else if (ret == IOU_REQUEUE)
@@ -321,7 +327,6 @@ static int io_poll_check_events(struct i
 		 * Release all references, retry if someone tried to restart
 		 * task_work while we were executing it.
 		 */
-		v &= IO_POLL_REF_MASK;
 	} while (atomic_sub_return(v, &req->poll_refs) & IO_POLL_REF_MASK);
 
 	io_napi_add(req);
author maintainer
#56 lore raw

PATCH 56/220 io_uring/kbuf: fix missing BUF_MORE for incremental buffers at EOF

In reply to Greg Kroah-Hartman

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

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

From: Jens Axboe <[email protected]>

commit 3ecd3e03144b38a21a3b70254f1b9d2e16629b09 upstream.

For a zero length transfer, io_kbuf_inc_commit() is called with !len. Since we never enter the while loop to consume the buffers, io_kbuf_inc_commit() ends up returning true, consuming the buffer. But if no data was consumed, by definition it cannot have consumed the buffer. Return false for that case.

Fixes ae98dbf43d75 ("io_uring/kbuf: add support for incremental buffer consumption")
---
 io_uring/kbuf.c |    4 ++++
 1 file changed, 4 insertions(+)
io_uring/kbuf.c +4 -0
@@ -34,6 +34,10 @@ struct io_provide_buf {
 
 static bool io_kbuf_inc_commit(struct io_buffer_list *bl, int len)
 {
+	/* No data consumed, return false early to avoid consuming the buffer */
+	if (!len)
+		return false;
+
 	while (len) {
 		struct io_uring_buf *buf;
 		u32 buf_len, this_len;
author maintainer
#57 lore raw

PATCH 57/220 io_uring/kbuf: propagate BUF_MORE through early buffer commit path

In reply to Greg Kroah-Hartman

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

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

From: Jens Axboe <[email protected]>

commit 418eab7a6f3c002d8e64d6e95ec27118017019af upstream.

When io_should_commit() returns true (eg for non-pollable files), buffer commit happens at buffer selection time and sel->buf_list is set to NULL. When __io_put_kbufs() generates CQE flags at completion time, it calls __io_put_kbuf_ring() which finds a NULL buffer_list and hence cannot determine whether the buffer was consumed or not. This means that IORING_CQE_F_BUF_MORE is never set for non-pollable input with incrementally consumed buffers.

Likewise for io_buffers_select(), which always commits upfront and discards the return value of io_kbuf_commit().

Add REQ_F_BUF_MORE to store the result of io_kbuf_commit() during early commit. Then __io_put_kbuf_ring() can check this flag and set IORING_F_BUF_MORE accordingy.

Fixes ae98dbf43d75 ("io_uring/kbuf: add support for incremental buffer consumption")
---
 include/linux/io_uring_types.h |    3 +++
 io_uring/kbuf.c                |   10 +++++++---
 2 files changed, 10 insertions(+), 3 deletions(-)
include/linux/io_uring_types.h +3 -0
@@ -524,6 +524,7 @@ enum {
 	REQ_F_BL_NO_RECYCLE_BIT,
 	REQ_F_BUFFERS_COMMIT_BIT,
 	REQ_F_BUF_NODE_BIT,
+	REQ_F_BUF_MORE_BIT,
 	REQ_F_HAS_METADATA_BIT,
 	REQ_F_IMPORT_BUFFER_BIT,
 	REQ_F_SQE_COPIED_BIT,
@@ -609,6 +610,8 @@ enum {
 	REQ_F_BUFFERS_COMMIT	= IO_REQ_FLAG(REQ_F_BUFFERS_COMMIT_BIT),
 	/* buf node is valid */
 	REQ_F_BUF_NODE		= IO_REQ_FLAG(REQ_F_BUF_NODE_BIT),
+	/* incremental buffer consumption, more space available */
+	REQ_F_BUF_MORE		= IO_REQ_FLAG(REQ_F_BUF_MORE_BIT),
 	/* request has read/write metadata assigned */
 	REQ_F_HAS_METADATA	= IO_REQ_FLAG(REQ_F_HAS_METADATA_BIT),
 	/*
io_uring/kbuf.c +7 -3
@@ -216,7 +216,8 @@ static struct io_br_sel io_ring_buffer_s
 	sel.addr = u64_to_user_ptr(READ_ONCE(buf->addr));
 
 	if (io_should_commit(req, issue_flags)) {
-		io_kbuf_commit(req, sel.buf_list, *len, 1);
+		if (!io_kbuf_commit(req, sel.buf_list, *len, 1))
+			req->flags |= REQ_F_BUF_MORE;
 		sel.buf_list = NULL;
 	}
 	return sel;
@@ -349,7 +350,8 @@ int io_buffers_select(struct io_kiocb *r
 		 */
 		if (ret > 0) {
 			req->flags |= REQ_F_BUFFERS_COMMIT | REQ_F_BL_NO_RECYCLE;
-			io_kbuf_commit(req, sel->buf_list, arg->out_len, ret);
+			if (!io_kbuf_commit(req, sel->buf_list, arg->out_len, ret))
+				req->flags |= REQ_F_BUF_MORE;
 		}
 	} else {
 		ret = io_provided_buffers_select(req, &arg->out_len, sel->buf_list, arg->iovs);
@@ -395,8 +397,10 @@ static inline bool __io_put_kbuf_ring(st
 
 	if (bl)
 		ret = io_kbuf_commit(req, bl, len, nr);
+	if (ret && (req->flags & REQ_F_BUF_MORE))
+		ret = false;
 
-	req->flags &= ~REQ_F_BUFFER_RING;
+	req->flags &= ~(REQ_F_BUFFER_RING | REQ_F_BUF_MORE);
 	return ret;
 }
 
author maintainer
#58 lore raw

PATCH 58/220 vt: save/restore unicode screen buffer for alternate screen

In reply to Greg Kroah-Hartman

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

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

From: Nicolas Pitre <[email protected]>

commit 5eb608319bb56464674a71b4a66ea65c6c435d64 upstream.

The alternate screen support added by commit 23743ba64709 ("vt: add support for smput/rmput escape codes") only saves and restores the regular screen buffer (vc_origin), but completely ignores the corresponding unicode screen buffer (vc_uni_lines) creating a messed-up display.

Add vc_saved_uni_lines to save the unicode screen buffer when entering the alternate screen, and restore it when leaving. Also ensure proper cleanup in reset_terminal() and vc_deallocate().

Fixes 23743ba64709 ("vt: add support for smput/rmput escape codes")
Cc stable <[email protected]>
---
 drivers/tty/vt/vt.c            |    8 ++++++++
 include/linux/console_struct.h |    1 +
 2 files changed, 9 insertions(+)
drivers/tty/vt/vt.c +8 -0
@@ -1345,6 +1345,8 @@ struct vc_data *vc_deallocate(unsigned i
 			kfree(vc->vc_saved_screen);
 			vc->vc_saved_screen = NULL;
 		}
+		vc_uniscr_free(vc->vc_saved_uni_lines);
+		vc->vc_saved_uni_lines = NULL;
 	}
 	return vc;
 }
@@ -1890,6 +1892,8 @@ static void enter_alt_screen(struct vc_d
 	vc->vc_saved_screen = kmemdup((u16 *)vc->vc_origin, size, GFP_KERNEL);
 	if (vc->vc_saved_screen == NULL)
 		return;
+	vc->vc_saved_uni_lines = vc->vc_uni_lines;
+	vc->vc_uni_lines = NULL;
 	vc->vc_saved_rows = vc->vc_rows;
 	vc->vc_saved_cols = vc->vc_cols;
 	save_cur(vc);
@@ -1911,6 +1915,8 @@ static void leave_alt_screen(struct vc_d
 		dest = ((u16 *)vc->vc_origin) + r * vc->vc_cols;
 		memcpy(dest, src, 2 * cols);
 	}
+	vc_uniscr_set(vc, vc->vc_saved_uni_lines);
+	vc->vc_saved_uni_lines = NULL;
 	restore_cur(vc);
 	/* Update the entire screen */
 	if (con_should_update(vc))
@@ -2233,6 +2239,8 @@ static void reset_terminal(struct vc_dat
 	if (vc->vc_saved_screen != NULL) {
 		kfree(vc->vc_saved_screen);
 		vc->vc_saved_screen = NULL;
+		vc_uniscr_free(vc->vc_saved_uni_lines);
+		vc->vc_saved_uni_lines = NULL;
 		vc->vc_saved_rows = 0;
 		vc->vc_saved_cols = 0;
 	}
include/linux/console_struct.h +1 -0
@@ -160,6 +160,7 @@ struct vc_data {
 	struct uni_pagedict **uni_pagedict_loc; /* [!] Location of uni_pagedict variable for this console */
 	u32 **vc_uni_lines;			/* unicode screen content */
 	u16		*vc_saved_screen;
+	u32		**vc_saved_uni_lines;
 	unsigned int	vc_saved_cols;
 	unsigned int	vc_saved_rows;
 	/* additional information is in vt_kern.h */
author maintainer
#59 lore raw

PATCH 59/220 serial: 8250_pci: add support for the AX99100

In reply to Greg Kroah-Hartman

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

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

From: Martin Roukala (né Peres) <[email protected]>

commit 9c0072bc33d349c83d223e64be30794e11938a6b upstream.

This is found in popular brands such as StarTech.com or Delock, and has been a source of frustration to quite a few people, if I can trust Amazon comments complaining about Linux support via the official out-of-the-tree driver.

---
 drivers/tty/serial/8250/8250_pci.c |   17 +++++++++++++++++
 1 file changed, 17 insertions(+)
drivers/tty/serial/8250/8250_pci.c +17 -0
@@ -137,6 +137,8 @@ struct serial_private {
 };
 
 #define PCI_DEVICE_ID_HPE_PCI_SERIAL	0x37e
+#define PCIE_VENDOR_ID_ASIX		0x125B
+#define PCIE_DEVICE_ID_AX99100		0x9100
 
 static const struct pci_device_id pci_use_msi[] = {
 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
@@ -149,6 +151,8 @@ static const struct pci_device_id pci_us
 			 0xA000, 0x1000) },
 	{ PCI_DEVICE_SUB(PCI_VENDOR_ID_HP_3PAR, PCI_DEVICE_ID_HPE_PCI_SERIAL,
 			 PCI_ANY_ID, PCI_ANY_ID) },
+	{ PCI_DEVICE_SUB(PCIE_VENDOR_ID_ASIX, PCIE_DEVICE_ID_AX99100,
+			 0xA000, 0x1000) },
 	{ }
 };
 
@@ -920,6 +924,7 @@ static int pci_netmos_init(struct pci_de
 	case PCI_DEVICE_ID_NETMOS_9912:
 	case PCI_DEVICE_ID_NETMOS_9922:
 	case PCI_DEVICE_ID_NETMOS_9900:
+	case PCIE_DEVICE_ID_AX99100:
 		num_serial = pci_netmos_9900_numports(dev);
 		break;
 
@@ -2555,6 +2560,14 @@ static struct pci_serial_quirk pci_seria
 		.init		= pci_netmos_init,
 		.setup		= pci_netmos_9900_setup,
 	},
+	{
+		.vendor		= PCIE_VENDOR_ID_ASIX,
+		.device		= PCI_ANY_ID,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.init		= pci_netmos_init,
+		.setup		= pci_netmos_9900_setup,
+	},
 	/*
 	 * EndRun Technologies
 	*/
@@ -6076,6 +6089,10 @@ static const struct pci_device_id serial
 		0xA000, 0x3002,
 		0, 0, pbn_NETMOS9900_2s_115200 },
 
+	{	PCIE_VENDOR_ID_ASIX, PCIE_DEVICE_ID_AX99100,
+		0xA000, 0x1000,
+		0, 0, pbn_b0_1_115200 },
+
 	/*
 	 * Best Connectivity and Rosewill PCI Multi I/O cards
 	 */
author maintainer
#60 lore raw

PATCH 60/220 serial: 8250: Fix TX deadlock when using DMA

In reply to Greg Kroah-Hartman

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

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

From: Raul E Rangel <[email protected]>

commit a424a34b8faddf97b5af41689087e7a230f79ba7 upstream.

dmaengine_terminate_async does not guarantee that the __dma_tx_complete callback will run. The callback is currently the only place where dma->tx_running gets cleared. If the transaction is canceled and the callback never runs, then dma->tx_running will never get cleared and we will never schedule new TX DMA transactions again.

This change makes it so we clear dma->tx_running after we terminate the DMA transaction. This is "safe" because serial8250_tx_dma_flush is holding the UART port lock. The first thing the callback does is also grab the UART port lock, so access to dma->tx_running is serialized.

---
 drivers/tty/serial/8250/8250_dma.c |   15 +++++++++++++++
 1 file changed, 15 insertions(+)
drivers/tty/serial/8250/8250_dma.c +15 -0
@@ -162,7 +162,22 @@ void serial8250_tx_dma_flush(struct uart
 	 */
 	dma->tx_size = 0;
 
+	/*
+	 * We can't use `dmaengine_terminate_sync` because `uart_flush_buffer` is
+	 * holding the uart port spinlock.
+	 */
 	dmaengine_terminate_async(dma->txchan);
+
+	/*
+	 * The callback might or might not run. If it doesn't run, we need to ensure
+	 * that `tx_running` is cleared so that we can schedule new transactions.
+	 * If it does run, then the zombie callback will clear `tx_running` again
+	 * and perform a no-op since `tx_size` was cleared above.
+	 *
+	 * In either case, we ASSUME the DMA transaction will terminate before we
+	 * issue a new `serial8250_tx_dma`.
+	 */
+	dma->tx_running = 0;
 }
 
 int serial8250_rx_dma(struct uart_8250_port *p)
author maintainer
#61 lore raw

PATCH 61/220 serial: 8250: always disable IRQ during THRE test

In reply to Greg Kroah-Hartman

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

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

From: Peng Zhang <[email protected]>

commit 24b98e8664e157aff0814a0f49895ee8223f382f upstream.

commit 039d4926379b ("serial: 8250: Toggle IER bits on only after irq has been set up") moved IRQ setup before the THRE test, in combination with commit 205d300aea75 ("serial: 8250: change lock order in serial8250_do_startup()") the interrupt handler can run during the test and race with its IIR reads. This can produce wrong THRE test results and cause spurious registration of the serial8250_backup_timeout timer. Unconditionally disable the IRQ for the short duration of the test and re-enable it afterwards to avoid the race.

Fixes 039d4926379b ("serial: 8250: Toggle IER bits on only after irq has been set up")

Depends-on: 205d300aea75 ("serial: 8250: change lock order in serial8250_do_startup()")

---
 drivers/tty/serial/8250/8250_port.c |    6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/tty/serial/8250/8250_port.c +2 -4
@@ -2147,8 +2147,7 @@ static void serial8250_THRE_test(struct
 	if (up->port.flags & UPF_NO_THRE_TEST)
 		return;
 
-	if (port->irqflags & IRQF_SHARED)
-		disable_irq_nosync(port->irq);
+	disable_irq(port->irq);
 
 	/*
 	 * Test for UARTs that do not reassert THRE when the transmitter is idle and the interrupt
@@ -2170,8 +2169,7 @@ static void serial8250_THRE_test(struct
 		serial_port_out(port, UART_IER, 0);
 	}
 
-	if (port->irqflags & IRQF_SHARED)
-		enable_irq(port->irq);
+	enable_irq(port->irq);
 
 	/*
 	 * If the interrupt is not reasserted, or we otherwise don't trust the iir, setup a timer to
author maintainer
#62 lore raw

PATCH 62/220 serial: 8250: Protect LCR write in shutdown

In reply to Greg Kroah-Hartman

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

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

From: Ilpo Järvinen <[email protected]>

commit 59a33d83bbe6d73d2071d7ae21590b29faed0503 upstream.

The 8250_dw driver needs to potentially perform very complex operations during LCR writes because its BUSY handling prevents updates to LCR while UART is BUSY (which is not fully under our control without those complex operations). Thus, LCR writes should occur under port's lock.

Move LCR write under port's lock in serial8250_do_shutdown(). Also split the LCR RMW so that the logic is on a separate line for clarity.

---
 drivers/tty/serial/8250/8250_port.c |   11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)
drivers/tty/serial/8250/8250_port.c +6 -5
@@ -2348,6 +2348,7 @@ static int serial8250_startup(struct uar
 void serial8250_do_shutdown(struct uart_port *port)
 {
 	struct uart_8250_port *up = up_to_u8250p(port);
+	u32 lcr;
 
 	serial8250_rpm_get(up);
 	/*
@@ -2374,13 +2375,13 @@ void serial8250_do_shutdown(struct uart_
 			port->mctrl &= ~TIOCM_OUT2;
 
 		serial8250_set_mctrl(port, port->mctrl);
+
+		/* Disable break condition */
+		lcr = serial_port_in(port, UART_LCR);
+		lcr &= ~UART_LCR_SBC;
+		serial_port_out(port, UART_LCR, lcr);
 	}
 
-	/*
-	 * Disable break condition and FIFOs
-	 */
-	serial_port_out(port, UART_LCR,
-			serial_port_in(port, UART_LCR) & ~UART_LCR_SBC);
 	serial8250_clear_fifos(up);
 
 	rsa_disable(up);
author maintainer
#63 lore raw

PATCH 63/220 serial: 8250_dw: Avoid unnecessary LCR writes

In reply to Greg Kroah-Hartman

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

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

From: Ilpo Järvinen <[email protected]>

commit 8002d6d6d0d8a36a7d6ca523b17a51cb0fa7c3c3 upstream.

When DW UART is configured with BUSY flag, LCR writes may not always succeed which can make any LCR write complex and very expensive. Performing write directly can trigger IRQ and the driver has to perform complex and distruptive sequence while retrying the write.

Therefore, it's better to avoid doing LCR write that would not change the value of the LCR register. Add LCR write avoidance code into the 8250_dw driver's .serial_out() functions.

---
 drivers/tty/serial/8250/8250_dw.c |   31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)
drivers/tty/serial/8250/8250_dw.c +31 -0
@@ -181,6 +181,22 @@ static void dw8250_check_lcr(struct uart
 	 */
 }
 
+/*
+ * With BUSY, LCR writes can be very expensive (IRQ + complex retry logic).
+ * If the write does not change the value of the LCR register, skip it entirely.
+ */
+static bool dw8250_can_skip_reg_write(struct uart_port *p, unsigned int offset, u32 value)
+{
+	struct dw8250_data *d = to_dw8250_data(p->private_data);
+	u32 lcr;
+
+	if (offset != UART_LCR || d->uart_16550_compatible)
+		return false;
+
+	lcr = serial_port_in(p, offset);
+	return lcr == value;
+}
+
 /* Returns once the transmitter is empty or we run out of retries */
 static void dw8250_tx_wait_empty(struct uart_port *p)
 {
@@ -207,12 +223,18 @@ static void dw8250_tx_wait_empty(struct
 
 static void dw8250_serial_out(struct uart_port *p, unsigned int offset, u32 value)
 {
+	if (dw8250_can_skip_reg_write(p, offset, value))
+		return;
+
 	writeb(value, p->membase + (offset << p->regshift));
 	dw8250_check_lcr(p, offset, value);
 }
 
 static void dw8250_serial_out38x(struct uart_port *p, unsigned int offset, u32 value)
 {
+	if (dw8250_can_skip_reg_write(p, offset, value))
+		return;
+
 	/* Allow the TX to drain before we reconfigure */
 	if (offset == UART_LCR)
 		dw8250_tx_wait_empty(p);
@@ -237,6 +259,9 @@ static u32 dw8250_serial_inq(struct uart
 
 static void dw8250_serial_outq(struct uart_port *p, unsigned int offset, u32 value)
 {
+	if (dw8250_can_skip_reg_write(p, offset, value))
+		return;
+
 	value &= 0xff;
 	__raw_writeq(value, p->membase + (offset << p->regshift));
 	/* Read back to ensure register write ordering. */
@@ -248,6 +273,9 @@ static void dw8250_serial_outq(struct ua
 
 static void dw8250_serial_out32(struct uart_port *p, unsigned int offset, u32 value)
 {
+	if (dw8250_can_skip_reg_write(p, offset, value))
+		return;
+
 	writel(value, p->membase + (offset << p->regshift));
 	dw8250_check_lcr(p, offset, value);
 }
@@ -261,6 +289,9 @@ static u32 dw8250_serial_in32(struct uar
 
 static void dw8250_serial_out32be(struct uart_port *p, unsigned int offset, u32 value)
 {
+	if (dw8250_can_skip_reg_write(p, offset, value))
+		return;
+
 	iowrite32be(value, p->membase + (offset << p->regshift));
 	dw8250_check_lcr(p, offset, value);
 }
author maintainer
#64 lore raw

PATCH 64/220 serial: 8250: Add serial8250_handle_irq_locked()

In reply to Greg Kroah-Hartman

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

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

From: Ilpo Järvinen <[email protected]>

commit 8324a54f604da18f21070702a8ad82ab2062787b upstream.

8250_port exports serial8250_handle_irq() to HW specific 8250 drivers. It takes port's lock within but a HW specific 8250 driver may want to take port's lock itself, do something, and then call the generic handler in 8250_port but to do that, the caller has to release port's lock for no good reason.

Introduce serial8250_handle_irq_locked() which a HW specific driver can call while already holding port's lock.

As this is new export, put it straight into a namespace (where all 8250 exports should eventually be moved).

---
 drivers/tty/serial/8250/8250_port.c |   24 ++++++++++++++++--------
 include/linux/serial_8250.h         |    1 +
 2 files changed, 17 insertions(+), 8 deletions(-)
drivers/tty/serial/8250/8250_port.c +16 -8
@@ -18,6 +18,7 @@
 #include <linux/irq.h>
 #include <linux/console.h>
 #include <linux/gpio/consumer.h>
+#include <linux/lockdep.h>
 #include <linux/sysrq.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
@@ -1782,20 +1783,16 @@ static bool handle_rx_dma(struct uart_82
 }
 
 /*
- * This handles the interrupt from one port.
+ * Context: port's lock must be held by the caller.
  */
-int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
+void serial8250_handle_irq_locked(struct uart_port *port, unsigned int iir)
 {
 	struct uart_8250_port *up = up_to_u8250p(port);
 	struct tty_port *tport = &port->state->port;
 	bool skip_rx = false;
-	unsigned long flags;
 	u16 status;
 
-	if (iir & UART_IIR_NO_INT)
-		return 0;
-
-	uart_port_lock_irqsave(port, &flags);
+	lockdep_assert_held_once(&port->lock);
 
 	status = serial_lsr_in(up);
 
@@ -1828,8 +1825,19 @@ int serial8250_handle_irq(struct uart_po
 		else if (!up->dma->tx_running)
 			__stop_tx(up);
 	}
+}
+EXPORT_SYMBOL_NS_GPL(serial8250_handle_irq_locked, "SERIAL_8250");
+
+/*
+ * This handles the interrupt from one port.
+ */
+int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
+{
+	if (iir & UART_IIR_NO_INT)
+		return 0;
 
-	uart_unlock_and_check_sysrq_irqrestore(port, flags);
+	guard(uart_port_lock_irqsave)(port);
+	serial8250_handle_irq_locked(port, iir);
 
 	return 1;
 }
include/linux/serial_8250.h +1 -0
@@ -195,6 +195,7 @@ void serial8250_do_set_mctrl(struct uart
 void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud,
 			       unsigned int quot);
 int fsl8250_handle_irq(struct uart_port *port);
+void serial8250_handle_irq_locked(struct uart_port *port, unsigned int iir);
 int serial8250_handle_irq(struct uart_port *port, unsigned int iir);
 u16 serial8250_rx_chars(struct uart_8250_port *up, u16 lsr);
 void serial8250_read_char(struct uart_8250_port *up, u16 lsr);
author maintainer
#65 lore raw

PATCH 65/220 serial: 8250_dw: Rework dw8250_handle_irq() locking and IIR handling

In reply to Greg Kroah-Hartman

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

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

From: Ilpo Järvinen <[email protected]>

commit 883c5a2bc934c165c4491d1ef7da0ac4e9765077 upstream.

dw8250_handle_irq() takes port's lock multiple times with no good reason to release it in between and calls serial8250_handle_irq() that also takes port's lock.

Take port's lock only once in dw8250_handle_irq() and use serial8250_handle_irq_locked() to avoid releasing port's lock in between.

As IIR_NO_INT check in serial8250_handle_irq() was outside of port's lock, it has to be done already in dw8250_handle_irq().

DW UART can, in addition to IIR_NO_INT, report BUSY_DETECT (0x7) which collided with the IIR_NO_INT (0x1) check in serial8250_handle_irq() (because & is used instead of ==) meaning that no other work is done by serial8250_handle_irq() during an BUSY_DETECT interrupt.

This allows reorganizing code in dw8250_handle_irq() to do both IIR_NO_INT and BUSY_DETECT handling right at the start simplifying the logic.

---
 drivers/tty/serial/8250/8250_dw.c |   37 +++++++++++++++++++++----------------
 1 file changed, 21 insertions(+), 16 deletions(-)
drivers/tty/serial/8250/8250_dw.c +21 -16
@@ -9,6 +9,9 @@
  * LCR is written whilst busy.  If it is, then a busy detect interrupt is
  * raised, the LCR needs to be rewritten and the uart status register read.
  */
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/cleanup.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/device.h>
@@ -40,6 +43,8 @@
 #define RZN1_UART_RDMACR 0x110 /* DMA Control Register Receive Mode */
 
 /* DesignWare specific register fields */
+#define DW_UART_IIR_IID			GENMASK(3, 0)
+
 #define DW_UART_MCR_SIRE		BIT(6)
 
 /* Renesas specific register fields */
@@ -312,7 +317,19 @@ static int dw8250_handle_irq(struct uart
 	bool rx_timeout = (iir & 0x3f) == UART_IIR_RX_TIMEOUT;
 	unsigned int quirks = d->pdata->quirks;
 	unsigned int status;
-	unsigned long flags;
+
+	switch (FIELD_GET(DW_UART_IIR_IID, iir)) {
+	case UART_IIR_NO_INT:
+		return 0;
+
+	case UART_IIR_BUSY:
+		/* Clear the USR */
+		serial_port_in(p, d->pdata->usr_reg);
+
+		return 1;
+	}
+
+	guard(uart_port_lock_irqsave)(p);
 
 	/*
 	 * There are ways to get Designware-based UARTs into a state where
@@ -325,20 +342,15 @@ static int dw8250_handle_irq(struct uart
 	 * so we limit the workaround only to non-DMA mode.
 	 */
 	if (!up->dma && rx_timeout) {
-		uart_port_lock_irqsave(p, &flags);
 		status = serial_lsr_in(up);
 
 		if (!(status & (UART_LSR_DR | UART_LSR_BI)))
 			serial_port_in(p, UART_RX);
-
-		uart_port_unlock_irqrestore(p, flags);
 	}
 
 	/* Manually stop the Rx DMA transfer when acting as flow controller */
 	if (quirks & DW_UART_QUIRK_IS_DMA_FC && up->dma && up->dma->rx_running && rx_timeout) {
-		uart_port_lock_irqsave(p, &flags);
 		status = serial_lsr_in(up);
-		uart_port_unlock_irqrestore(p, flags);
 
 		if (status & (UART_LSR_DR | UART_LSR_BI)) {
 			dw8250_writel_ext(p, RZN1_UART_RDMACR, 0);
@@ -346,17 +358,9 @@ static int dw8250_handle_irq(struct uart
 		}
 	}
 
-	if (serial8250_handle_irq(p, iir))
-		return 1;
-
-	if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
-		/* Clear the USR */
-		serial_port_in(p, d->pdata->usr_reg);
+	serial8250_handle_irq_locked(p, iir);
 
-		return 1;
-	}
-
-	return 0;
+	return 1;
 }
 
 static void dw8250_clk_work_cb(struct work_struct *work)
@@ -865,6 +869,7 @@ static struct platform_driver dw8250_pla
 
 module_platform_driver(dw8250_platform_driver);
 
+MODULE_IMPORT_NS("SERIAL_8250");
 MODULE_AUTHOR("Jamie Iles");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Synopsys DesignWare 8250 serial port driver");
author maintainer
#66 lore raw

PATCH 66/220 serial: 8250_dw: Rework IIR_NO_INT handling to stop interrupt storm

In reply to Greg Kroah-Hartman

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

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

From: Ilpo Järvinen <[email protected]>

commit 73a4ed8f9efaaaf8207614ccc1c9d5ca1888f23a upstream.

INTC10EE UART can end up into an interrupt storm where it reports IIR_NO_INT (0x1). If the storm happens during active UART operation, it is promptly stopped by IIR value change due to Rx or Tx events. However, when there is no activity, either due to idle serial line or due to specific circumstances such as during shutdown that writes IER=0, there is nothing to stop the storm.

During shutdown the storm is particularly problematic because serial8250_do_shutdown() calls synchronize_irq() that will hang in waiting for the storm to finish which never happens.

This problem can also result in triggering a warning:

irq 45: nobody cared (try booting with the "irqpoll" option) [...snip...]
handlers:
serial8250_interrupt
Disabling IRQ #45

Normal means to reset interrupt status by reading LSR, MSR, USR, or RX register do not result in the UART deasserting the IRQ.

Add a quirk to INTC10EE UARTs to enable Tx interrupts if UART's Tx is currently empty and inactive. Rework IIR_NO_INT to keep track of the number of consecutive IIR_NO_INT, and on fourth one perform the quirk. Enabling Tx interrupts should change IIR value from IIR_NO_INT to IIR_THRI which has been observed to stop the storm.

---
 drivers/tty/serial/8250/8250_dw.c |   67 +++++++++++++++++++++++++++++++++++---
 1 file changed, 63 insertions(+), 4 deletions(-)
drivers/tty/serial/8250/8250_dw.c +63 -4
@@ -61,6 +61,13 @@
 #define DW_UART_QUIRK_IS_DMA_FC		BIT(3)
 #define DW_UART_QUIRK_APMC0D08		BIT(4)
 #define DW_UART_QUIRK_CPR_VALUE		BIT(5)
+#define DW_UART_QUIRK_IER_KICK		BIT(6)
+
+/*
+ * Number of consecutive IIR_NO_INT interrupts required to trigger interrupt
+ * storm prevention code.
+ */
+#define DW_UART_QUIRK_IER_KICK_THRES	4
 
 struct dw8250_platform_data {
 	u8 usr_reg;
@@ -82,6 +89,8 @@ struct dw8250_data {
 
 	unsigned int		skip_autocfg:1;
 	unsigned int		uart_16550_compatible:1;
+
+	u8			no_int_count;
 };
 
 static inline struct dw8250_data *to_dw8250_data(struct dw8250_port_data *data)
@@ -308,6 +317,29 @@ static u32 dw8250_serial_in32be(struct u
        return dw8250_modify_msr(p, offset, value);
 }
 
+/*
+ * INTC10EE UART can IRQ storm while reporting IIR_NO_INT. Inducing IIR value
+ * change has been observed to break the storm.
+ *
+ * If Tx is empty (THRE asserted), we use here IER_THRI to cause IIR_NO_INT ->
+ * IIR_THRI transition.
+ */
+static void dw8250_quirk_ier_kick(struct uart_port *p)
+{
+	struct uart_8250_port *up = up_to_u8250p(p);
+	u32 lsr;
+
+	if (up->ier & UART_IER_THRI)
+		return;
+
+	lsr = serial_lsr_in(up);
+	if (!(lsr & UART_LSR_THRE))
+		return;
+
+	serial_port_out(p, UART_IER, up->ier | UART_IER_THRI);
+	serial_port_in(p, UART_LCR);		/* safe, no side-effects */
+	serial_port_out(p, UART_IER, up->ier);
+}
 
 static int dw8250_handle_irq(struct uart_port *p)
 {
@@ -318,18 +350,30 @@ static int dw8250_handle_irq(struct uart
 	unsigned int quirks = d->pdata->quirks;
 	unsigned int status;
 
+	guard(uart_port_lock_irqsave)(p);
+
 	switch (FIELD_GET(DW_UART_IIR_IID, iir)) {
 	case UART_IIR_NO_INT:
+		if (d->uart_16550_compatible || up->dma)
+			return 0;
+
+		if (quirks & DW_UART_QUIRK_IER_KICK &&
+		    d->no_int_count == (DW_UART_QUIRK_IER_KICK_THRES - 1))
+			dw8250_quirk_ier_kick(p);
+		d->no_int_count = (d->no_int_count + 1) % DW_UART_QUIRK_IER_KICK_THRES;
+
 		return 0;
 
 	case UART_IIR_BUSY:
 		/* Clear the USR */
 		serial_port_in(p, d->pdata->usr_reg);
 
+		d->no_int_count = 0;
+
 		return 1;
 	}
 
-	guard(uart_port_lock_irqsave)(p);
+	d->no_int_count = 0;
 
 	/*
 	 * There are ways to get Designware-based UARTs into a state where
@@ -562,6 +606,14 @@ static void dw8250_reset_control_assert(
 	reset_control_assert(data);
 }
 
+static void dw8250_shutdown(struct uart_port *port)
+{
+	struct dw8250_data *d = to_dw8250_data(port->private_data);
+
+	serial8250_do_shutdown(port);
+	d->no_int_count = 0;
+}
+
 static int dw8250_probe(struct platform_device *pdev)
 {
 	struct uart_8250_port uart = {}, *up = &uart;
@@ -685,10 +737,12 @@ static int dw8250_probe(struct platform_
 		dw8250_quirks(p, data);
 
 	/* If the Busy Functionality is not implemented, don't handle it */
-	if (data->uart_16550_compatible)
+	if (data->uart_16550_compatible) {
 		p->handle_irq = NULL;
-	else if (data->pdata)
+	} else if (data->pdata) {
 		p->handle_irq = dw8250_handle_irq;
+		p->shutdown = dw8250_shutdown;
+	}
 
 	dw8250_setup_dma_filter(p, data);
 
@@ -822,6 +876,11 @@ static const struct dw8250_platform_data
 	.quirks = DW_UART_QUIRK_SKIP_SET_RATE,
 };
 
+static const struct dw8250_platform_data dw8250_intc10ee = {
+	.usr_reg = DW_UART_USR,
+	.quirks = DW_UART_QUIRK_IER_KICK,
+};
+
 static const struct of_device_id dw8250_of_match[] = {
 	{ .compatible = "snps,dw-apb-uart", .data = &dw8250_dw_apb },
 	{ .compatible = "cavium,octeon-3860-uart", .data = &dw8250_octeon_3860_data },
@@ -851,7 +910,7 @@ static const struct acpi_device_id dw825
 	{ "INT33C5", (kernel_ulong_t)&dw8250_dw_apb },
 	{ "INT3434", (kernel_ulong_t)&dw8250_dw_apb },
 	{ "INT3435", (kernel_ulong_t)&dw8250_dw_apb },
-	{ "INTC10EE", (kernel_ulong_t)&dw8250_dw_apb },
+	{ "INTC10EE", (kernel_ulong_t)&dw8250_intc10ee },
 	{ },
 };
 MODULE_DEVICE_TABLE(acpi, dw8250_acpi_match);
author maintainer
#67 lore raw

PATCH 67/220 serial: 8250: Add late synchronize_irq() to shutdown to handle DW UART BUSY

In reply to Greg Kroah-Hartman

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

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

From: Ilpo Järvinen <[email protected]>

commit e0a368ae79531ff92105a2692f10d83052055856 upstream.

When DW UART is !uart_16550_compatible, it can indicate BUSY at any point (when under constant Rx pressure) unless a complex sequence of steps is performed. Any LCR write can run a foul with the condition that prevents writing LCR while the UART is BUSY, which triggers BUSY_DETECT interrupt that seems unmaskable using IER bits.

Normal flow is that dw8250_handle_irq() handles BUSY_DETECT condition by reading USR register. This BUSY feature, however, breaks the assumptions made in serial8250_do_shutdown(), which runs synchronize_irq() after clearing IER and assumes no interrupts can occur after that point but then proceeds to update LCR, which on DW UART can trigger an interrupt.

If serial8250_do_shutdown() releases the interrupt handler before the handler has run and processed the BUSY_DETECT condition by read the USR register, the IRQ is not deasserted resulting in interrupt storm that triggers "irq x: nobody cared" warning leading to disabling the IRQ.

Add late synchronize_irq() into serial8250_do_shutdown() to ensure BUSY_DETECT from DW UART is handled before port's interrupt handler is released. Alternative would be to add DW UART specific shutdown function but it would mostly duplicate the generic code and the extra synchronize_irq() seems pretty harmless in serial8250_do_shutdown().

---
 drivers/tty/serial/8250/8250_port.c |    6 ++++++
 1 file changed, 6 insertions(+)
drivers/tty/serial/8250/8250_port.c +6 -0
@@ -2399,6 +2399,12 @@ void serial8250_do_shutdown(struct uart_
 	 * the IRQ chain.
 	 */
 	serial_port_in(port, UART_RX);
+	/*
+	 * LCR writes on DW UART can trigger late (unmaskable) IRQs.
+	 * Handle them before releasing the handler.
+	 */
+	synchronize_irq(port->irq);
+
 	serial8250_rpm_put(up);
 
 	up->ops->release_irq(up);
author maintainer
#68 lore raw

PATCH 68/220 serial: 8250_dw: Ensure BUSY is deasserted

In reply to Greg Kroah-Hartman

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

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

From: Ilpo Järvinen <[email protected]>

commit a7b9ce39fbe4ae2919fe4f7ac16c293cb6632d30 upstream.

DW UART cannot write to LCR, DLL, and DLH while BUSY is asserted. Existance of BUSY depends on uart_16550_compatible, if UART HW is configured with it those registers can always be written.

There currently is dw8250_force_idle() which attempts to achieve non-BUSY state by disabling FIFO, however, the solution is unreliable when Rx keeps getting more and more characters.

Create a sequence of operations that ensures UART cannot keep BUSY asserted indefinitely. The new sequence relies on enabling loopback mode temporarily to prevent incoming Rx characters keeping UART BUSY.

Ensure no Tx in ongoing while the UART is switches into the loopback mode (requires exporting serial8250_fifo_wait_for_lsr_thre() and adding DMA Tx pause/resume functions).

According to tests performed by Adriana Nicolae <[email protected]>, simply disabling FIFO or clearing FIFOs only once does not always ensure BUSY is deasserted but up to two tries may be needed. This could be related to ongoing Rx of a character (a guess, not known for sure). Therefore, retry FIFO clearing a few times (retry limit 4 is arbitrary number but using, e.g., p->fifosize seems overly large). Tests performed by others did not exhibit similar challenge but it does not seem harmful to leave the FIFO clearing loop in place for all DW UARTs with BUSY functionality.

Use the new dw8250_idle_enter/exit() to do divisor writes and LCR writes. In case of plain LCR writes, opportunistically try to update LCR first and only invoke dw8250_idle_enter() if the write did not succeed (it has been observed that in practice most LCR writes do succeed without complications).

This issue was first reported by qianfan Zhao who put lots of debugging effort into understanding the solution space.

---
 drivers/tty/serial/8250/8250.h      |   25 +++++
 drivers/tty/serial/8250/8250_dw.c   |  163 ++++++++++++++++++++++++++----------
 drivers/tty/serial/8250/8250_port.c |   28 +++---
 3 files changed, 161 insertions(+), 55 deletions(-)
drivers/tty/serial/8250/8250.h +25 -0
@@ -175,7 +175,9 @@ static unsigned int __maybe_unused seria
 	return value;
 }
 
+void serial8250_clear_fifos(struct uart_8250_port *p);
 void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p);
+void serial8250_fifo_wait_for_lsr_thre(struct uart_8250_port *up, unsigned int count);
 
 void serial8250_rpm_get(struct uart_8250_port *p);
 void serial8250_rpm_put(struct uart_8250_port *p);
@@ -400,6 +402,26 @@ static inline bool serial8250_tx_dma_run
 
 	return dma && dma->tx_running;
 }
+
+static inline void serial8250_tx_dma_pause(struct uart_8250_port *p)
+{
+	struct uart_8250_dma *dma = p->dma;
+
+	if (!dma->tx_running)
+		return;
+
+	dmaengine_pause(dma->txchan);
+}
+
+static inline void serial8250_tx_dma_resume(struct uart_8250_port *p)
+{
+	struct uart_8250_dma *dma = p->dma;
+
+	if (!dma->tx_running)
+		return;
+
+	dmaengine_resume(dma->txchan);
+}
 #else
 static inline int serial8250_tx_dma(struct uart_8250_port *p)
 {
@@ -421,6 +443,9 @@ static inline bool serial8250_tx_dma_run
 {
 	return false;
 }
+
+static inline void serial8250_tx_dma_pause(struct uart_8250_port *p) { }
+static inline void serial8250_tx_dma_resume(struct uart_8250_port *p) { }
 #endif
 
 static inline int ns16550a_goto_highspeed(struct uart_8250_port *up)
drivers/tty/serial/8250/8250_dw.c +121 -42

225 lines not on this page · raw message

drivers/tty/serial/8250/8250_port.c +15 -13
@@ -489,7 +489,7 @@ serial_port_out_sync(struct uart_port *p
 /*
  * FIFO support.
  */
-static void serial8250_clear_fifos(struct uart_8250_port *p)
+void serial8250_clear_fifos(struct uart_8250_port *p)
 {
 	if (p->capabilities & UART_CAP_FIFO) {
 		serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO);
@@ -498,6 +498,7 @@ static void serial8250_clear_fifos(struc
 		serial_out(p, UART_FCR, 0);
 	}
 }
+EXPORT_SYMBOL_NS_GPL(serial8250_clear_fifos, "SERIAL_8250");
 
 static enum hrtimer_restart serial8250_em485_handle_start_tx(struct hrtimer *t);
 static enum hrtimer_restart serial8250_em485_handle_stop_tx(struct hrtimer *t);
@@ -3198,6 +3199,17 @@ void serial8250_set_defaults(struct uart
 }
 EXPORT_SYMBOL_GPL(serial8250_set_defaults);
 
+void serial8250_fifo_wait_for_lsr_thre(struct uart_8250_port *up, unsigned int count)
+{
+	unsigned int i;
+
+	for (i = 0; i < count; i++) {
+		if (wait_for_lsr(up, UART_LSR_THRE))
+			return;
+	}
+}
+EXPORT_SYMBOL_NS_GPL(serial8250_fifo_wait_for_lsr_thre, "SERIAL_8250");
+
 #ifdef CONFIG_SERIAL_8250_CONSOLE
 
 static void serial8250_console_putchar(struct uart_port *port, unsigned char ch)
@@ -3239,16 +3251,6 @@ static void serial8250_console_restore(s
 	serial8250_out_MCR(up, up->mcr | UART_MCR_DTR | UART_MCR_RTS);
 }
 
-static void fifo_wait_for_lsr(struct uart_8250_port *up, unsigned int count)
-{
-	unsigned int i;
-
-	for (i = 0; i < count; i++) {
-		if (wait_for_lsr(up, UART_LSR_THRE))
-			return;
-	}
-}
-
 /*
  * Print a string to the serial port using the device FIFO
  *
@@ -3267,7 +3269,7 @@ static void serial8250_console_fifo_writ
 
 	while (s != end) {
 		/* Allow timeout for each byte of a possibly full FIFO */
-		fifo_wait_for_lsr(up, fifosize);
+		serial8250_fifo_wait_for_lsr_thre(up, fifosize);
 
 		for (i = 0; i < fifosize && s != end; ++i) {
 			if (*s == '\n' && !cr_sent) {
@@ -3285,7 +3287,7 @@ static void serial8250_console_fifo_writ
 	 * Allow timeout for each byte written since the caller will only wait
 	 * for UART_LSR_BOTH_EMPTY using the timeout of a single character
 	 */
-	fifo_wait_for_lsr(up, tx_count);
+	serial8250_fifo_wait_for_lsr_thre(up, tx_count);
 }
 
 /*
author maintainer
#69 lore raw

PATCH 69/220 serial: core: fix infinite loop in handle_tx() for PORT_UNKNOWN

In reply to Greg Kroah-Hartman

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

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

From: Jiayuan Chen <[email protected]>

commit 455ce986fa356ff43a43c0d363ba95fa152f21d5 upstream.

uart_write_room() and uart_write() behave inconsistently when xmit_buf is NULL (which happens for PORT_UNKNOWN ports that were never properly initialized):

- uart_write_room() returns kfifo_avail() which can be > 0
- uart_write() checks xmit_buf and returns 0 if NULL

This inconsistency causes an infinite loop in drivers that rely on tty_write_room() to determine if they can write:

  while (tty_write_room(tty) > 0) {
      written = tty->ops->write(...);
      // written is always 0, loop never exits
  }

For example, caif_serial's handle_tx() enters an infinite loop when used with PORT_UNKNOWN serial ports, causing system hangs.

Fix by making uart_write_room() also check xmit_buf and return 0 if it's NULL, consistent with uart_write().

Reproducer: https://gist.github.com/mrpre/d9a694cc0e19828ee3bc3b37983fde13

---
 drivers/tty/serial/serial_core.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/tty/serial/serial_core.c +4 -1
@@ -643,7 +643,10 @@ static unsigned int uart_write_room(stru
 	unsigned int ret;
 
 	port = uart_port_ref_lock(state, &flags);
-	ret = kfifo_avail(&state->port.xmit_fifo);
+	if (!state->port.xmit_buf)
+		ret = 0;
+	else
+		ret = kfifo_avail(&state->port.xmit_fifo);
 	uart_port_unlock_deref(port, flags);
 	return ret;
 }
author maintainer
#70 lore raw

PATCH 70/220 serial: uartlite: fix PM runtime usage count underflow on probe

In reply to Greg Kroah-Hartman

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

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

From: Maciej Andrzejewski ICEYE <[email protected]>

commit d54801cd509515f674a5aac1d3ea1401d2a05863 upstream.

ulite_probe() calls pm_runtime_put_autosuspend() at the end of probe without holding a corresponding PM runtime reference for non-console ports.

During ulite_assign(), uart_add_one_port() triggers uart_configure_port() which calls ulite_pm() via uart_change_pm(). For non-console ports, the UART core performs a balanced get/put cycle:

uart_change_pm(ON) -> ulite_pm() -> pm_runtime_get_sync() +1
uart_change_pm(OFF) -> ulite_pm() -> pm_runtime_put_autosuspend() -1

This leaves no spare reference for the pm_runtime_put_autosuspend() at the end of probe. The PM runtime core prevents the count from actually going below zero, and instead triggers a
"Runtime PM usage count underflow!" warning.

For console ports the bug is masked: the UART core skips the uart_change_pm(OFF) call, so the UART core's unbalanced get happens to pair with probe's trailing put.

Add pm_runtime_get_noresume() before pm_runtime_enable() to take an explicit probe-owned reference that the trailing pm_runtime_put_autosuspend() can release. This ensures a correct usage count regardless of whether the port is a console.

Fixes 5bbe10a6942d ("tty: serial: uartlite: Add runtime pm support")
Cc stable <[email protected]>
---
 drivers/tty/serial/uartlite.c |    1 +
 1 file changed, 1 insertion(+)
drivers/tty/serial/uartlite.c +1 -0
@@ -878,6 +878,7 @@ of_err:
 	pm_runtime_use_autosuspend(&pdev->dev);
 	pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT);
 	pm_runtime_set_active(&pdev->dev);
+	pm_runtime_get_noresume(&pdev->dev);
 	pm_runtime_enable(&pdev->dev);
 
 	ret = ulite_assign(&pdev->dev, id, res->start, irq, pdata);
author maintainer
#71 lore raw

PATCH 71/220 drm: Fix use-after-free on framebuffers and property blobs when calling drm_dev_unplug

In reply to Greg Kroah-Hartman

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

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

From: Maarten Lankhorst <[email protected]>

commit 6bee098b91417654703e17eb5c1822c6dfd0c01d upstream.

When trying to do a rather aggressive test of igt's "xe_module_load --r reload" with a full desktop environment and game running I noticed a few OOPSes when dereferencing freed pointers, related to framebuffers and property blobs after the compositor exits.

Solve this by guarding the freeing in drm_file with drm_dev_enter/exit, and immediately put the references from struct drm_file objects during drm_dev_unplug().

Related warnings for framebuffers on the subtest:

[  739.713076] ------------[ cut here ]------------
               WARN_ON(!list_empty(&dev->mode_config.fb_list))
[  739.713079] WARNING: drivers/gpu/drm/drm_mode_config.c:584 at drm_mode_config_cleanup+0x30b/0x320 [drm], CPU#12: xe_module_load/13145
....
[  739.713328] Call Trace:
[  739.713330]  <TASK>
[  739.713335]  ? intel_pmdemand_destroy_state+0x11/0x20 [xe]
[  739.713574]  ? intel_atomic_global_obj_cleanup+0xe4/0x1a0 [xe]
[  739.713794]  intel_display_driver_remove_noirq+0x51/0xb0 [xe]
[  739.714041]  xe_display_fini_early+0x33/0x50 [xe]
[  739.714284]  devm_action_release+0xf/0x20
[  739.714294]  devres_release_all+0xad/0xf0
[  739.714301]  device_unbind_cleanup+0x12/0xa0
[  739.714305]  device_release_driver_internal+0x1b7/0x210
[  739.714311]  device_driver_detach+0x14/0x20
[  739.714315]  unbind_store+0xa6/0xb0
[  739.714319]  drv_attr_store+0x21/0x30
[  739.714322]  sysfs_kf_write+0x48/0x60
[  739.714328]  kernfs_fop_write_iter+0x16b/0x240
[  739.714333]  vfs_write+0x266/0x520
[  739.714341]  ksys_write+0x72/0xe0
[  739.714345]  __x64_sys_write+0x19/0x20
[  739.714347]  x64_sys_call+0xa15/0xa30
[  739.714355]  do_syscall_64+0xd8/0xab0
[  739.714361]  entry_SYSCALL_64_after_hwframe+0x4b/0x53

and

[  739.714459] ------------[ cut here ]------------
[  739.714461] xe 0000:67:00.0: [drm] drm_WARN_ON(!list_empty(&fb->filp_head))
[  739.714464] WARNING: drivers/gpu/drm/drm_framebuffer.c:833 at drm_framebuffer_free+0x6c/0x90 [drm], CPU#12: xe_module_load/13145
[  739.714715] RIP: 0010:drm_framebuffer_free+0x7a/0x90 [drm]
...
[  739.714869] Call Trace:
[  739.714871]  <TASK>
[  739.714876]  drm_mode_config_cleanup+0x26a/0x320 [drm]
[  739.714998]  ? __drm_printfn_seq_file+0x20/0x20 [drm]
[  739.715115]  ? drm_mode_config_cleanup+0x207/0x320 [drm]
[  739.715235]  intel_display_driver_remove_noirq+0x51/0xb0 [xe]
[  739.715576]  xe_display_fini_early+0x33/0x50 [xe]
[  739.715821]  devm_action_release+0xf/0x20
[  739.715828]  devres_release_all+0xad/0xf0
[  739.715843]  device_unbind_cleanup+0x12/0xa0
[  739.715850]  device_release_driver_internal+0x1b7/0x210
[  739.715856]  device_driver_detach+0x14/0x20
[  739.715860]  unbind_store+0xa6/0xb0
[  739.715865]  drv_attr_store+0x21/0x30
[  739.715868]  sysfs_kf_write+0x48/0x60
[  739.715873]  kernfs_fop_write_iter+0x16b/0x240
[  739.715878]  vfs_write+0x266/0x520
[  739.715886]  ksys_write+0x72/0xe0
[  739.715890]  __x64_sys_write+0x19/0x20
[  739.715893]  x64_sys_call+0xa15/0xa30
[  739.715900]  do_syscall_64+0xd8/0xab0
[  739.715905]  entry_SYSCALL_64_after_hwframe+0x4b/0x53

and then finally file close blows up:

[  743.186530] Oops: general protection fault, probably for non-canonical address 0xdead000000000122: 0000 [#1] SMP
[  743.186535] CPU: 3 UID: 1000 PID: 3453 Comm: kwin_wayland Tainted: G        W           7.0.0-rc1-valkyria+ #110 PREEMPT_{RT,(lazy)}
[  743.186537] Tainted: [W]=WARN
[  743.186538] Hardware name: Gigabyte Technology Co., Ltd. X299 AORUS Gaming 3/X299 AORUS Gaming 3-CF, BIOS F8n 12/06/2021
[  743.186539] RIP: 0010:drm_framebuffer_cleanup+0x55/0xc0 [drm]
[  743.186588] Code: d8 72 73 0f b6 42 05 ff c3 39 c3 72 e8 49 8d bd 50 07 00 00 31 f6 e8 3a 80 d3 e1 49 8b 44 24 10 49 8d 7c 24 08 49 8b 54 24 08 <48> 3b 38 0f 85 95 7f 02 00 48 3b 7a 08 0f 85 8b 7f 02 00 48 89 42
[  743.186589] RSP: 0018:ffffc900085e3cf8 EFLAGS: 00010202
[  743.186591] RAX: dead000000000122 RBX: 0000000000000001 RCX: ffffffff8217ed03
[  743.186592] RDX: dead000000000100 RSI: 0000000000000000 RDI: ffff88814675ba08
[  743.186593] RBP: ffffc900085e3d10 R08: 0000000000000000 R09: 0000000000000000
[  743.186593] R10: 0000000000000000 R11: 0000000000000000 R12: ffff88814675ba00
[  743.186594] R13: ffff88810d778000 R14: ffff888119f6dca0 R15: ffff88810c660bb0
[  743.186595] FS:  00007ff377d21280(0000) GS:ffff888cec3f8000(0000) knlGS:0000000000000000
[  743.186596] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  743.186596] CR2: 000055690b55e000 CR3: 0000000113586003 CR4: 00000000003706f0
[  743.186597] Call Trace:
[  743.186598]  <TASK>
[  743.186603]  intel_user_framebuffer_destroy+0x12/0x90 [xe]
[  743.186722]  drm_framebuffer_free+0x3a/0x90 [drm]
[  743.186750]  ? trace_hardirqs_on+0x5f/0x120
[  743.186754]  drm_mode_object_put+0x51/0x70 [drm]
[  743.186786]  drm_fb_release+0x105/0x190 [drm]
[  743.186812]  ? rt_mutex_slowunlock+0x3aa/0x410
[  743.186817]  ? rt_spin_lock+0xea/0x1b0
[  743.186819]  drm_file_free+0x1e0/0x2c0 [drm]
[  743.186843]  drm_release_noglobal+0x91/0xf0 [drm]
[  743.186865]  __fput+0x100/0x2e0
[  743.186869]  fput_close_sync+0x40/0xa0
[  743.186870]  __x64_sys_close+0x3e/0x80
[  743.186873]  x64_sys_call+0xa07/0xa30
[  743.186879]  do_syscall_64+0xd8/0xab0
[  743.186881]  entry_SYSCALL_64_after_hwframe+0x4b/0x53
[  743.186882] RIP: 0033:0x7ff37e567732
[  743.186884] Code: 08 0f 85 a1 38 ff ff 49 89 fb 48 89 f0 48 89 d7 48 89 ce 4c 89 c2 4d 89 ca 4c 8b 44 24 08 4c 8b 4c 24 10 4c 89 5c 24 08 0f 05 <c3> 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 f3 0f 1e fa 55 bf 01 00
[  743.186885] RSP: 002b:00007ffc818169a8 EFLAGS: 00000246 ORIG_RAX: 0000000000000003
[  743.186886] RAX: ffffffffffffffda RBX: 00007ffc81816a30 RCX: 00007ff37e567732
[  743.186887] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000012
[  743.186888] RBP: 00007ffc818169d0 R08: 0000000000000000 R09: 0000000000000000
[  743.186889] R10: 0000000000000000 R11: 0000000000000246 R12: 000055d60a7996e0
[  743.186889] R13: 00007ffc81816a90 R14: 00007ffc81816a90 R15: 000055d60a782a30
[  743.186892]  </TASK>
[  743.186893] Modules linked in: rfcomm snd_hrtimer xt_CHECKSUM xt_MASQUERADE xt_conntrack ipt_REJECT nf_reject_ipv4 xt_tcpudp xt_addrtype nft_compat x_tables nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 nf_tables overlay cfg80211 bnep mtd_intel_dg snd_hda_codec_intelhdmi mtd snd_hda_codec_hdmi nls_utf8 mxm_wmi intel_wmi_thunderbolt gigabyte_wmi wmi_bmof xe drm_gpuvm drm_gpusvm_helper i2c_algo_bit drm_buddy drm_ttm_helper ttm video drm_suballoc_helper gpu_sched drm_client_lib drm_exec drm_display_helper cec drm_kunit_helpers drm_kms_helper kunit x86_pkg_temp_thermal intel_powerclamp coretemp snd_hda_codec_alc882 snd_hda_codec_realtek_lib snd_hda_codec_generic snd_hda_intel snd_soc_avs snd_soc_hda_codec snd_hda_ext_core snd_hda_codec snd_hwdep snd_hda_core snd_intel_dspcfg snd_soc_core snd_compress ac97_bus snd_pcm snd_seq snd_seq_device snd_timer i2c_i801 i2c_mux snd i2c_smbus btusb btrtl btbcm btmtk btintel bluetooth ecdh_generic rfkill ecc mei_me mei ioatdma dca wmi nfsd drm i2c_dev fuse nfnetlink
[  743.186938] ---[ end trace 0000000000000000 ]---

And for property blobs:

void drm_mode_config_cleanup(struct drm_device *dev) {
...

	list_for_each_entry_safe(blob, bt, &dev->mode_config.property_blob_list,
				 head_global) {
		drm_property_blob_put(blob);
	}

Resulting in:

[  371.072940] BUG: unable to handle page fault for address: 000001ffffffffff
[  371.072944] #PF: supervisor read access in kernel mode
[  371.072945] #PF: error_code(0x0000) - not-present page
[  371.072947] PGD 0 P4D 0
[  371.072950] Oops: Oops: 0000 [#1] SMP
[  371.072953] CPU: 0 UID: 1000 PID: 3693 Comm: kwin_wayland Not tainted 7.0.0-rc1-valkyria+ #111 PREEMPT_{RT,(lazy)}
[  371.072956] Hardware name: Gigabyte Technology Co., Ltd. X299 AORUS Gaming 3/X299 AORUS Gaming 3-CF, BIOS F8n 12/06/2021
[  371.072957] RIP: 0010:drm_property_destroy_user_blobs+0x3b/0x90 [drm]
[  371.073019] Code: 00 00 48 83 ec 10 48 8b 86 30 01 00 00 48 39 c3 74 59 48 89 c2 48 8d 48 c8 48 8b 00 4c 8d 60 c8 eb 04 4c 8d 60 c8 48 8b 71 40 <48> 39 16 0f 85 39 32 01 00 48 3b 50 08 0f 85 2f 32 01 00 48 89 70
[  371.073021] RSP: 0018:ffffc90006a73de8 EFLAGS: 00010293
[  371.073022] RAX: 000001ffffffffff RBX: ffff888118a1a930 RCX: ffff8881b92355c0
[  371.073024] RDX: ffff8881b92355f8 RSI: 000001ffffffffff RDI: ffff888118be4000
[  371.073025] RBP: ffffc90006a73e08 R08: ffff8881009b7300 R09: ffff888cecc5b000
[  371.073026] R10: ffffc90006a73e90 R11: 0000000000000002 R12: 000001ffffffffc7
[  371.073027] R13: ffff888118a1a980 R14: ffff88810b366d20 R15: ffff888118a1a970
[  371.073028] FS:  00007f1faccbb280(0000) GS:ffff888cec2db000(0000) knlGS:0000000000000000
[  371.073029] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  371.073030] CR2: 000001ffffffffff CR3: 000000010655c001 CR4: 00000000003706f0
[  371.073031] Call Trace:
[  371.073033]  <TASK>
[  371.073036]  drm_file_free+0x1df/0x2a0 [drm]
[  371.073077]  drm_release_noglobal+0x7a/0xe0 [drm]
[  371.073113]  __fput+0xe2/0x2b0
[  371.073118]  fput_close_sync+0x40/0xa0
[  371.073119]  __x64_sys_close+0x3e/0x80
[  371.073122]  x64_sys_call+0xa07/0xa30
[  371.073126]  do_syscall_64+0xc0/0x840
[  371.073130]  entry_SYSCALL_64_after_hwframe+0x4b/0x53
[  371.073132] RIP: 0033:0x7f1fb3501732
[  371.073133] Code: 08 0f 85 a1 38 ff ff 49 89 fb 48 89 f0 48 89 d7 48 89 ce 4c 89 c2 4d 89 ca 4c 8b 44 24 08 4c 8b 4c 24 10 4c 89 5c 24 08 0f 05 <c3> 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 f3 0f 1e fa 55 bf 01 00
[  371.073135] RSP: 002b:00007ffe8e6f0278 EFLAGS: 00000246 ORIG_RAX: 0000000000000003
[  371.073136] RAX: ffffffffffffffda RBX: 00007ffe8e6f0300 RCX: 00007f1fb3501732
[  371.073137] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000012
[  371.073138] RBP: 00007ffe8e6f02a0 R08: 0000000000000000 R09: 0000000000000000
[  371.073139] R10: 0000000000000000 R11: 0000000000000246 R12: 00005585ba46eea0
[  371.073140] R13: 00007ffe8e6f0360 R14: 00007ffe8e6f0360 R15: 00005585ba458a30
[  371.073143]  </TASK>
[  371.073144] Modules linked in: rfcomm snd_hrtimer xt_addrtype xt_CHECKSUM xt_MASQUERADE xt_conntrack ipt_REJECT nf_reject_ipv4 xt_tcpudp nft_compat x_tables nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 nf_tables overlay cfg80211 bnep snd_hda_codec_intelhdmi snd_hda_codec_hdmi mtd_intel_dg mtd nls_utf8 wmi_bmof mxm_wmi gigabyte_wmi intel_wmi_thunderbolt xe drm_gpuvm drm_gpusvm_helper i2c_algo_bit drm_buddy drm_ttm_helper ttm video drm_suballoc_helper gpu_sched drm_client_lib drm_exec drm_display_helper cec drm_kunit_helpers drm_kms_helper kunit x86_pkg_temp_thermal intel_powerclamp coretemp snd_hda_codec_alc882 snd_hda_codec_realtek_lib snd_hda_codec_generic snd_hda_intel snd_soc_avs snd_soc_hda_codec snd_hda_ext_core snd_hda_codec snd_hwdep snd_hda_core snd_intel_dspcfg snd_soc_core snd_compress ac97_bus snd_pcm snd_seq snd_seq_device snd_timer i2c_i801 btusb i2c_mux i2c_smbus btrtl snd btbcm btmtk btintel bluetooth ecdh_generic rfkill ecc mei_me mei ioatdma dca wmi nfsd drm i2c_dev fuse nfnetlink
[  371.073198] CR2: 000001ffffffffff
[  371.073199] ---[ end trace 0000000000000000 ]---

Add a guard around file close, and ensure the warnings from drm_mode_config do not trigger. Fix those by allowing an open reference to the file descriptor and cleaning up the file linked list entry in drm_mode_config_cleanup().

Cc <[email protected]> # v4.18+
Fixes bee330f3d672 ("drm: Use srcu to protect drm_device.unplugged")
Cc Thomas Hellström <[email protected]>
---
 drivers/gpu/drm/drm_file.c        |    5 ++++-
 drivers/gpu/drm/drm_mode_config.c |    9 ++++++---
 2 files changed, 10 insertions(+), 4 deletions(-)
drivers/gpu/drm/drm_file.c +4 -1
@@ -233,6 +233,7 @@ static void drm_events_release(struct dr
 void drm_file_free(struct drm_file *file)
 {
 	struct drm_device *dev;
+	int idx;
 
 	if (!file)
 		return;
@@ -249,9 +250,11 @@ void drm_file_free(struct drm_file *file
 
 	drm_events_release(file);
 
-	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+	if (drm_core_check_feature(dev, DRIVER_MODESET) &&
+	    drm_dev_enter(dev, &idx)) {
 		drm_fb_release(file);
 		drm_property_destroy_user_blobs(dev, file);
+		drm_dev_exit(idx);
 	}
 
 	if (drm_core_check_feature(dev, DRIVER_SYNCOBJ))
drivers/gpu/drm/drm_mode_config.c +6 -3
@@ -577,10 +577,13 @@ void drm_mode_config_cleanup(struct drm_
 	 */
 	WARN_ON(!list_empty(&dev->mode_config.fb_list));
 	list_for_each_entry_safe(fb, fbt, &dev->mode_config.fb_list, head) {
-		struct drm_printer p = drm_dbg_printer(dev, DRM_UT_KMS, "[leaked fb]");
+		if (list_empty(&fb->filp_head) || drm_framebuffer_read_refcount(fb) > 1) {
+			struct drm_printer p = drm_dbg_printer(dev, DRM_UT_KMS, "[leaked fb]");
 
-		drm_printf(&p, "framebuffer[%u]:\n", fb->base.id);
-		drm_framebuffer_print_info(&p, 1, fb);
+			drm_printf(&p, "framebuffer[%u]:\n", fb->base.id);
+			drm_framebuffer_print_info(&p, 1, fb);
+		}
+		list_del_init(&fb->filp_head);
 		drm_framebuffer_free(&fb->base.refcount);
 	}
 
author maintainer
#72 lore raw

PATCH 72/220 drm/amd/display: Wrap dcn32_override_min_req_memclk() in DC_FP_{START, END}

In reply to Greg Kroah-Hartman

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

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

From: Xi Ruoyao <[email protected]>

commit ebe82c6e75cfc547154d0fd843b0dd6cca3d548f upstream.

[Why]
The dcn32_override_min_req_memclk function is in dcn32_fpu.c, which is compiled with CC_FLAGS_FPU into FP instructions. So when we call it we must use DC_FP_{START,END} to save and restore the FP context, and prepare the FP unit on architectures like LoongArch where the FP unit isn't always on.

Fixes ee7be8f3de1c ("drm/amd/display: Limit DCN32 8 channel or less parts to DPM1 for FPO")
(cherry picked from commit 25bb1d54ba3983c064361033a8ec15474fece37e)
---
 drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c |    3 +++
 1 file changed, 3 insertions(+)
drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c +3 -0
@@ -1789,7 +1789,10 @@ static bool dml1_validate(struct dc *dc,
 
 	dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel);
 
+	DC_FP_START();
 	dcn32_override_min_req_memclk(dc, context);
+	DC_FP_END();
+
 	dcn32_override_min_req_dcfclk(dc, context);
 
 	BW_VAL_TRACE_END_WATERMARKS();
author maintainer
#73 lore raw

PATCH 73/220 drm/amdgpu/gmc9.0: add bounds checking for cid

In reply to Greg Kroah-Hartman

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

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

From: Alex Deucher <[email protected]>

commit f39e1270277f4b06db0b2c6ec9405b6dd766fb13 upstream.

The value should never exceed the array size as those are the only values the hardware is expected to return, but add checks anyway.

Cc Benjamin Cheng <[email protected]>
(cherry picked from commit e14d468304832bcc4a082d95849bc0a41b18ddea)
---
 drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c |   21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +14 -7
@@ -693,28 +693,35 @@ static int gmc_v9_0_process_interrupt(st
 	} else {
 		switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
 		case IP_VERSION(9, 0, 0):
-			mmhub_cid = mmhub_client_ids_vega10[cid][rw];
+			mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_vega10) ?
+				mmhub_client_ids_vega10[cid][rw] : NULL;
 			break;
 		case IP_VERSION(9, 3, 0):
-			mmhub_cid = mmhub_client_ids_vega12[cid][rw];
+			mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_vega12) ?
+				mmhub_client_ids_vega12[cid][rw] : NULL;
 			break;
 		case IP_VERSION(9, 4, 0):
-			mmhub_cid = mmhub_client_ids_vega20[cid][rw];
+			mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_vega20) ?
+				mmhub_client_ids_vega20[cid][rw] : NULL;
 			break;
 		case IP_VERSION(9, 4, 1):
-			mmhub_cid = mmhub_client_ids_arcturus[cid][rw];
+			mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_arcturus) ?
+				mmhub_client_ids_arcturus[cid][rw] : NULL;
 			break;
 		case IP_VERSION(9, 1, 0):
 		case IP_VERSION(9, 2, 0):
-			mmhub_cid = mmhub_client_ids_raven[cid][rw];
+			mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_raven) ?
+				mmhub_client_ids_raven[cid][rw] : NULL;
 			break;
 		case IP_VERSION(1, 5, 0):
 		case IP_VERSION(2, 4, 0):
-			mmhub_cid = mmhub_client_ids_renoir[cid][rw];
+			mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_renoir) ?
+				mmhub_client_ids_renoir[cid][rw] : NULL;
 			break;
 		case IP_VERSION(1, 8, 0):
 		case IP_VERSION(9, 4, 2):
-			mmhub_cid = mmhub_client_ids_aldebaran[cid][rw];
+			mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_aldebaran) ?
+				mmhub_client_ids_aldebaran[cid][rw] : NULL;
 			break;
 		default:
 			mmhub_cid = NULL;
author maintainer
#74 lore raw

PATCH 74/220 drm/amdgpu/mmhub2.0: add bounds checking for cid

In reply to Greg Kroah-Hartman

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

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

From: Alex Deucher <[email protected]>

commit 0b26edac4ac5535df1f63e6e8ab44c24fe1acad7 upstream.

The value should never exceed the array size as those are the only values the hardware is expected to return, but add checks anyway.

(cherry picked from commit e064cef4b53552602bb6ac90399c18f662f3cacd)
---
 drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c +6 -3
@@ -154,14 +154,17 @@ mmhub_v2_0_print_l2_protection_fault_sta
 	switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
 	case IP_VERSION(2, 0, 0):
 	case IP_VERSION(2, 0, 2):
-		mmhub_cid = mmhub_client_ids_navi1x[cid][rw];
+		mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_navi1x) ?
+			mmhub_client_ids_navi1x[cid][rw] : NULL;
 		break;
 	case IP_VERSION(2, 1, 0):
 	case IP_VERSION(2, 1, 1):
-		mmhub_cid = mmhub_client_ids_sienna_cichlid[cid][rw];
+		mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_sienna_cichlid) ?
+			mmhub_client_ids_sienna_cichlid[cid][rw] : NULL;
 		break;
 	case IP_VERSION(2, 1, 2):
-		mmhub_cid = mmhub_client_ids_beige_goby[cid][rw];
+		mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_beige_goby) ?
+			mmhub_client_ids_beige_goby[cid][rw] : NULL;
 		break;
 	default:
 		mmhub_cid = NULL;
author maintainer
#75 lore raw

PATCH 75/220 drm/amdgpu/mmhub2.3: add bounds checking for cid

In reply to Greg Kroah-Hartman

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

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

From: Alex Deucher <[email protected]>

commit a54403a534972af5d9ba5aaa3bb6ead612500ec6 upstream.

The value should never exceed the array size as those are the only values the hardware is expected to return, but add checks anyway.

(cherry picked from commit 89cd90375c19fb45138990b70e9f4ba4806f05c4)
---
 drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c +2 -1
@@ -94,7 +94,8 @@ mmhub_v2_3_print_l2_protection_fault_sta
 	case IP_VERSION(2, 3, 0):
 	case IP_VERSION(2, 4, 0):
 	case IP_VERSION(2, 4, 1):
-		mmhub_cid = mmhub_client_ids_vangogh[cid][rw];
+		mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_vangogh) ?
+			mmhub_client_ids_vangogh[cid][rw] : NULL;
 		break;
 	default:
 		mmhub_cid = NULL;
author maintainer
#76 lore raw

PATCH 76/220 drm/amdgpu/mmhub3.0.1: add bounds checking for cid

In reply to Greg Kroah-Hartman

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

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

From: Alex Deucher <[email protected]>

commit 5d4e88bcfef29569a1db224ef15e28c603666c6d upstream.

The value should never exceed the array size as those are the only values the hardware is expected to return, but add checks anyway.

(cherry picked from commit 5f76083183363c4528a4aaa593f5d38c28fe7d7b)
---
 drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c +2 -1
@@ -117,7 +117,8 @@ mmhub_v3_0_1_print_l2_protection_fault_s
 
 	switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
 	case IP_VERSION(3, 0, 1):
-		mmhub_cid = mmhub_client_ids_v3_0_1[cid][rw];
+		mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_v3_0_1) ?
+			mmhub_client_ids_v3_0_1[cid][rw] : NULL;
 		break;
 	default:
 		mmhub_cid = NULL;
author maintainer
#77 lore raw

PATCH 77/220 drm/amdgpu/mmhub3.0.2: add bounds checking for cid

In reply to Greg Kroah-Hartman

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

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

From: Alex Deucher <[email protected]>

commit e5e6d67b1ce9764e67aef2d0eef9911af53ad99a upstream.

The value should never exceed the array size as those are the only values the hardware is expected to return, but add checks anyway.

(cherry picked from commit 1441f52c7f6ae6553664aa9e3e4562f6fc2fe8ea)
---
 drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_2.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_2.c +2 -1
@@ -108,7 +108,8 @@ mmhub_v3_0_2_print_l2_protection_fault_s
 		"MMVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n",
 		status);
 
-	mmhub_cid = mmhub_client_ids_v3_0_2[cid][rw];
+	mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_v3_0_2) ?
+		mmhub_client_ids_v3_0_2[cid][rw] : NULL;
 	dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n",
 		mmhub_cid ? mmhub_cid : "unknown", cid);
 	dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n",
author maintainer
#78 lore raw

PATCH 78/220 drm/amdgpu/mmhub3.0: add bounds checking for cid

In reply to Greg Kroah-Hartman

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

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

From: Alex Deucher <[email protected]>

commit cdb82ecbeccb55fae75a3c956b605f7801a30db1 upstream.

The value should never exceed the array size as those are the only values the hardware is expected to return, but add checks anyway.

(cherry picked from commit f14f27bbe2a3ed7af32d5f6eaf3f417139f45253)
---
 drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c +2 -1
@@ -110,7 +110,8 @@ mmhub_v3_0_print_l2_protection_fault_sta
 	switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
 	case IP_VERSION(3, 0, 0):
 	case IP_VERSION(3, 0, 1):
-		mmhub_cid = mmhub_client_ids_v3_0_0[cid][rw];
+		mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_v3_0_0) ?
+			mmhub_client_ids_v3_0_0[cid][rw] : NULL;
 		break;
 	default:
 		mmhub_cid = NULL;
author maintainer
#79 lore raw

PATCH 79/220 drm/amdgpu/mmhub4.1.0: add bounds checking for cid

In reply to Greg Kroah-Hartman

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

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

From: Alex Deucher <[email protected]>

commit 3cdd405831d8cc50a5eae086403402697bb98a4a upstream.

The value should never exceed the array size as those are the only values the hardware is expected to return, but add checks anyway.

(cherry picked from commit 04f063d85090f5dd0c671010ce88ee49d9dcc8ed)
---
 drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c +2 -1
@@ -102,7 +102,8 @@ mmhub_v4_1_0_print_l2_protection_fault_s
 		status);
 	switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
 	case IP_VERSION(4, 1, 0):
-		mmhub_cid = mmhub_client_ids_v4_1_0[cid][rw];
+		mmhub_cid = cid < ARRAY_SIZE(mmhub_client_ids_v4_1_0) ?
+			mmhub_client_ids_v4_1_0[cid][rw] : NULL;
 		break;
 	default:
 		mmhub_cid = NULL;
author maintainer
#80 lore raw

PATCH 80/220 drm/imagination: Fix deadlock in soft reset sequence

In reply to Greg Kroah-Hartman

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

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

From: Alessio Belle <[email protected]>

commit a55c2a5c8d680156495b7b1e2a9f5a3e313ba524 upstream.

The soft reset sequence is currently executed from the threaded IRQ handler, hence it cannot call disable_irq() which internally waits for IRQ handlers, i.e. itself, to complete.

Use disable_irq_nosync() during a soft reset instead.

Fixes cc1aeedb98ad ("drm/imagination: Implement firmware infrastructure and META FW support")
---
 drivers/gpu/drm/imagination/pvr_power.c |   11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
drivers/gpu/drm/imagination/pvr_power.c +10 -1
@@ -510,7 +510,16 @@ pvr_power_reset(struct pvr_device *pvr_d
 	}
 
 	/* Disable IRQs for the duration of the reset. */
-	disable_irq(pvr_dev->irq);
+	if (hard_reset) {
+		disable_irq(pvr_dev->irq);
+	} else {
+		/*
+		 * Soft reset is triggered as a response to a FW command to the Host and is
+		 * processed from the threaded IRQ handler. This code cannot (nor needs to)
+		 * wait for any IRQ processing to complete.
+		 */
+		disable_irq_nosync(pvr_dev->irq);
+	}
 
 	do {
 		if (hard_reset) {
author maintainer
#81 lore raw

PATCH 81/220 drm/imagination: Synchronize interrupts before suspending the GPU

In reply to Greg Kroah-Hartman

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

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

From: Alessio Belle <[email protected]>

commit 2d7f05cddf4c268cc36256a2476946041dbdd36d upstream.

The runtime PM suspend callback doesn't know whether the IRQ handler is in progress on a different CPU core and doesn't wait for it to finish.

Depending on timing, the IRQ handler could be running while the GPU is suspended, leading to kernel crashes when trying to access GPU registers. See example signature below.

In a power off sequence initiated by the runtime PM suspend callback, wait for any IRQ handlers in progress on other CPU cores to finish, by calling synchronize_irq().

At the same time, remove the runtime PM resume/put calls in the threaded IRQ handler. On top of not being the right approach to begin with, and being at the wrong place as they should have wrapped all GPU register accesses, the driver would hit a deadlock between synchronize_irq() being called from a runtime PM suspend callback, holding the device power lock, and the resume callback requiring the same.

Example crash signature on a TI AM68 SK platform:

  [  337.241218] SError Interrupt on CPU0, code 0x00000000bf000000 -- SError
  [  337.241239] CPU: 0 UID: 0 PID: 112 Comm: irq/234-gpu Tainted: G   M                6.17.7-B2C-00005-g9c7bbe4ea16c #2 PREEMPT
  [  337.241246] Tainted: [M]=MACHINE_CHECK
  [  337.241249] Hardware name: Texas Instruments AM68 SK (DT)
  [  337.241252] pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
  [  337.241256] pc : pvr_riscv_irq_pending+0xc/0x24
  [  337.241277] lr : pvr_device_irq_thread_handler+0x64/0x310
  [  337.241282] sp : ffff800085b0bd30
  [  337.241284] x29: ffff800085b0bd50 x28: ffff0008070d9eab x27: ffff800083a5ce10
  [  337.241291] x26: ffff000806e48f80 x25: ffff0008070d9eac x24: 0000000000000000
  [  337.241296] x23: ffff0008068e9bf0 x22: ffff0008068e9bd0 x21: ffff800085b0bd30
  [  337.241301] x20: ffff0008070d9e00 x19: ffff0008068e9000 x18: 0000000000000001
  [  337.241305] x17: 637365645f656c70 x16: 0000000000000000 x15: ffff000b7df9ff40
  [  337.241310] x14: 0000a585fe3c0d0e x13: 000000999704f060 x12: 000000000002771a
  [  337.241314] x11: 00000000000000c0 x10: 0000000000000af0 x9 : ffff800085b0bd00
  [  337.241318] x8 : ffff0008071175d0 x7 : 000000000000b955 x6 : 0000000000000003
  [  337.241323] x5 : 0000000000000000 x4 : 0000000000000002 x3 : 0000000000000000
  [  337.241327] x2 : ffff800080e39d20 x1 : ffff800080e3fc48 x0 : 0000000000000000
  [  337.241333] Kernel panic - not syncing: Asynchronous SError Interrupt
  [  337.241337] CPU: 0 UID: 0 PID: 112 Comm: irq/234-gpu Tainted: G   M                6.17.7-B2C-00005-g9c7bbe4ea16c #2 PREEMPT
  [  337.241342] Tainted: [M]=MACHINE_CHECK
  [  337.241343] Hardware name: Texas Instruments AM68 SK (DT)
  [  337.241345] Call trace:
  [  337.241348]  show_stack+0x18/0x24 (C)
  [  337.241357]  dump_stack_lvl+0x60/0x80
  [  337.241364]  dump_stack+0x18/0x24
  [  337.241368]  vpanic+0x124/0x2ec
  [  337.241373]  abort+0x0/0x4
  [  337.241377]  add_taint+0x0/0xbc
  [  337.241384]  arm64_serror_panic+0x70/0x80
  [  337.241389]  do_serror+0x3c/0x74
  [  337.241392]  el1h_64_error_handler+0x30/0x48
  [  337.241400]  el1h_64_error+0x6c/0x70
  [  337.241404]  pvr_riscv_irq_pending+0xc/0x24 (P)
  [  337.241410]  irq_thread_fn+0x2c/0xb0
  [  337.241416]  irq_thread+0x170/0x334
  [  337.241421]  kthread+0x12c/0x210
  [  337.241428]  ret_from_fork+0x10/0x20
  [  337.241434] SMP: stopping secondary CPUs
  [  337.241451] Kernel Offset: disabled
  [  337.241453] CPU features: 0x040000,02002800,20002001,0400421b
  [  337.241456] Memory Limit: none
  [  337.457921] ---[ end Kernel panic - not syncing: Asynchronous SError Interrupt ]---
Fixes cc1aeedb98ad ("drm/imagination: Implement firmware infrastructure and META FW support")
Fixes 96822d38ff57 ("drm/imagination: Handle Rogue safety event IRQs")
Cc [email protected] # see patch description, needs adjustments for < 6.16
---
 drivers/gpu/drm/imagination/pvr_device.c |   17 -----------------
 drivers/gpu/drm/imagination/pvr_power.c  |   11 ++++++++---
 2 files changed, 8 insertions(+), 20 deletions(-)
drivers/gpu/drm/imagination/pvr_device.c +0 -17
@@ -224,29 +224,12 @@ static irqreturn_t pvr_device_irq_thread
 	}
 
 	if (pvr_dev->has_safety_events) {
-		int err;
-
-		/*
-		 * Ensure the GPU is powered on since some safety events (such
-		 * as ECC faults) can happen outside of job submissions, which
-		 * are otherwise the only time a power reference is held.
-		 */
-		err = pvr_power_get(pvr_dev);
-		if (err) {
-			drm_err_ratelimited(drm_dev,
-					    "%s: could not take power reference (%d)\n",
-					    __func__, err);
-			return ret;
-		}
-
 		while (pvr_device_safety_irq_pending(pvr_dev)) {
 			pvr_device_safety_irq_clear(pvr_dev);
 			pvr_device_handle_safety_events(pvr_dev);
 
 			ret = IRQ_HANDLED;
 		}
-
-		pvr_power_put(pvr_dev);
 	}
 
 	return ret;
drivers/gpu/drm/imagination/pvr_power.c +8 -3
@@ -90,7 +90,7 @@ pvr_power_request_pwr_off(struct pvr_dev
 }
 
 static int
-pvr_power_fw_disable(struct pvr_device *pvr_dev, bool hard_reset)
+pvr_power_fw_disable(struct pvr_device *pvr_dev, bool hard_reset, bool rpm_suspend)
 {
 	if (!hard_reset) {
 		int err;
@@ -106,6 +106,11 @@ pvr_power_fw_disable(struct pvr_device *
 			return err;
 	}
 
+	if (rpm_suspend) {
+		/* Wait for late processing of GPU or firmware IRQs in other cores */
+		synchronize_irq(pvr_dev->irq);
+	}
+
 	return pvr_fw_stop(pvr_dev);
 }
 
@@ -361,7 +366,7 @@ pvr_power_device_suspend(struct device *
 		return -EIO;
 
 	if (pvr_dev->fw_dev.booted) {
-		err = pvr_power_fw_disable(pvr_dev, false);
+		err = pvr_power_fw_disable(pvr_dev, false, true);
 		if (err)
 			goto err_drm_dev_exit;
 	}
@@ -527,7 +532,7 @@ pvr_power_reset(struct pvr_device *pvr_d
 			queues_disabled = true;
 		}
 
-		err = pvr_power_fw_disable(pvr_dev, hard_reset);
+		err = pvr_power_fw_disable(pvr_dev, hard_reset, false);
 		if (!err) {
 			if (hard_reset) {
 				pvr_dev->fw_dev.booted = false;
author maintainer
#82 lore raw

PATCH 82/220 drm/radeon: apply state adjust rules to some additional HAINAN vairants

In reply to Greg Kroah-Hartman

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

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

From: Alex Deucher <[email protected]>

commit 86650ee2241ff84207eaa298ab318533f3c21a38 upstream.

They need a similar workaround.

(cherry picked from commit 87327658c848f56eac166cb382b57b83bf06c5ac)
---
 drivers/gpu/drm/radeon/si_dpm.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/gpu/drm/radeon/si_dpm.c +3 -1
@@ -2915,9 +2915,11 @@ static void si_apply_state_adjust_rules(
 	if (rdev->family == CHIP_HAINAN) {
 		if ((rdev->pdev->revision == 0x81) ||
 		    (rdev->pdev->revision == 0xC3) ||
+		    (rdev->pdev->device == 0x6660) ||
 		    (rdev->pdev->device == 0x6664) ||
 		    (rdev->pdev->device == 0x6665) ||
-		    (rdev->pdev->device == 0x6667)) {
+		    (rdev->pdev->device == 0x6667) ||
+		    (rdev->pdev->device == 0x666F)) {
 			max_sclk = 75000;
 		}
 		if ((rdev->pdev->revision == 0xC3) ||
author maintainer
#83 lore raw

PATCH 83/220 drm/amdgpu: apply state adjust rules to some additional HAINAN vairants

In reply to Greg Kroah-Hartman

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

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

From: Alex Deucher <[email protected]>

commit 9787f7da186ee8143b7b6d914cfa0b6e7fee2648 upstream.

They need a similar workaround.

(cherry picked from commit 0de31d92a173d3d94f28051b0b80a6c98913aed4)
---
 drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c +3 -1
@@ -3454,9 +3454,11 @@ static void si_apply_state_adjust_rules(
 	if (adev->asic_type == CHIP_HAINAN) {
 		if ((adev->pdev->revision == 0x81) ||
 		    (adev->pdev->revision == 0xC3) ||
+		    (adev->pdev->device == 0x6660) ||
 		    (adev->pdev->device == 0x6664) ||
 		    (adev->pdev->device == 0x6665) ||
-		    (adev->pdev->device == 0x6667)) {
+		    (adev->pdev->device == 0x6667) ||
+		    (adev->pdev->device == 0x666F)) {
 			max_sclk = 75000;
 		}
 		if ((adev->pdev->revision == 0xC3) ||
author maintainer
#84 lore raw

PATCH 84/220 drm/amdgpu: Limit BO list entry count to prevent resource exhaustion

In reply to Greg Kroah-Hartman

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

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

From: Jesse.Zhang <[email protected]>

commit 6270b1a5dab94665d7adce3dc78bc9066ed28bdd upstream.

Userspace can pass an arbitrary number of BO list entries via the bo_number field. Although the previous multiplication overflow check prevents out-of-bounds allocation, a large number of entries could still cause excessive memory allocation (up to potentially gigabytes) and unnecessarily long list processing times.

Introduce a hard limit of 128k entries per BO list, which is more than sufficient for any realistic use case (e.g., a single list containing all buffers in a large scene). This prevents memory exhaustion attacks and ensures predictable performance.

Return -EINVAL if the requested entry count exceeds the limit

(cherry picked from commit 688b87d39e0aa8135105b40dc167d74b5ada5332)
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c |    4 ++++
 1 file changed, 4 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c +4 -0
@@ -36,6 +36,7 @@
 
 #define AMDGPU_BO_LIST_MAX_PRIORITY	32u
 #define AMDGPU_BO_LIST_NUM_BUCKETS	(AMDGPU_BO_LIST_MAX_PRIORITY + 1)
+#define AMDGPU_BO_LIST_MAX_ENTRIES	(128 * 1024)
 
 static void amdgpu_bo_list_free_rcu(struct rcu_head *rcu)
 {
@@ -190,6 +191,9 @@ int amdgpu_bo_create_list_entry_array(st
 	const uint32_t bo_number = in->bo_number;
 	struct drm_amdgpu_bo_list_entry *info;
 
+	if (bo_number > AMDGPU_BO_LIST_MAX_ENTRIES)
+		return -EINVAL;
+
 	/* copy the handle array from userspace to a kernel buffer */
 	if (likely(info_size == bo_info_size)) {
 		info = vmemdup_array_user(uptr, bo_number, info_size);
author maintainer
#85 lore raw

PATCH 85/220 drm/amdgpu: rework how we handle TLB fences

In reply to Greg Kroah-Hartman

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

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

From: Alex Deucher <[email protected]>

commit e9f58ff991dd4be13fd7a651bbf64329c090af09 upstream.

Add a new VM flag to indicate whether or not we need a TLB fence. Userqs (KFD or KGD) require a TLB fence. A TLB fence is not strictly required for kernel queues, but it shouldn't hurt. That said, enabling this unconditionally should be fine, but it seems to tickle some issues in KIQ/MES. Only enable them for KFD, or when KGD userq queues are enabled (currently via module parameter).

Fixes f3854e04b708 ("drm/amdgpu: attach tlb fence to the PTs update")
Cc Christian König <[email protected]>
Cc Prike Liang <[email protected]>
(cherry picked from commit 69c5fbd2b93b5ced77c6e79afe83371bca84c788)
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c |    7 ++++++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h |    2 ++
 2 files changed, 8 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +6 -1
@@ -1069,7 +1069,10 @@ amdgpu_vm_tlb_flush(struct amdgpu_vm_upd
 	}
 
 	/* Prepare a TLB flush fence to be attached to PTs */
-	if (!params->unlocked) {
+	/* The check for need_tlb_fence should be dropped once we
+	 * sort out the issues with KIQ/MES TLB invalidation timeouts.
+	 */
+	if (!params->unlocked && vm->need_tlb_fence) {
 		amdgpu_vm_tlb_fence_create(params->adev, vm, fence);
 
 		/* Makes sure no PD/PT is freed before the flush */
@@ -2602,6 +2605,7 @@ int amdgpu_vm_init(struct amdgpu_device
 	ttm_lru_bulk_move_init(&vm->lru_bulk_move);
 
 	vm->is_compute_context = false;
+	vm->need_tlb_fence = amdgpu_userq_enabled(&adev->ddev);
 
 	vm->use_cpu_for_update = !!(adev->vm_manager.vm_update_mode &
 				    AMDGPU_VM_USE_CPU_FOR_GFX);
@@ -2739,6 +2743,7 @@ int amdgpu_vm_make_compute(struct amdgpu
 	dma_fence_put(vm->last_update);
 	vm->last_update = dma_fence_get_stub();
 	vm->is_compute_context = true;
+	vm->need_tlb_fence = true;
 
 unreserve_bo:
 	amdgpu_bo_unreserve(vm->root.bo);
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +2 -0
@@ -440,6 +440,8 @@ struct amdgpu_vm {
 	struct ttm_lru_bulk_move lru_bulk_move;
 	/* Flag to indicate if VM is used for compute */
 	bool			is_compute_context;
+	/* Flag to indicate if VM needs a TLB fence (KFD or KGD) */
+	bool			need_tlb_fence;
 
 	/* Memory partition number, -1 means any partition */
 	int8_t			mem_id;
author maintainer
#86 lore raw

PATCH 86/220 drm/i915/dmc: Fix an unlikely NULL pointer deference at probe

In reply to Greg Kroah-Hartman

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

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

From: Imre Deak <[email protected]>

commit ac57eb3b7d2ad649025b5a0fa207315f755ac4f6 upstream.

intel_dmc_update_dc6_allowed_count() oopses when DMC hasn't been initialized, and dmc is thus NULL.

That would be the case when the call path is intel_power_domains_init_hw() -> {skl,bxt,icl}_display_core_init() -> gen9_set_dc_state() -> intel_dmc_update_dc6_allowed_count(), as intel_power_domains_init_hw() is called *before* intel_dmc_init().

However, gen9_set_dc_state() calls intel_dmc_update_dc6_allowed_count() conditionally, depending on the current and target DC states. At probe, the target is disabled, but if DC6 is enabled, the function is called, and an oops follows. Apparently it's quite unlikely that DC6 is enabled at probe, as we haven't seen this failure mode before.

It is also strange to have DC6 enabled at boot, since that would require the DMC firmware (loaded by BIOS); the BIOS loading the DMC firmware and the driver stopping / reprogramming the firmware is a poorly specified sequence and as such unlikely an intentional BIOS behaviour. It's more likely that BIOS is leaving an unintentionally enabled DC6 HW state behind (without actually loading the required DMC firmware for this).

The tracking of the DC6 allowed counter only works if starting / stopping the counter depends on the _SW_ DC6 state vs. the current _HW_ DC6 state (since stopping the counter requires the DC5 counter captured when the counter was started). Thus, using the HW DC6 state is incorrect and it also leads to the above oops. Fix both issues by using the SW DC6 state for the tracking.

This is v2 of the fix originally sent by Jani, updated based on the first Link: discussion below.

Fixes 88c1f9a4d36d ("drm/i915/dmc: Create debugfs entry for dc6 counter")
Cc Mohammed Thasleem <[email protected]>
Cc Jani Nikula <[email protected]>
Cc Tao Liu <[email protected]>
Cc <[email protected]> # v6.16+
(cherry picked from commit 2344b93af8eb5da5d496b4e0529d35f0f559eaf0)
---
 drivers/gpu/drm/i915/display/intel_display_power_well.c |    2 +-
 drivers/gpu/drm/i915/display/intel_dmc.c                |    3 +--
 2 files changed, 2 insertions(+), 3 deletions(-)
drivers/gpu/drm/i915/display/intel_display_power_well.c +1 -1
@@ -798,7 +798,7 @@ void gen9_set_dc_state(struct intel_disp
 			power_domains->dc_state, val & mask);
 
 	enable_dc6 = state & DC_STATE_EN_UPTO_DC6;
-	dc6_was_enabled = val & DC_STATE_EN_UPTO_DC6;
+	dc6_was_enabled = power_domains->dc_state & DC_STATE_EN_UPTO_DC6;
 	if (!dc6_was_enabled && enable_dc6)
 		intel_dmc_update_dc6_allowed_count(display, true);
 
drivers/gpu/drm/i915/display/intel_dmc.c +1 -2
@@ -1591,8 +1591,7 @@ static bool intel_dmc_get_dc6_allowed_co
 		return false;
 
 	mutex_lock(&power_domains->lock);
-	dc6_enabled = intel_de_read(display, DC_STATE_EN) &
-		      DC_STATE_EN_UPTO_DC6;
+	dc6_enabled = power_domains->dc_state & DC_STATE_EN_UPTO_DC6;
 	if (dc6_enabled)
 		intel_dmc_update_dc6_allowed_count(display, false);
 
author maintainer
#87 lore raw

PATCH 87/220 drm/i915/psr: Compute PSR entry_setup_frames into intel_crtc_state

In reply to Greg Kroah-Hartman

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

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

From: Jouni Högander <[email protected]>

commit 7caac659a837af9fd4cad85be851982b88859484 upstream.

PSR entry_setup_frames is currently computed directly into struct intel_dp:intel_psr:entry_setup_frames. This causes a problem if mode change gets rejected after PSR compute config: Psr_entry_setup_frames computed for this rejected state is in intel_dp:intel_psr:entry_setup_frame. Fix this by computing it into intel_crtc_state and copy the value into intel_dp:intel_psr:entry_setup_frames on PSR enable.

Fixes 2b981d57e480 ("drm/i915/display: Support PSR entry VSC packet to be transmitted one frame earlier")
Cc Mika Kahola <[email protected]>
Cc <[email protected]> # v6.8+
(cherry picked from commit 8c229b4aa00262c13787982e998c61c0783285e0)
---
 drivers/gpu/drm/i915/display/intel_display_types.h |    1 +
 drivers/gpu/drm/i915/display/intel_psr.c           |    5 +++--
 2 files changed, 4 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/display/intel_display_types.h +1 -0
@@ -1160,6 +1160,7 @@ struct intel_crtc_state {
 	u32 dc3co_exitline;
 	u16 su_y_granularity;
 	u8 active_non_psr_pipes;
+	u8 entry_setup_frames;
 	const char *no_psr_reason;
 
 	/*
drivers/gpu/drm/i915/display/intel_psr.c +3 -2
@@ -1711,7 +1711,7 @@ static bool _psr_compute_config(struct i
 	entry_setup_frames = intel_psr_entry_setup_frames(intel_dp, adjusted_mode);
 
 	if (entry_setup_frames >= 0) {
-		intel_dp->psr.entry_setup_frames = entry_setup_frames;
+		crtc_state->entry_setup_frames = entry_setup_frames;
 	} else {
 		crtc_state->no_psr_reason = "PSR setup timing not met";
 		drm_dbg_kms(display->drm,
@@ -1792,7 +1792,7 @@ static bool intel_psr_needs_wa_180378188
 {
 	struct intel_display *display = to_intel_display(intel_dp);
 
-	return (DISPLAY_VER(display) == 20 && intel_dp->psr.entry_setup_frames > 0 &&
+	return (DISPLAY_VER(display) == 20 && crtc_state->entry_setup_frames > 0 &&
 		!crtc_state->has_sel_update);
 }
 
@@ -2167,6 +2167,7 @@ static void intel_psr_enable_locked(stru
 	intel_dp->psr.pkg_c_latency_used = crtc_state->pkg_c_latency_used;
 	intel_dp->psr.io_wake_lines = crtc_state->alpm_state.io_wake_lines;
 	intel_dp->psr.fast_wake_lines = crtc_state->alpm_state.fast_wake_lines;
+	intel_dp->psr.entry_setup_frames = crtc_state->entry_setup_frames;
 
 	if (!psr_interrupt_error_check(intel_dp))
 		return;
author maintainer
#88 lore raw

PATCH 88/220 drm/i915/psr: Disable PSR on update_m_n and update_lrr

In reply to Greg Kroah-Hartman

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

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

From: Jouni Högander <[email protected]>

commit b0a4dba7b623aa7cbc9efcc56b4af2ec8b274f3e upstream.

PSR/PR parameters might change based on update_m_n or update_lrr. Disable on update_m_n and update_lrr to ensure proper parameters are taken into use on next PSR enable in intel_psr_post_plane_update.

Fixes 2bc98c6f97af ("drm/i915/alpm: Compute ALPM parameters into crtc_state->alpm_state")
Cc <[email protected]> # v6.19+
(cherry picked from commit 65852b56bfa929f99e28c96fd98b02058959da7f)
---
 drivers/gpu/drm/i915/display/intel_psr.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/gpu/drm/i915/display/intel_psr.c +2 -0
@@ -3087,6 +3087,8 @@ void intel_psr_pre_plane_update(struct i
 			 * - Display WA #1136: skl, bxt
 			 */
 			if (intel_crtc_needs_modeset(new_crtc_state) ||
+			    new_crtc_state->update_m_n ||
+			    new_crtc_state->update_lrr ||
 			    !new_crtc_state->has_psr ||
 			    !new_crtc_state->active_planes ||
 			    new_crtc_state->has_sel_update != psr->sel_update_enabled ||
author maintainer
#89 lore raw

PATCH 89/220 drm/xe/guc: Ensure CT state transitions via STOP before DISABLED

In reply to Greg Kroah-Hartman

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

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

From: Zhanjun Dong <[email protected]>

commit 7838dd8367419e9fc43b79c038321cb3c04de2a2 upstream.

The GuC CT state transition requires moving to the STOP state before entering the DISABLED state. Update the driver teardown sequence to make the proper state machine transitions.

Fixes ee4b32220a6b ("drm/xe/guc: Add devm release action to safely tear down CT")
(cherry picked from commit dace8cb0032f57ea67c87b3b92ad73c89dd2db44)
---
 drivers/gpu/drm/xe/xe_guc_ct.c |    1 +
 1 file changed, 1 insertion(+)
drivers/gpu/drm/xe/xe_guc_ct.c +1 -0
@@ -265,6 +265,7 @@ static void guc_action_disable_ct(void *
 {
 	struct xe_guc_ct *ct = arg;
 
+	xe_guc_ct_stop(ct);
 	guc_ct_change_state(ct, XE_GUC_CT_STATE_DISABLED);
 }
 
author maintainer
#90 lore raw

PATCH 90/220 drm/xe/oa: Allow reading after disabling OA stream

In reply to Greg Kroah-Hartman

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

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

From: Ashutosh Dixit <[email protected]>

commit 9be6fd9fbd2032b683e51374497768af9aaa228a upstream.

Some OA data might be present in the OA buffer when OA stream is disabled. Allow UMD's to retrieve this data, so that all data till the point when OA stream is disabled can be retrieved.

v2: Update tail pointer after disable (Umesh)

Fixes efb315d0a013 ("drm/xe/oa/uapi: Read file_operation")
(cherry picked from commit 4ff57c5e8dbba23b5457be12f9709d5c016da16e)
---
 drivers/gpu/drm/xe/xe_oa.c |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/gpu/drm/xe/xe_oa.c +5 -2
@@ -543,8 +543,7 @@ static ssize_t xe_oa_read(struct file *f
 	size_t offset = 0;
 	int ret;
 
-	/* Can't read from disabled streams */
-	if (!stream->enabled || !stream->sample)
+	if (!stream->sample)
 		return -EINVAL;
 
 	if (!(file->f_flags & O_NONBLOCK)) {
@@ -1460,6 +1459,10 @@ static void xe_oa_stream_disable(struct
 
 	if (stream->sample)
 		hrtimer_cancel(&stream->poll_check_timer);
+
+	/* Update stream->oa_buffer.tail to allow any final reports to be read */
+	if (xe_oa_buffer_check_unlocked(stream))
+		wake_up(&stream->poll_wq);
 }
 
 static int xe_oa_enable_preempt_timeslice(struct xe_oa_stream *stream)
author maintainer
#91 lore raw

PATCH 91/220 drm/xe: Always kill exec queues in xe_guc_submit_pause_abort

In reply to Greg Kroah-Hartman

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

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

From: Matthew Brost <[email protected]>

commit 26c638d5602e329e0b26281a74c6ec69dee12f23 upstream.

xe_guc_submit_pause_abort is intended to be called after something disastrous occurs (e.g., VF migration fails, device wedging, or driver unload) and should immediately trigger the teardown of remaining submission state. With that, kill any remaining queues in this function.

Fixes 7c4b7e34c83b ("drm/xe/vf: Abort VF post migration recovery on failure")
(cherry picked from commit 78f3bf00be4f15daead02ba32d4737129419c902)
---
 drivers/gpu/drm/xe/xe_guc_submit.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/gpu/drm/xe/xe_guc_submit.c +1 -2
@@ -2410,8 +2410,7 @@ void xe_guc_submit_pause_abort(struct xe
 			continue;
 
 		xe_sched_submission_start(sched);
-		if (exec_queue_killed_or_banned_or_wedged(q))
-			xe_guc_exec_queue_trigger_cleanup(q);
+		guc_exec_queue_kill(q);
 	}
 	mutex_unlock(&guc->submission_state.lock);
 }
author maintainer
#92 lore raw

PATCH 92/220 drm/xe: Fix missing runtime PM reference in ccs_mode_store

In reply to Greg Kroah-Hartman

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

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

From: Sanjay Yadav <[email protected]>

commit 65d046b2d8e0d6d855379a981869005fd6b6a41b upstream.

ccs_mode_store() calls xe_gt_reset() which internally invokes xe_pm_runtime_get_noresume(). That function requires the caller to already hold an outer runtime PM reference and warns if none is held:

  [46.891177] xe 0000:03:00.0: [drm] Missing outer runtime PM protection
  [46.891178] WARNING: drivers/gpu/drm/xe/xe_pm.c:885 at
  xe_pm_runtime_get_noresume+0x8b/0xc0

Fix this by protecting xe_gt_reset() with the scope-based guard(xe_pm_runtime)(xe), which is the preferred form when the reference lifetime matches a single scope.

v2:
- Use scope-based guard(xe_pm_runtime)(xe) (Shuicheng)
- Update commit message accordingly

Fixes 480b358e7d8e ("drm/xe: Do not wake device during a GT reset")
Cc <[email protected]> # v6.19+
Cc Thomas Hellström <[email protected]>
Cc Matthew Brost <[email protected]>
Cc Rodrigo Vivi <[email protected]>
Cc Shuicheng Lin <[email protected]>
(cherry picked from commit 7937ea733f79b3f25e802a0c8360bf7423856f36)
---
 drivers/gpu/drm/xe/xe_gt_ccs_mode.c |    2 ++
 1 file changed, 2 insertions(+)
drivers/gpu/drm/xe/xe_gt_ccs_mode.c +2 -0
@@ -12,6 +12,7 @@
 #include "xe_gt_printk.h"
 #include "xe_gt_sysfs.h"
 #include "xe_mmio.h"
+#include "xe_pm.h"
 #include "xe_sriov.h"
 
 static void __xe_gt_apply_ccs_mode(struct xe_gt *gt, u32 num_engines)
@@ -150,6 +151,7 @@ ccs_mode_store(struct device *kdev, stru
 		xe_gt_info(gt, "Setting compute mode to %d\n", num_engines);
 		gt->ccs_mode = num_engines;
 		xe_gt_record_user_engines(gt);
+		guard(xe_pm_runtime)(xe);
 		xe_gt_reset(gt);
 	}
 
author maintainer
#93 lore raw

PATCH 93/220 drm/xe: Open-code GGTT MMIO access protection

In reply to Greg Kroah-Hartman

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

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

From: Matthew Brost <[email protected]>

commit 01f2557aa684e514005541e71a3d01f4cd45c170 upstream.

GGTT MMIO access is currently protected by hotplug (drm_dev_enter), which works correctly when the driver loads successfully and is later unbound or unloaded. However, if driver load fails, this protection is insufficient because drm_dev_unplug() is never called.

Additionally, devm release functions cannot guarantee that all BOs with GGTT mappings are destroyed before the GGTT MMIO region is removed, as some BOs may be freed asynchronously by worker threads.

To address this, introduce an open-coded flag, protected by the GGTT lock, that guards GGTT MMIO access. The flag is cleared during the dev_fini_ggtt devm release function to ensure MMIO access is disabled once teardown begins.

Fixes 919bb54e989c ("drm/xe: Fix missing runtime outer protection for ggtt_remove_node")
(cherry picked from commit 4f3a998a173b4325c2efd90bdadc6ccd3ad9a431)
---
 drivers/gpu/drm/xe/xe_ggtt.c       |   10 ++++------
 drivers/gpu/drm/xe/xe_ggtt_types.h |    5 ++++-
 2 files changed, 8 insertions(+), 7 deletions(-)
drivers/gpu/drm/xe/xe_ggtt.c +4 -6
@@ -274,6 +274,8 @@ static void dev_fini_ggtt(void *arg)
 {
 	struct xe_ggtt *ggtt = arg;
 
+	scoped_guard(mutex, &ggtt->lock)
+		ggtt->flags &= ~XE_GGTT_FLAGS_ONLINE;
 	drain_workqueue(ggtt->wq);
 }
 
@@ -332,6 +334,7 @@ int xe_ggtt_init_early(struct xe_ggtt *g
 	if (err)
 		return err;
 
+	ggtt->flags |= XE_GGTT_FLAGS_ONLINE;
 	err = devm_add_action_or_reset(xe->drm.dev, dev_fini_ggtt, ggtt);
 	if (err)
 		return err;
@@ -365,13 +368,10 @@ static void xe_ggtt_initial_clear(struct
 static void ggtt_node_remove(struct xe_ggtt_node *node)
 {
 	struct xe_ggtt *ggtt = node->ggtt;
-	struct xe_device *xe = tile_to_xe(ggtt->tile);
 	bool bound;
-	int idx;
-
-	bound = drm_dev_enter(&xe->drm, &idx);
 
 	mutex_lock(&ggtt->lock);
+	bound = ggtt->flags & XE_GGTT_FLAGS_ONLINE;
 	if (bound)
 		xe_ggtt_clear(ggtt, node->base.start, node->base.size);
 	drm_mm_remove_node(&node->base);
@@ -384,8 +384,6 @@ static void ggtt_node_remove(struct xe_g
 	if (node->invalidate_on_remove)
 		xe_ggtt_invalidate(ggtt);
 
-	drm_dev_exit(idx);
-
 free_node:
 	xe_ggtt_node_fini(node);
 }
drivers/gpu/drm/xe/xe_ggtt_types.h +4 -1
@@ -25,11 +25,14 @@ struct xe_ggtt {
 	/** @size: Total size of this GGTT */
 	u64 size;
 
-#define XE_GGTT_FLAGS_64K BIT(0)
+#define XE_GGTT_FLAGS_64K       BIT(0)
+#define XE_GGTT_FLAGS_ONLINE	BIT(1)
 	/**
 	 * @flags: Flags for this GGTT
 	 * Acceptable flags:
 	 * - %XE_GGTT_FLAGS_64K - if PTE size is 64K. Otherwise, regular is 4K.
+	 * - %XE_GGTT_FLAGS_ONLINE - is GGTT online, protected by ggtt->lock
+	 *   after init
 	 */
 	unsigned int flags;
 	/** @scratch: Internal object allocation used as a scratch page */
author maintainer
#94 lore raw

PATCH 94/220 Bluetooth: L2CAP: Fix accepting multiple L2CAP_ECRED_CONN_REQ

In reply to Greg Kroah-Hartman

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

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

From: Luiz Augusto von Dentz <[email protected]>

commit 5b3e2052334f2ff6d5200e952f4aa66994d09899 upstream.

Currently the code attempts to accept requests regardless of the command identifier which may cause multiple requests to be marked as pending (FLAG_DEFER_SETUP) which can cause more than L2CAP_ECRED_MAX_CID(5) to be allocated in l2cap_ecred_rsp_defer causing an overflow.

The spec is quite clear that the same identifier shall not be used on subsequent requests:

'Within each signaling channel a different Identifier shall be used for each successive request or indication.'
https://www.bluetooth.com/wp-content/uploads/Files/Specification/HTML/Core-62/out/en/host/logical-link-control-and-adaptation-protocol-specification.html#UUID-32a25a06-4aa4-c6c7-77c5-dcfe3682355d

So this attempts to check if there are any channels pending with the same identifier and rejects if any are found.

Fixes 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
---
 net/bluetooth/l2cap_core.c |   10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)
net/bluetooth/l2cap_core.c +9 -1
@@ -5045,7 +5045,7 @@ static inline int l2cap_ecred_conn_req(s
 	u16 mtu, mps;
 	__le16 psm;
 	u8 result, rsp_len = 0;
-	int i, num_scid;
+	int i, num_scid = 0;
 	bool defer = false;
 
 	if (!enable_ecred)
@@ -5057,6 +5057,14 @@ static inline int l2cap_ecred_conn_req(s
 		result = L2CAP_CR_LE_INVALID_PARAMS;
 		goto response;
 	}
+
+	/* Check if there are no pending channels with the same ident */
+	__l2cap_chan_list_id(conn, cmd->ident, l2cap_ecred_list_defer,
+			     &num_scid);
+	if (num_scid) {
+		result = L2CAP_CR_LE_INVALID_PARAMS;
+		goto response;
+	}
 
 	cmd_len -= sizeof(*req);
 	num_scid = cmd_len / sizeof(u16);
author maintainer
#95 lore raw

PATCH 95/220 btrfs: log new dentries when logging parent dir of a conflicting inode

In reply to Greg Kroah-Hartman

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

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

From: Filipe Manana <[email protected]>

[ Upstream commit 9573a365ff9ff45da9222d3fe63695ce562beb24 ]

If we log the parent directory of a conflicting inode, we are not logging the new dentries of the directory, so when we finish we have the parent directory's inode marked as logged but we did not log its new dentries. As a consequence if the parent directory is explicitly fsynced later and it does not have any new changes since we logged it, the fsync is a no-op and after a power failure the new dentries are missing.

Example scenario:

  $ mkdir foo
  $ sync

$rmdir foo

  $ mkdir dir1
  $ mkdir dir2

# A file with the same name and parent as the directory we just deleted

  # and was persisted in a past transaction. So the deleted directory's
  # inode is a conflicting inode of this new file's inode.
  $ touch foo
  $ ln foo dir2/link

# The fsync on dir2 will log the parent directory (".") because the

  # conflicting inode (deleted directory) does not exists anymore, but it
  # it does not log its new dentries (dir1).
  $ xfs_io -c "fsync" dir2

# This fsync on the parent directory is no-op, since the previous fsync

  # logged it (but without logging its new dentries).
  $ xfs_io -c "fsync" .

<power failure>

# After log replay dir1 is missing.

Fix this by ensuring we log new dir dentries whenever we log the parent directory of a no longer existing conflicting inode.

A test case for fstests will follow soon.

---
 fs/btrfs/tree-log.c | 6 ++++++
 1 file changed, 6 insertions(+)
fs/btrfs/tree-log.c +6 -0
index 6cffcf0c3e7af..6c40f48cc194d 100644
@@ -6195,6 +6195,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
 				  struct btrfs_root *root,
 				  struct btrfs_log_ctx *ctx)
 {
+	const bool orig_log_new_dentries = ctx->log_new_dentries;
 	int ret = 0;
 
 	/*
@@ -6256,7 +6257,11 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
 			 * dir index key range logged for the directory. So we
 			 * must make sure the deletion is recorded.
 			 */
+			ctx->log_new_dentries = false;
 			ret = btrfs_log_inode(trans, inode, LOG_INODE_ALL, ctx);
+			if (!ret && ctx->log_new_dentries)
+				ret = log_new_dir_dentries(trans, inode, ctx);
+
 			btrfs_add_delayed_iput(inode);
 			if (ret)
 				break;
@@ -6291,6 +6296,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
 			break;
 	}
 
+	ctx->log_new_dentries = orig_log_new_dentries;
 	ctx->logging_conflict_inodes = false;
 	if (ret)
 		free_conflicting_inodes(ctx);
Signature · 1 line
2.51.0
author maintainer
#96 lore raw

PATCH 96/220 btrfs: tree-checker: fix misleading root drop_level error message

In reply to Greg Kroah-Hartman

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

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

From: ZhengYuan Huang <[email protected]>

[ Upstream commit fc1cd1f18c34f91e78362f9629ab9fd43b9dcab9 ]

Fix tree-checker error message to report "invalid root drop_level" instead of the misleading "invalid root level".

Fixes 259ee7754b67 ("btrfs: tree-checker: Add ROOT_ITEM check")
---
 fs/btrfs/tree-checker.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/btrfs/tree-checker.c +1 -1
index 12d6ae49bc078..59794d726fd27 100644
@@ -1256,7 +1256,7 @@ static int check_root_item(struct extent_buffer *leaf, struct btrfs_key *key,
 	}
 	if (unlikely(btrfs_root_drop_level(&ri) >= BTRFS_MAX_LEVEL)) {
 		generic_err(leaf, slot,
-			    "invalid root level, have %u expect [0, %u]",
+			    "invalid root drop_level, have %u expect [0, %u]",
 			    btrfs_root_drop_level(&ri), BTRFS_MAX_LEVEL - 1);
 		return -EUCLEAN;
 	}
Signature · 1 line
2.51.0
author maintainer
#97 lore raw

PATCH 97/220 soc: microchip: mpfs: Fix memory leak in mpfs_sys_controller_probe()

In reply to Greg Kroah-Hartman

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

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

From: Zilin Guan <[email protected]>

[ Upstream commit 5a741f8cc6fe62542f955cd8d24933a1b6589cbd ]

In mpfs_sys_controller_probe(), if of_get_mtd_device_by_node() fails, the function returns immediately without freeing the allocated memory for sys_controller, leading to a memory leak.

Fix this by jumping to the out_free label to ensure the memory is properly freed.

Also, consolidate the error handling for the mbox_request_channel() failure case to use the same label.

Fixes 742aa6c563d2 ("soc: microchip: mpfs: enable access to the system controller's flash")
---
 drivers/soc/microchip/mpfs-sys-controller.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)
drivers/soc/microchip/mpfs-sys-controller.c +9 -4
index 30bc45d17d343..81636cfecd37e 100644
@@ -142,8 +142,10 @@ static int mpfs_sys_controller_probe(struct platform_device *pdev)
 
 	sys_controller->flash = of_get_mtd_device_by_node(np);
 	of_node_put(np);
-	if (IS_ERR(sys_controller->flash))
-		return dev_err_probe(dev, PTR_ERR(sys_controller->flash), "Failed to get flash\n");
+	if (IS_ERR(sys_controller->flash)) {
+		ret = dev_err_probe(dev, PTR_ERR(sys_controller->flash), "Failed to get flash\n");
+		goto out_free;
+	}
 
 no_flash:
 	sys_controller->client.dev = dev;
@@ -155,8 +157,7 @@ static int mpfs_sys_controller_probe(struct platform_device *pdev)
 	if (IS_ERR(sys_controller->chan)) {
 		ret = dev_err_probe(dev, PTR_ERR(sys_controller->chan),
 				    "Failed to get mbox channel\n");
-		kfree(sys_controller);
-		return ret;
+		goto out_free;
 	}
 
 	init_completion(&sys_controller->c);
@@ -174,6 +175,10 @@ static int mpfs_sys_controller_probe(struct platform_device *pdev)
 	dev_info(&pdev->dev, "Registered MPFS system controller\n");
 
 	return 0;
+
+out_free:
+	kfree(sys_controller);
+	return ret;
 }
 
 static void mpfs_sys_controller_remove(struct platform_device *pdev)
Signature · 1 line
2.51.0
author maintainer
#98 lore raw

PATCH 98/220 cache: starfive: fix device node leak in starlink_cache_init()

In reply to Greg Kroah-Hartman

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

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

From: Felix Gu <[email protected]>

[ Upstream commit 3c85234b979af71cb9db5eb976ea08a468415767 ]

of_find_matching_node() returns a device_node with refcount incremented.

Use __free(device_node) attribute to automatically call of_node_put() when the variable goes out of scope, preventing the refcount leak.

Fixes cabff60ca77d ("cache: Add StarFive StarLink cache management")
---
 drivers/cache/starfive_starlink_cache.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/cache/starfive_starlink_cache.c +2 -2
index 24c7d078ca227..3a25d2d7c70ca 100644
@@ -102,11 +102,11 @@ static const struct of_device_id starlink_cache_ids[] = {
 
 static int __init starlink_cache_init(void)
 {
-	struct device_node *np;
 	u32 block_size;
 	int ret;
 
-	np = of_find_matching_node(NULL, starlink_cache_ids);
+	struct device_node *np __free(device_node) =
+		of_find_matching_node(NULL, starlink_cache_ids);
 	if (!of_device_is_available(np))
 		return -ENODEV;
 
Signature · 1 line
2.51.0
author maintainer
#99 lore raw

PATCH 99/220 cache: ax45mp: Fix device node reference leak in ax45mp_cache_init()

In reply to Greg Kroah-Hartman

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

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

From: Felix Gu <[email protected]>

[ Upstream commit 0528a348b04b327a4611e29589beb4c9ae81304a ]

In ax45mp_cache_init(), of_find_matching_node() returns a device node with an incremented reference count that must be released with of_node_put(). The current code fails to call of_node_put() which causes a reference leak.

Use the __free(device_node) attribute to ensure automatic cleanup when the variable goes out of scope.

Fixes d34599bcd2e4 ("cache: Add L2 cache management for Andes AX45MP RISC-V core")
---
 drivers/cache/ax45mp_cache.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/cache/ax45mp_cache.c +2 -2
index 1d7dd3d2c101c..934c5087ec2bd 100644
@@ -178,11 +178,11 @@ static const struct of_device_id ax45mp_cache_ids[] = {
 
 static int __init ax45mp_cache_init(void)
 {
-	struct device_node *np;
 	struct resource res;
 	int ret;
 
-	np = of_find_matching_node(NULL, ax45mp_cache_ids);
+	struct device_node *np __free(device_node) =
+		of_find_matching_node(NULL, ax45mp_cache_ids);
 	if (!of_device_is_available(np))
 		return -ENODEV;
 
Signature · 1 line
2.51.0
author maintainer
#100 lore raw

PATCH 100/220 soc: rockchip: grf: Add missing of_node_put() when returning

In reply to Greg Kroah-Hartman

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

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

From: Shawn Lin <[email protected]>

[ Upstream commit 24ed11ee5bacf9a9aca18fc6b47667c7f38d578b ]

Fix the smatch checking:
drivers/soc/rockchip/grf.c:249 rockchip_grf_init()
warn: inconsistent refcounting 'np->kobj.kref.refcount.refs.counter':

---
 drivers/soc/rockchip/grf.c | 1 +
 1 file changed, 1 insertion(+)
drivers/soc/rockchip/grf.c +1 -0
index 04937c40da471..b459607c118aa 100644
@@ -231,6 +231,7 @@ static int __init rockchip_grf_init(void)
 		grf = syscon_node_to_regmap(np);
 		if (IS_ERR(grf)) {
 			pr_err("%s: could not get grf syscon\n", __func__);
+			of_node_put(np);
 			return PTR_ERR(grf);
 		}
 
Signature · 1 line
2.51.0
author maintainer
#101 lore raw

PATCH 101/220 soc: fsl: qbman: fix race condition in qman_destroy_fq

In reply to Greg Kroah-Hartman

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

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

From: Richard Genoud <[email protected]>

[ Upstream commit 014077044e874e270ec480515edbc1cadb976cf2 ]

When QMAN_FQ_FLAG_DYNAMIC_FQID is set, there's a race condition between fq_table[fq->idx] state and freeing/allocating from the pool and WARN_ON(fq_table[fq->idx]) in qman_create_fq() gets triggered.

Indeed, we can have:

         Thread A                             Thread B
    qman_destroy_fq()                    qman_create_fq()
      qman_release_fqid()
        qman_shutdown_fq()
        gen_pool_free()
           -- At this point, the fqid is available again --
                                           qman_alloc_fqid()
           -- so, we can get the just-freed fqid in thread B --
                                           fq->fqid = fqid;
                                           fq->idx = fqid * 2;
                                           WARN_ON(fq_table[fq->idx]);
                                           fq_table[fq->idx] = fq;
     fq_table[fq->idx] = NULL;

And adding some logs between qman_release_fqid() and fq_table[fq->idx] = NULL makes the WARN_ON() trigger a lot more.

To prevent that, ensure that fq_table[fq->idx] is set to NULL before gen_pool_free() is called by using smp_wmb().

---
 drivers/soc/fsl/qbman/qman.c | 24 ++++++++++++++++++++++--
 1 file changed, 22 insertions(+), 2 deletions(-)
drivers/soc/fsl/qbman/qman.c +22 -2
index 6b392b3ad4b15..39a3e7aab6ff2 100644
@@ -1827,6 +1827,8 @@ EXPORT_SYMBOL(qman_create_fq);
 
 void qman_destroy_fq(struct qman_fq *fq)
 {
+	int leaked;
+
 	/*
 	 * We don't need to lock the FQ as it is a pre-condition that the FQ be
 	 * quiesced. Instead, run some checks.
@@ -1834,11 +1836,29 @@ void qman_destroy_fq(struct qman_fq *fq)
 	switch (fq->state) {
 	case qman_fq_state_parked:
 	case qman_fq_state_oos:
-		if (fq_isset(fq, QMAN_FQ_FLAG_DYNAMIC_FQID))
-			qman_release_fqid(fq->fqid);
+		/*
+		 * There's a race condition here on releasing the fqid,
+		 * setting the fq_table to NULL, and freeing the fqid.
+		 * To prevent it, this order should be respected:
+		 */
+		if (fq_isset(fq, QMAN_FQ_FLAG_DYNAMIC_FQID)) {
+			leaked = qman_shutdown_fq(fq->fqid);
+			if (leaked)
+				pr_debug("FQID %d leaked\n", fq->fqid);
+		}
 
 		DPAA_ASSERT(fq_table[fq->idx]);
 		fq_table[fq->idx] = NULL;
+
+		if (fq_isset(fq, QMAN_FQ_FLAG_DYNAMIC_FQID) && !leaked) {
+			/*
+			 * fq_table[fq->idx] should be set to null before
+			 * freeing fq->fqid otherwise it could by allocated by
+			 * qman_alloc_fqid() while still being !NULL
+			 */
+			smp_wmb();
+			gen_pool_free(qm_fqalloc, fq->fqid | DPAA_GENALLOC_OFF, 1);
+		}
 		return;
 	default:
 		break;
Signature · 1 line
2.51.0
author maintainer
#102 lore raw

PATCH 102/220 soc: fsl: cpm1: qmc: Fix error check for devm_ioremap_resource() in qmc_qe_init_resources()

In reply to Greg Kroah-Hartman

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

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

From: Chen Ni <[email protected]>

[ Upstream commit 3f4e403304186d79fddace860360540fc3af97f9 ]

Fix wrong variable used for error checking after devm_ioremap_resource() call. The function checks qmc->scc_pram instead of qmc->dpram, which could lead to incorrect error handling.

Fixes eb680d563089 ("soc: fsl: cpm1: qmc: Add support for QUICC Engine (QE) implementation")
---
 drivers/soc/fsl/qe/qmc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/soc/fsl/qe/qmc.c +2 -2
index da5ea6d356184..6db5ab05c2c1c 100644
@@ -1799,8 +1799,8 @@ static int qmc_qe_init_resources(struct qmc *qmc, struct platform_device *pdev)
 		return -EINVAL;
 	qmc->dpram_offset = res->start - qe_muram_dma(qe_muram_addr(0));
 	qmc->dpram = devm_ioremap_resource(qmc->dev, res);
-	if (IS_ERR(qmc->scc_pram))
-		return PTR_ERR(qmc->scc_pram);
+	if (IS_ERR(qmc->dpram))
+		return PTR_ERR(qmc->dpram);
 
 	return 0;
 }
Signature · 1 line
2.51.0
author maintainer
#103 lore raw

PATCH 103/220 tee: shm: Remove refcounting of kernel pages

In reply to Greg Kroah-Hartman

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

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

From: Matthew Wilcox <[email protected]>

[ Upstream commit 08d9a4580f71120be3c5b221af32dca00a48ceb0 ]

Earlier TEE subsystem assumed to refcount all the memory pages to be shared with TEE implementation to be refcounted. However, the slab allocations within the kernel don't allow refcounting kernel pages.

It is rather better to trust the kernel clients to not free pages while being shared with TEE implementation. Hence, remove refcounting of kernel pages from register_shm_helper() API.

Fixes b9c0e49abfca ("mm: decline to manipulate the refcount on a slab page")
---
 drivers/tee/tee_shm.c | 27 ---------------------------
 1 file changed, 27 deletions(-)
drivers/tee/tee_shm.c +0 -27
index 4a47de4bb2e5c..898707ca21a8e 100644
@@ -23,29 +23,11 @@ struct tee_shm_dma_mem {
 	struct page *page;
 };
 
-static void shm_put_kernel_pages(struct page **pages, size_t page_count)
-{
-	size_t n;
-
-	for (n = 0; n < page_count; n++)
-		put_page(pages[n]);
-}
-
-static void shm_get_kernel_pages(struct page **pages, size_t page_count)
-{
-	size_t n;
-
-	for (n = 0; n < page_count; n++)
-		get_page(pages[n]);
-}
-
 static void release_registered_pages(struct tee_shm *shm)
 {
 	if (shm->pages) {
 		if (shm->flags & TEE_SHM_USER_MAPPED)
 			unpin_user_pages(shm->pages, shm->num_pages);
-		else
-			shm_put_kernel_pages(shm->pages, shm->num_pages);
 
 		kfree(shm->pages);
 	}
@@ -477,13 +459,6 @@ register_shm_helper(struct tee_context *ctx, struct iov_iter *iter, u32 flags,
 		goto err_put_shm_pages;
 	}
 
-	/*
-	 * iov_iter_extract_kvec_pages does not get reference on the pages,
-	 * get a reference on them.
-	 */
-	if (iov_iter_is_kvec(iter))
-		shm_get_kernel_pages(shm->pages, num_pages);
-
 	shm->offset = off;
 	shm->size = len;
 	shm->num_pages = num_pages;
@@ -499,8 +474,6 @@ register_shm_helper(struct tee_context *ctx, struct iov_iter *iter, u32 flags,
 err_put_shm_pages:
 	if (!iov_iter_is_kvec(iter))
 		unpin_user_pages(shm->pages, shm->num_pages);
-	else
-		shm_put_kernel_pages(shm->pages, shm->num_pages);
 err_free_shm_pages:
 	kfree(shm->pages);
 err_free_shm:
Signature · 1 line
2.51.0
author maintainer
#104 lore raw

PATCH 104/220 wifi: mac80211: remove keys after disabling beaconing

In reply to Greg Kroah-Hartman

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

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

From: Johannes Berg <[email protected]>

[ Upstream commit 708bbb45537780a8d3721ca1e0cf1932c1d1bf5f ]

We shouldn't remove keys before disable beaconing, at least when beacon protection is used, since that would remove keys that are still used for beacon transmission at the same time. Stop before removing keys so there's no race.

---
 net/mac80211/cfg.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
net/mac80211/cfg.c +6 -6
index c81091a5cc3a3..e480b48e8365d 100644
@@ -1889,12 +1889,6 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
 
 	__sta_info_flush(sdata, true, link_id, NULL);
 
-	ieee80211_remove_link_keys(link, &keys);
-	if (!list_empty(&keys)) {
-		synchronize_net();
-		ieee80211_free_key_list(local, &keys);
-	}
-
 	ieee80211_stop_mbssid(sdata);
 	RCU_INIT_POINTER(link_conf->tx_bss_conf, NULL);
 
@@ -1906,6 +1900,12 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
 	ieee80211_link_info_change_notify(sdata, link,
 					  BSS_CHANGED_BEACON_ENABLED);
 
+	ieee80211_remove_link_keys(link, &keys);
+	if (!list_empty(&keys)) {
+		synchronize_net();
+		ieee80211_free_key_list(local, &keys);
+	}
+
 	if (sdata->wdev.links[link_id].cac_started) {
 		chandef = link_conf->chanreq.oper;
 		wiphy_delayed_work_cancel(wiphy, &link->dfs_cac_timer_work);
Signature · 1 line
2.51.0
author maintainer
#105 lore raw

PATCH 105/220 wifi: mac80211: use jiffies_delta_to_msecs() for sta_info inactive times

In reply to Greg Kroah-Hartman

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

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

From: Nicolas Cavallari <[email protected]>

[ Upstream commit ac6f24cc9c0a9aefa55ec9696dcafa971d4d760b ]

Inactive times of around 0xffffffff milliseconds have been observed on an ath9k device on ARM. This is likely due to a memory ordering race in the jiffies_to_msecs(jiffies - last_active()) calculation causing an overflow when the observed jiffies is below ieee80211_sta_last_active().

Use jiffies_delta_to_msecs() instead to avoid this problem.

Fixes 7bbdd2d98797 ("mac80211: implement station stats retrieval")
---
 net/mac80211/sta_info.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)
net/mac80211/sta_info.c +5 -2
index 1a995bc301b19..b0d9bb830f293 100644
@@ -2759,7 +2759,9 @@ static void sta_set_link_sinfo(struct sta_info *sta,
 	}
 
 	link_sinfo->inactive_time =
-		jiffies_to_msecs(jiffies - ieee80211_sta_last_active(sta, link_id));
+		jiffies_delta_to_msecs(jiffies -
+				       ieee80211_sta_last_active(sta,
+								 link_id));
 
 	if (!(link_sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES64) |
 				    BIT_ULL(NL80211_STA_INFO_TX_BYTES)))) {
@@ -2992,7 +2994,8 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
 	sinfo->connected_time = ktime_get_seconds() - sta->last_connected;
 	sinfo->assoc_at = sta->assoc_at;
 	sinfo->inactive_time =
-		jiffies_to_msecs(jiffies - ieee80211_sta_last_active(sta, -1));
+		jiffies_delta_to_msecs(jiffies -
+				       ieee80211_sta_last_active(sta, -1));
 
 	if (!(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES64) |
 			       BIT_ULL(NL80211_STA_INFO_TX_BYTES)))) {
Signature · 1 line
2.51.0
author maintainer
#106 lore raw

PATCH 106/220 wifi: mac80211: Fix static_branch_dec() underflow for aql_disable.

In reply to Greg Kroah-Hartman

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

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

From: Kuniyuki Iwashima <[email protected]>

[ Upstream commit b94ae8e0d5fe1bdbbfdc3854ff6ce98f6876a828 ]

syzbot reported static_branch_dec() underflow in aql_enable_write(). [0]

The problem is that aql_enable_write() does not serialise concurrent write()s to the debugfs.

aql_enable_write() checks static_key_false(&aql_disable.key) and later calls static_branch_inc() or static_branch_dec(), but the state may change between the two calls.

aql_disable does not need to track inc/dec.

Let's use static_branch_enable() and static_branch_disable().

[0]:
val == 0

WARNING: kernel/jump_label.c:311 at __static_key_slow_dec_cpuslocked.part.0+0x107/0x120 kernel/jump_label.c:311, CPU#0: syz.1.3155/20288
Modules linked in:
CPU: 0 UID: 0 PID: 20288 Comm: syz.1.3155 Tainted: G     U       L      syzkaller #0 PREEMPT(full)
Tainted: [U]=USER, [L]=SOFTLOCKUP
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/24/2026
RIP: 0010:__static_key_slow_dec_cpuslocked.part.0+0x107/0x120 kernel/jump_label.c:311
Code: f2 c9 ff 5b 5d c3 cc cc cc cc e8 54 f2 c9 ff 48 89 df e8 ac f9 ff ff eb ad e8 45 f2 c9 ff 90 0f 0b 90 eb a2 e8 3a f2 c9 ff 90 <0f> 0b 90 eb 97 48 89 df e8 5c 4b 33 00 e9 36 ff ff ff 0f 1f 80 00
RSP: 0018:ffffc9000b9f7c10 EFLAGS: 00010293
RAX: 0000000000000000 RBX: ffffffff9b3e5d40 RCX: ffffffff823c57b4
RDX: ffff8880285a0000 RSI: ffffffff823c5846 RDI: ffff8880285a0000
RBP: 0000000000000000 R08: 0000000000000005 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000000 R12: 000000000000000a
R13: 1ffff9200173ef88 R14: 0000000000000001 R15: ffffc9000b9f7e98
FS:  00007f530dd726c0(0000) GS:ffff8881245e3000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000200000001140 CR3: 000000007cc4a000 CR4: 00000000003526f0
Call Trace:
 <TASK>
 __static_key_slow_dec_cpuslocked kernel/jump_label.c:297 [inline]
 __static_key_slow_dec kernel/jump_label.c:321 [inline]
 static_key_slow_dec+0x7c/0xc0 kernel/jump_label.c:336
 aql_enable_write+0x2b2/0x310 net/mac80211/debugfs.c:343
 short_proxy_write+0x133/0x1a0 fs/debugfs/file.c:383
 vfs_write+0x2aa/0x1070 fs/read_write.c:684
 ksys_pwrite64 fs/read_write.c:793 [inline]
 __do_sys_pwrite64 fs/read_write.c:801 [inline]
 __se_sys_pwrite64 fs/read_write.c:798 [inline]
 __x64_sys_pwrite64+0x1eb/0x250 fs/read_write.c:798
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xc9/0xf80 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f530cf9aeb9
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:00007f530dd72028 EFLAGS: 00000246 ORIG_RAX: 0000000000000012
RAX: ffffffffffffffda RBX: 00007f530d215fa0 RCX: 00007f530cf9aeb9
RDX: 0000000000000003 RSI: 0000000000000000 RDI: 0000000000000010
RBP: 00007f530d008c1f R08: 0000000000000000 R09: 0000000000000000
R10: 4200000000000005 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f530d216038 R14: 00007f530d215fa0 R15: 00007ffde89fb978
 </TASK>
---
 net/mac80211/debugfs.c | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)
net/mac80211/debugfs.c +5 -9
index d02f07368c511..687a66cd49433 100644
@@ -320,7 +320,6 @@ static ssize_t aql_enable_read(struct file *file, char __user *user_buf,
 static ssize_t aql_enable_write(struct file *file, const char __user *user_buf,
 				size_t count, loff_t *ppos)
 {
-	bool aql_disabled = static_key_false(&aql_disable.key);
 	char buf[3];
 	size_t len;
 
@@ -335,15 +334,12 @@ static ssize_t aql_enable_write(struct file *file, const char __user *user_buf,
 	if (len > 0 && buf[len - 1] == '\n')
 		buf[len - 1] = 0;
 
-	if (buf[0] == '0' && buf[1] == '\0') {
-		if (!aql_disabled)
-			static_branch_inc(&aql_disable);
-	} else if (buf[0] == '1' && buf[1] == '\0') {
-		if (aql_disabled)
-			static_branch_dec(&aql_disable);
-	} else {
+	if (buf[0] == '0' && buf[1] == '\0')
+		static_branch_enable(&aql_disable);
+	else if (buf[0] == '1' && buf[1] == '\0')
+		static_branch_disable(&aql_disable);
+	else
 		return -EINVAL;
-	}
 
 	return count;
 }
Signature · 1 line
2.51.0
author maintainer
#107 lore raw

PATCH 107/220 wifi: cfg80211: cancel pmsr_free_wk in cfg80211_pmsr_wdev_down

In reply to Greg Kroah-Hartman

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

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

From: Peddolla Harshavardhan Reddy <[email protected]>

[ Upstream commit 6dccbc9f3e1d38565dff7730d2b7d1e8b16c9b09 ]

When the nl80211 socket that originated a PMSR request is closed, cfg80211_release_pmsr() sets the request's nl_portid to zero and schedules pmsr_free_wk to process the abort asynchronously. If the interface is concurrently torn down before that work runs, cfg80211_pmsr_wdev_down() calls cfg80211_pmsr_process_abort() directly. However, the already- scheduled pmsr_free_wk work item remains pending and may run after the interface has been removed from the driver. This could cause the driver's abort_pmsr callback to operate on a torn-down interface, leading to undefined behavior and potential crashes.

Cancel pmsr_free_wk synchronously in cfg80211_pmsr_wdev_down() before calling cfg80211_pmsr_process_abort(). This ensures any pending or in-progress work is drained before interface teardown proceeds, preventing the work from invoking the driver abort callback after the interface is gone.

Fixes 9bb7e0f24e7e ("cfg80211: add peer measurement with FTM initiator API")
---
 net/wireless/pmsr.c | 1 +
 1 file changed, 1 insertion(+)
net/wireless/pmsr.c +1 -0
index a117f5093ca29..13801cf35e9fc 100644
@@ -647,6 +647,7 @@ void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev)
 	}
 	spin_unlock_bh(&wdev->pmsr_lock);
 
+	cancel_work_sync(&wdev->pmsr_free_wk);
 	if (found)
 		cfg80211_pmsr_process_abort(wdev);
 
Signature · 1 line
2.51.0
author maintainer
#108 lore raw

PATCH 108/220 arm64: dts: renesas: rzt2h-n2h-evk: Add ramp delay for SD0 card regulator

In reply to Greg Kroah-Hartman

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

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

From: Lad Prabhakar <[email protected]>

[ Upstream commit bb70589b67039e491dd60cf71272884e926a0f95 ]

Add a ramp delay of 60 uV/us to the vqmmc_sdhi0 voltage regulator to fix UHS-I SD card detection failures.

Measurements on CN78 pin 4 showed the actual voltage ramp time to be 21.86ms when switching between 3.3V and 1.8V. A 25ms ramp delay has been configured to provide adequate margin. The calculation is based on the voltage delta of 1.5V (3.3V - 1.8V):
1500000 uV / 60 uV/us = 25000 us (25ms)

Prior to this patch, UHS-I cards failed to initialize with:

mmc0: error -110 whilst initialising SD card

After this patch, UHS-I cards are properly detected on SD0:

mmc0: new UHS-I speed SDR104 SDXC card at address aaaa
mmcblk0: mmc0:aaaa SR64G 59.5 GiB

Fixes d065453e5ee09 ("arm64: dts: renesas: rzt2h-rzn2h-evk: Enable SD card slot")
---
 arch/arm64/boot/dts/renesas/rzt2h-n2h-evk-common.dtsi | 1 +
 1 file changed, 1 insertion(+)
arch/arm64/boot/dts/renesas/rzt2h-n2h-evk-common.dtsi +1 -0
index 63bd91690b540..890e4ddc1e78b 100644
@@ -53,6 +53,7 @@ vqmmc_sdhi0: regulator-vqmmc-sdhi0 {
 		regulator-max-microvolt = <3300000>;
 		gpios-states = <0>;
 		states = <3300000 0>, <1800000 1>;
+		regulator-ramp-delay = <60>;
 	};
 #endif
 
Signature · 1 line
2.51.0
author maintainer
#109 lore raw

PATCH 109/220 arm64: dts: renesas: rzv2-evk-cn15-sd: Add ramp delay for SD0 regulator

In reply to Greg Kroah-Hartman

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

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

From: Lad Prabhakar <[email protected]>

[ Upstream commit 5c03465ecf6a56b7b261df9594f0e10612f53a50 ]

Set an appropriate ramp delay for the SD0 I/O voltage regulator in the CN15 SD overlay to make UHS-I voltage switching reliable during card initialization.

This issue was observed on the RZ/V2H EVK, while the same UHS-I cards worked on the RZ/V2N EVK without problems. Adding the ramp delay makes the behavior consistent and avoids SD init timeouts.

Before this change SD0 could fail with:

mmc0: error -110 whilst initialising SD card

With the delay in place UHS-I cards enumerate correctly:

    mmc0: new UHS-I speed SDR104 SDXC card at address aaaa
    mmcblk0: mmc0:aaaa SR64G 59.5 GiB
     mmcblk0: p1
Fixes 3d6c2bc7629c8 ("arm64: dts: renesas: Add CN15 eMMC and SD overlays for RZ/V2H and RZ/V2N EVKs")
---
 arch/arm64/boot/dts/renesas/rzv2-evk-cn15-sd.dtso | 1 +
 1 file changed, 1 insertion(+)
arch/arm64/boot/dts/renesas/rzv2-evk-cn15-sd.dtso +1 -0
index 0af1e0a6c7f48..fc53c1aae3b52 100644
@@ -25,6 +25,7 @@
 		regulator-max-microvolt = <3300000>;
 		gpios-states = <0>;
 		states = <3300000 0>, <1800000 1>;
+		regulator-ramp-delay = <60>;
 	};
 };
 
Signature · 1 line
2.51.0
author maintainer
#110 lore raw

PATCH 110/220 arm64: dts: renesas: r9a09g057: Remove wdt{0,2,3} nodes

In reply to Greg Kroah-Hartman

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

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

From: Fabrizio Castro <[email protected]>

[ Upstream commit a3f34651de4287138c0da19ba321ad72622b4af3 ]

The HW user manual for the Renesas RZ/V2H(P) SoC (a.k.a r9a09g057) states that only WDT1 is supposed to be accessed by the CA55 cores. WDT0 is supposed to be used by the CM33 core, WDT2 is supposed to be used by the CR8 core 0, and WDT3 is supposed to be used by the CR8 core 1.

Remove wdt{0,2,3} from the SoC specific device tree to make it compliant with the specification from the HW manual.

This change is harmless as there are currently no users of the wdt{0,2,3} device tree nodes, only the wdt1 node is actually used.

Fixes 095105496e7d ("arm64: dts: renesas: r9a09g057: Add WDT0-WDT3 nodes")
---
 arch/arm64/boot/dts/renesas/r9a09g057.dtsi | 30 ----------------------
 1 file changed, 30 deletions(-)
arch/arm64/boot/dts/renesas/r9a09g057.dtsi +0 -30
index 4df32d7e99981..3d7f4dae5c195 100644
@@ -581,16 +581,6 @@ ostm7: timer@12c03000 {
 			status = "disabled";
 		};
 
-		wdt0: watchdog@11c00400 {
-			compatible = "renesas,r9a09g057-wdt";
-			reg = <0 0x11c00400 0 0x400>;
-			clocks = <&cpg CPG_MOD 0x4b>, <&cpg CPG_MOD 0x4c>;
-			clock-names = "pclk", "oscclk";
-			resets = <&cpg 0x75>;
-			power-domains = <&cpg>;
-			status = "disabled";
-		};
-
 		wdt1: watchdog@14400000 {
 			compatible = "renesas,r9a09g057-wdt";
 			reg = <0 0x14400000 0 0x400>;
@@ -601,26 +591,6 @@ wdt1: watchdog@14400000 {
 			status = "disabled";
 		};
 
-		wdt2: watchdog@13000000 {
-			compatible = "renesas,r9a09g057-wdt";
-			reg = <0 0x13000000 0 0x400>;
-			clocks = <&cpg CPG_MOD 0x4f>, <&cpg CPG_MOD 0x50>;
-			clock-names = "pclk", "oscclk";
-			resets = <&cpg 0x77>;
-			power-domains = <&cpg>;
-			status = "disabled";
-		};
-
-		wdt3: watchdog@13000400 {
-			compatible = "renesas,r9a09g057-wdt";
-			reg = <0 0x13000400 0 0x400>;
-			clocks = <&cpg CPG_MOD 0x51>, <&cpg CPG_MOD 0x52>;
-			clock-names = "pclk", "oscclk";
-			resets = <&cpg 0x78>;
-			power-domains = <&cpg>;
-			status = "disabled";
-		};
-
 		rtc: rtc@11c00800 {
 			compatible = "renesas,r9a09g057-rtca3", "renesas,rz-rtca3";
 			reg = <0 0x11c00800 0 0x400>;
Signature · 1 line
2.51.0
author maintainer
#111 lore raw

PATCH 111/220 arm64: dts: renesas: r9a09g077: Fix CPG register region sizes

In reply to Greg Kroah-Hartman

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

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

From: Lad Prabhakar <[email protected]>

[ Upstream commit b12985ceca18bcf67f176883175d544daad5e00e ]

The CPG register regions were incorrectly sized. Update them to match the actual hardware specification:
- First region (0x80280000): 0x1000 -> 0x10000 (64kiB)
- Second region (0x81280000): 0x9000 -> 0x10000 (64kiB)

Fixes d17b34744f5e4 ("arm64: dts: renesas: Add initial support for the Renesas RZ/T2H SoC")
---
 arch/arm64/boot/dts/renesas/r9a09g077.dtsi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm64/boot/dts/renesas/r9a09g077.dtsi +2 -2
index f5fa6ca064097..5f4d30f75cbde 100644
@@ -747,8 +747,8 @@ mii_conv3: mii-conv@3 {
 
 		cpg: clock-controller@80280000 {
 			compatible = "renesas,r9a09g077-cpg-mssr";
-			reg = <0 0x80280000 0 0x1000>,
-			      <0 0x81280000 0 0x9000>;
+			reg = <0 0x80280000 0 0x10000>,
+			      <0 0x81280000 0 0x10000>;
 			clocks = <&extal_clk>;
 			clock-names = "extal";
 			#clock-cells = <2>;
Signature · 1 line
2.51.0
author maintainer
#112 lore raw

PATCH 112/220 arm64: dts: renesas: r9a09g087: Fix CPG register region sizes

In reply to Greg Kroah-Hartman

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

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

From: Lad Prabhakar <[email protected]>

[ Upstream commit f459672cf3ffd3c062973838951418271aa2ceef ]

The CPG register regions were incorrectly sized. Update them to match the actual hardware specification:
- First region (0x80280000): 0x1000 -> 0x10000 (64kiB)
- Second region (0x81280000): 0x9000 -> 0x10000 (64kiB)

Fixes 4b3d31f0b81fe ("arm64: dts: renesas: Add initial SoC DTSI for the RZ/N2H SoC")
---
 arch/arm64/boot/dts/renesas/r9a09g087.dtsi | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm64/boot/dts/renesas/r9a09g087.dtsi +2 -2
index 361a9235f00d9..46f2b1fd98dc3 100644
@@ -750,8 +750,8 @@ mii_conv3: mii-conv@3 {
 
 		cpg: clock-controller@80280000 {
 			compatible = "renesas,r9a09g087-cpg-mssr";
-			reg = <0 0x80280000 0 0x1000>,
-			      <0 0x81280000 0 0x9000>;
+			reg = <0 0x80280000 0 0x10000>,
+			      <0 0x81280000 0 0x10000>;
 			clocks = <&extal_clk>;
 			clock-names = "extal";
 			#clock-cells = <2>;
Signature · 1 line
2.51.0
author maintainer
#113 lore raw

PATCH 113/220 arm64: dts: renesas: rzg3s-smarc-som: Set bypass for Versa3 PLL2

In reply to Greg Kroah-Hartman

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

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

From: Claudiu Beznea <[email protected]>

[ Upstream commit 6dcbb6f070cccabc6a13d640a5a84de581fdd761 ]

The default settings for the Versa3 device on the Renesas RZ/G3S SMARC SoM board have PLL2 disabled. PLL2 was later enabled together with audio support, as it is required to support both 44.1 kHz and 48 kHz audio.

With PLL2 enabled, it was observed that Linux occasionally either hangs during boot (the last log message being related to the I2C probe) or randomly crashes. This was mainly reproducible on cold boots. During debugging, it was also noticed that the Unicode replacement character (�) sometimes appears on the serial console. Further investigation traced this to the configuration applied through the Versa3 register at offset 0x1c, which controls PLL enablement.

The appearance of the Unicode replacement character suggested an issue with the SoC reference clock. The RZ/G3S reference clock is provided by the Versa3 clock generator (REF output).

After checking with the Renesas Versa3 hardware team, it was found that this is related to the PLL2 lock bit being set through the renesas,settings DT property.

The PLL lock bit must be set to avoid unstable clock output from the PLL. However, due to the Versa3 hardware design, when a PLL lock bit is set, all outputs (including the REF clock) are temporarily disabled until the configured PLLs become stable.

As an alternative, the bypass bit can be used. This does not interrupt the PLL2 output or any other Versa3 outputs, but it may result in temporary instability on PLL2 output while the configuration is applied. Since PLL2 feeds only the audio path and audio is not used during early boot, this is acceptable and does not affect system boot.

Drop the PLL2 lock bit and set the bypass bit instead.

This has been tested with more than 1000 cold boots.

Fixes a94253232b04 ("arm64: dts: renesas: rzg3s-smarc-som: Add versa3 clock generator node")
---
 arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/boot/dts/renesas/rzg3s-smarc-som.dtsi +1 -1
index 6f25ab6179829..fbfa6cfb19297 100644
@@ -162,7 +162,7 @@ versa3: clock-generator@68 {
 				       <100000000>;
 		renesas,settings = [
 		  80 00 11 19 4c 42 dc 2f 06 7d 20 1a 5f 1e f2 27
-		  00 40 00 00 00 00 00 00 06 0c 19 02 3f f0 90 86
+		  00 40 00 00 00 00 00 00 06 0c 19 02 3b f0 90 86
 		  a0 80 30 30 9c
 		];
 	};
Signature · 1 line
2.51.0
author maintainer
#114 lore raw

PATCH 114/220 arm64: dts: renesas: r8a78000: Fix out-of-range SPI interrupt numbers

In reply to Greg Kroah-Hartman

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

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

From: Geert Uytterhoeven <[email protected]>

[ Upstream commit 85c2601e2c2feb60980c7ca23de28c49472f61f1 ]

SPI interrupts are in the range 0-987. Extended SPI interrupts should use GIC_ESPI, instead of abusing GIC_SPI with a manual offset of 4064.

---
 arch/arm64/boot/dts/renesas/r8a78000.dtsi | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)
arch/arm64/boot/dts/renesas/r8a78000.dtsi +8 -8
index 4c97298fa7634..3e1c98903cea0 100644
@@ -698,7 +698,7 @@ scif0: serial@c0700000 {
 			compatible = "renesas,scif-r8a78000",
 				     "renesas,rcar-gen5-scif", "renesas,scif";
 			reg = <0 0xc0700000 0 0x40>;
-			interrupts = <GIC_SPI 4074 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_ESPI 10 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>;
 			clock-names = "fck", "brg_int", "scif_clk";
 			status = "disabled";
@@ -708,7 +708,7 @@ scif1: serial@c0704000 {
 			compatible = "renesas,scif-r8a78000",
 				     "renesas,rcar-gen5-scif", "renesas,scif";
 			reg = <0 0xc0704000 0 0x40>;
-			interrupts = <GIC_SPI 4075 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_ESPI 11 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>;
 			clock-names = "fck", "brg_int", "scif_clk";
 			status = "disabled";
@@ -718,7 +718,7 @@ scif3: serial@c0708000 {
 			compatible = "renesas,scif-r8a78000",
 				     "renesas,rcar-gen5-scif", "renesas,scif";
 			reg = <0 0xc0708000 0 0x40>;
-			interrupts = <GIC_SPI 4076 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_ESPI 12 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>;
 			clock-names = "fck", "brg_int", "scif_clk";
 			status = "disabled";
@@ -728,7 +728,7 @@ scif4: serial@c070c000 {
 			compatible = "renesas,scif-r8a78000",
 				     "renesas,rcar-gen5-scif", "renesas,scif";
 			reg = <0 0xc070c000 0 0x40>;
-			interrupts = <GIC_SPI 4077 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_ESPI 13 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&dummy_clk_sgasyncd16>, <&dummy_clk_sgasyncd16>, <&scif_clk>;
 			clock-names = "fck", "brg_int", "scif_clk";
 			status = "disabled";
@@ -738,7 +738,7 @@ hscif0: serial@c0710000 {
 			compatible = "renesas,hscif-r8a78000",
 				     "renesas,rcar-gen5-hscif", "renesas,hscif";
 			reg = <0 0xc0710000 0 0x60>;
-			interrupts = <GIC_SPI 4078 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_ESPI 14 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>;
 			clock-names = "fck", "brg_int", "scif_clk";
 			status = "disabled";
@@ -748,7 +748,7 @@ hscif1: serial@c0714000 {
 			compatible = "renesas,hscif-r8a78000",
 				     "renesas,rcar-gen5-hscif", "renesas,hscif";
 			reg = <0 0xc0714000 0 0x60>;
-			interrupts = <GIC_SPI 4079 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_ESPI 15 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>;
 			clock-names = "fck", "brg_int", "scif_clk";
 			status = "disabled";
@@ -758,7 +758,7 @@ hscif2: serial@c0718000 {
 			compatible = "renesas,hscif-r8a78000",
 				     "renesas,rcar-gen5-hscif", "renesas,hscif";
 			reg = <0 0xc0718000 0 0x60>;
-			interrupts = <GIC_SPI 4080 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_ESPI 16 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>;
 			clock-names = "fck", "brg_int", "scif_clk";
 			status = "disabled";
@@ -768,7 +768,7 @@ hscif3: serial@c071c000 {
 			compatible = "renesas,hscif-r8a78000",
 				     "renesas,rcar-gen5-hscif", "renesas,hscif";
 			reg = <0 0xc071c000 0 0x60>;
-			interrupts = <GIC_SPI 4081 IRQ_TYPE_LEVEL_HIGH>;
+			interrupts = <GIC_ESPI 17 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&dummy_clk_sgasyncd4>, <&dummy_clk_sgasyncd4>, <&scif_clk>;
 			clock-names = "fck", "brg_int", "scif_clk";
 			status = "disabled";
Signature · 1 line
2.51.0
author maintainer
#115 lore raw

PATCH 115/220 firmware: arm_ffa: Remove vm_id argument in ffa_rxtx_unmap()

In reply to Greg Kroah-Hartman

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

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

From: Yeoreum Yun <[email protected]>

[ Upstream commit a4e8473b775160f3ce978f621cf8dea2c7250433 ]

According to the FF-A specification (DEN0077, v1.1, §13.7), when FFA_RXTX_UNMAP is invoked from any instance other than non-secure physical, the w1 register must be zero (MBZ). If a non-zero value is supplied in this context, the SPMC must return FFA_INVALID_PARAMETER.

The Arm FF-A driver operates exclusively as a guest or non-secure physical instance where the partition ID is always zero and is not invoked from a hypervisor context where w1 carries a VM ID. In this execution model, the partition ID observed by the driver is always zero, and passing a VM ID is unnecessary and potentially invalid.

Remove the vm_id parameter from ffa_rxtx_unmap() and ensure that the SMC call is issued with w1 implicitly zeroed, as required by the specification. This prevents invalid parameter errors and aligns the implementation with the defined FF-A ABI behavior.

Fixes 3bbfe9871005 ("firmware: arm_ffa: Add initial Arm FFA driver support")

Message-Id: <[email protected]>

---
 drivers/firmware/arm_ffa/driver.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/firmware/arm_ffa/driver.c +4 -4
index 11a702e7f641c..f6ceae987acbc 100644
@@ -205,12 +205,12 @@ static int ffa_rxtx_map(phys_addr_t tx_buf, phys_addr_t rx_buf, u32 pg_cnt)
 	return 0;
 }
 
-static int ffa_rxtx_unmap(u16 vm_id)
+static int ffa_rxtx_unmap(void)
 {
 	ffa_value_t ret;
 
 	invoke_ffa_fn((ffa_value_t){
-		      .a0 = FFA_RXTX_UNMAP, .a1 = PACK_TARGET_INFO(vm_id, 0),
+		      .a0 = FFA_RXTX_UNMAP,
 		      }, &ret);
 
 	if (ret.a0 == FFA_ERROR)
@@ -2093,7 +2093,7 @@ static int __init ffa_init(void)
 
 	pr_err("failed to setup partitions\n");
 	ffa_notifications_cleanup();
-	ffa_rxtx_unmap(drv_info->vm_id);
+	ffa_rxtx_unmap();
 free_pages:
 	if (drv_info->tx_buffer)
 		free_pages_exact(drv_info->tx_buffer, rxtx_bufsz);
@@ -2108,7 +2108,7 @@ static void __exit ffa_exit(void)
 {
 	ffa_notifications_cleanup();
 	ffa_partitions_cleanup();
-	ffa_rxtx_unmap(drv_info->vm_id);
+	ffa_rxtx_unmap();
 	free_pages_exact(drv_info->tx_buffer, drv_info->rxtx_bufsz);
 	free_pages_exact(drv_info->rx_buffer, drv_info->rxtx_bufsz);
 	kfree(drv_info);
Signature · 1 line
2.51.0
author maintainer
#116 lore raw

PATCH 116/220 firmware: arm_scpi: Fix device_node reference leak in probe path

In reply to Greg Kroah-Hartman

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

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

From: Felix Gu <[email protected]>

[ Upstream commit 879c001afbac3df94160334fe5117c0c83b2cf48 ]

A device_node reference obtained from the device tree is not released on all error paths in the arm_scpi probe path. Specifically, a node returned by of_parse_phandle() could be leaked when the probe failed after the node was acquired. The probe function returns early and the shmem reference is not released.

Use __free(device_node) scope-based cleanup to automatically release the reference when the variable goes out of scope.

Fixes ed7ecb883901 ("firmware: arm_scpi: Add compatibility checks for shmem node")

Message-Id: <[email protected]>

---
 drivers/firmware/arm_scpi.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/firmware/arm_scpi.c +3 -2
index 87c323de17b90..398642cc25d90 100644
@@ -18,6 +18,7 @@
 
 #include <linux/bitmap.h>
 #include <linux/bitfield.h>
+#include <linux/cleanup.h>
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/export.h>
@@ -940,13 +941,13 @@ static int scpi_probe(struct platform_device *pdev)
 		int idx = scpi_drvinfo->num_chans;
 		struct scpi_chan *pchan = scpi_drvinfo->channels + idx;
 		struct mbox_client *cl = &pchan->cl;
-		struct device_node *shmem = of_parse_phandle(np, "shmem", idx);
+		struct device_node *shmem __free(device_node) =
+			of_parse_phandle(np, "shmem", idx);
 
 		if (!of_match_node(shmem_of_match, shmem))
 			return -ENXIO;
 
 		ret = of_address_to_resource(shmem, 0, &res);
-		of_node_put(shmem);
 		if (ret) {
 			dev_err(dev, "failed to get SCPI payload mem resource\n");
 			return ret;
Signature · 1 line
2.51.0
author maintainer
#117 lore raw

PATCH 117/220 firmware: arm_scmi: Fix NULL dereference on notify error path

In reply to Greg Kroah-Hartman

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

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

From: Cristian Marussi <[email protected]>

[ Upstream commit 555317d6100164748f7d09f80142739bd29f0cda ]

Since commit b5daf93b809d1 ("firmware: arm_scmi: Avoid notifier registration for unsupported events") the call chains leading to the helper __scmi_event_handler_get_ops expect an ERR_PTR to be returned on failure to get an handler for the requested event key, while the current helper can still return a NULL when no handler could be found or created.

Fix by forcing an ERR_PTR return value when the handler reference is NULL.

Fixes b5daf93b809d1 ("firmware: arm_scmi: Avoid notifier registration for unsupported events")

Message-Id: <[email protected]>

---
 drivers/firmware/arm_scmi/notify.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/firmware/arm_scmi/notify.c +2 -2
index dee9f238f6fdd..2047edbdc5f6b 100644
@@ -1066,7 +1066,7 @@ static int scmi_register_event_handler(struct scmi_notify_instance *ni,
  * since at creation time we usually want to have all setup and ready before
  * events really start flowing.
  *
- * Return: A properly refcounted handler on Success, NULL on Failure
+ * Return: A properly refcounted handler on Success, ERR_PTR on Failure
  */
 static inline struct scmi_event_handler *
 __scmi_event_handler_get_ops(struct scmi_notify_instance *ni,
@@ -1113,7 +1113,7 @@ __scmi_event_handler_get_ops(struct scmi_notify_instance *ni,
 	}
 	mutex_unlock(&ni->pending_mtx);
 
-	return hndl;
+	return hndl ?: ERR_PTR(-ENODEV);
 }
 
 static struct scmi_event_handler *
Signature · 1 line
2.51.0
author maintainer
#118 lore raw

PATCH 118/220 Bluetooth: LE L2CAP: Disconnect if received packets SDU exceeds IMTU

In reply to Greg Kroah-Hartman

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

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

From: Christian Eggers <[email protected]>

[ Upstream commit e1d9a66889867c232657a9b6f25d451d7c3ab96f ]

Core 6.0, Vol 3, Part A, 3.4.3:
"If the SDU length field value exceeds the receiver's MTU, the receiver shall disconnect the channel..."

This fixes L2CAP/LE/CFC/BV-26-C (running together with 'l2test -r -P 0x0027 -V le_public -I 100').

Fixes aac23bf63659 ("Bluetooth: Implement LE L2CAP reassembly")
---
 net/bluetooth/l2cap_core.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
net/bluetooth/l2cap_core.c +7 -3
index 319c87bd795d5..1618fe98dce71 100644
@@ -6654,8 +6654,10 @@ static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
 		return -ENOBUFS;
 	}
 
-	if (chan->imtu < skb->len) {
-		BT_ERR("Too big LE L2CAP PDU");
+	if (skb->len > chan->imtu) {
+		BT_ERR("Too big LE L2CAP PDU: len %u > %u", skb->len,
+		       chan->imtu);
+		l2cap_send_disconn_req(chan, ECONNRESET);
 		return -ENOBUFS;
 	}
 
@@ -6681,7 +6683,9 @@ static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
 		       sdu_len, skb->len, chan->imtu);
 
 		if (sdu_len > chan->imtu) {
-			BT_ERR("Too big LE L2CAP SDU length received");
+			BT_ERR("Too big LE L2CAP SDU length: len %u > %u",
+			       skb->len, sdu_len);
+			l2cap_send_disconn_req(chan, ECONNRESET);
 			err = -EMSGSIZE;
 			goto failed;
 		}
Signature · 1 line
2.51.0
author maintainer
#119 lore raw

PATCH 119/220 Bluetooth: LE L2CAP: Disconnect if sum of payload sizes exceed SDU

In reply to Greg Kroah-Hartman

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

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

From: Christian Eggers <[email protected]>

[ Upstream commit b6a2bf43aa37670432843bc73ae2a6288ba4d6f8 ]

Core 6.0, Vol 3, Part A, 3.4.3:
"... If the sum of the payload sizes for the K-frames exceeds the specified SDU length, the receiver shall disconnect the channel."

This fixes L2CAP/LE/CFC/BV-27-C (running together with 'l2test -r -P 0x0027 -V le_public').

Fixes aac23bf63659 ("Bluetooth: Implement LE L2CAP reassembly")
---
 net/bluetooth/l2cap_core.c | 1 +
 1 file changed, 1 insertion(+)
net/bluetooth/l2cap_core.c +1 -0
index 1618fe98dce71..05acc2e98f58f 100644
@@ -6721,6 +6721,7 @@ static int l2cap_ecred_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb)
 
 	if (chan->sdu->len + skb->len > chan->sdu_len) {
 		BT_ERR("Too much LE L2CAP data received");
+		l2cap_send_disconn_req(chan, ECONNRESET);
 		err = -EINVAL;
 		goto failed;
 	}
Signature · 1 line
2.51.0
author maintainer
#120 lore raw

PATCH 120/220 Bluetooth: SMP: make SM/PER/KDU/BI-04-C happy

In reply to Greg Kroah-Hartman

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

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

From: Christian Eggers <[email protected]>

[ Upstream commit 0e4d4dcc1a6e82cc6f9abf32193558efa7e1613d ]

The last test step ("Test with Invalid public key X and Y, all set to 0") expects to get an "DHKEY check failed" instead of "unspecified".

Fixes 6d19628f539f ("Bluetooth: SMP: Fail if remote and local public keys are identical")
---
 net/bluetooth/smp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/bluetooth/smp.c +1 -1
index 3a1ce04a7a536..9d96040745897 100644
@@ -2743,7 +2743,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
 	if (!test_bit(SMP_FLAG_DEBUG_KEY, &smp->flags) &&
 	    !crypto_memneq(key, smp->local_pk, 64)) {
 		bt_dev_err(hdev, "Remote and local public keys are identical");
-		return SMP_UNSPECIFIED;
+		return SMP_DHKEY_CHECK_FAILED;
 	}
 
 	memcpy(smp->remote_pk, key, 64);
Signature · 1 line
2.51.0
author maintainer
#121 lore raw

PATCH 121/220 Bluetooth: ISO: Fix defer tests being unstable

In reply to Greg Kroah-Hartman

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

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

From: Luiz Augusto von Dentz <[email protected]>

[ Upstream commit 62bcaa6b351b6dc400f6c6b83762001fd9f5c12d ]

iso-tester defer tests seem to fail with hci_conn_hash_lookup_cig being unable to resolve a cig in set_cig_params_sync due a race where it is run immediatelly before hci_bind_cis is able to set the QoS settings into the hci_conn object.

So this moves the assigning of the QoS settings to be done directly by hci_le_set_cig_params to prevent that from happening again.

Fixes 26afbd826ee3 ("Bluetooth: Add initial implementation of CIS connections")
---
 net/bluetooth/hci_conn.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
net/bluetooth/hci_conn.c +2 -2
index dc085856f5e91..0f512c2c2fd3c 100644
@@ -1944,6 +1944,8 @@ static bool hci_le_set_cig_params(struct hci_conn *conn, struct bt_iso_qos *qos)
 		return false;
 
 done:
+	conn->iso_qos = *qos;
+
 	if (hci_cmd_sync_queue(hdev, set_cig_params_sync,
 			       UINT_PTR(qos->ucast.cig), NULL) < 0)
 		return false;
@@ -2013,8 +2015,6 @@ struct hci_conn *hci_bind_cis(struct hci_dev *hdev, bdaddr_t *dst,
 	}
 
 	hci_conn_hold(cis);
-
-	cis->iso_qos = *qos;
 	cis->state = BT_BOUND;
 
 	return cis;
Signature · 1 line
2.51.0
author maintainer
#122 lore raw

PATCH 122/220 Bluetooth: hci_sync: Fix hci_le_create_conn_sync

In reply to Greg Kroah-Hartman

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

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

From: Michael Grzeschik <[email protected]>

[ Upstream commit 2cabe7ff1001b7a197009cf50ba71701f9cbd354 ]

While introducing hci_le_create_conn_sync the functionality of hci_connect_le was ported to hci_le_create_conn_sync including the disable of the scan before starting the connection.

When this code was run non synchronously the immediate call that was setting the flag HCI_LE_SCAN_INTERRUPTED had an impact. Since the completion handler for the LE_SCAN_DISABLE was not immediately called. In the completion handler of the LE_SCAN_DISABLE event, this flag is checked to set the state of the hdev to DISCOVERY_STOPPED.

With the synchronised approach the later setting of the HCI_LE_SCAN_INTERRUPTED flag has not the same effect. The completion handler would immediately fire in the LE_SCAN_DISABLE call, check for the flag, which is then not yet set and do nothing.

To fix this issue and make the function call work as before, we move the setting of the flag HCI_LE_SCAN_INTERRUPTED before disabling the scan.

Fixes 8e8b92ee60de ("Bluetooth: hci_sync: Add hci_le_create_conn_sync")
---
 net/bluetooth/hci_sync.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/bluetooth/hci_sync.c +1 -1
index 80b601e344ae3..43b36581e336d 100644
@@ -6596,8 +6596,8 @@ static int hci_le_create_conn_sync(struct hci_dev *hdev, void *data)
 	 * state.
 	 */
 	if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
-		hci_scan_disable_sync(hdev);
 		hci_dev_set_flag(hdev, HCI_LE_SCAN_INTERRUPTED);
+		hci_scan_disable_sync(hdev);
 	}
 
 	/* Update random address, but set require_privacy to false so
Signature · 1 line
2.51.0
author maintainer
#123 lore raw

PATCH 123/220 Bluetooth: MGMT: Fix list corruption and UAF in command complete handlers

In reply to Greg Kroah-Hartman

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

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

From: Wang Tao <[email protected]>

[ Upstream commit 17f89341cb4281d1da0e2fb0de5406ab7c4e25ef ]

Commit 302a1f674c00 ("Bluetooth: MGMT: Fix possible UAFs") introduced mgmt_pending_valid(), which not only validates the pending command but also unlinks it from the pending list if it is valid. This change in semantics requires updates to several completion handlers to avoid list corruption and memory safety issues.

This patch addresses two left-over issues from the aforementioned rework:

1. In mgmt_add_adv_patterns_monitor_complete(), mgmt_pending_remove() is replaced with mgmt_pending_free() in the success path. Since mgmt_pending_valid() already unlinks the command at the beginning of the function, calling mgmt_pending_remove() leads to a double list_del() and subsequent list corruption/kernel panic.

2. In set_mesh_complete(), the use of mgmt_pending_foreach() in the error path is removed. Since the current command is already unlinked by mgmt_pending_valid(), this foreach loop would incorrectly target other pending mesh commands, potentially freeing them while they are still being processed concurrently (leading to UAFs). The redundant mgmt_cmd_status() is also simplified to use cmd->opcode directly.

Fixes 302a1f674c00 ("Bluetooth: MGMT: Fix possible UAFs")
---
 net/bluetooth/mgmt.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)
net/bluetooth/mgmt.c +2 -5
index 0e46f9e08b106..2c63f49c33018 100644
@@ -2195,10 +2195,7 @@ static void set_mesh_complete(struct hci_dev *hdev, void *data, int err)
 	sk = cmd->sk;
 
 	if (status) {
-		mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_MESH_RECEIVER,
-				status);
-		mgmt_pending_foreach(MGMT_OP_SET_MESH_RECEIVER, hdev, true,
-				     cmd_status_rsp, &status);
+		mgmt_cmd_status(cmd->sk, hdev->id, cmd->opcode, status);
 		goto done;
 	}
 
@@ -5377,7 +5374,7 @@ static void mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev,
 
 	mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode,
 			  mgmt_status(status), &rp, sizeof(rp));
-	mgmt_pending_remove(cmd);
+	mgmt_pending_free(cmd);
 
 	hci_dev_unlock(hdev);
 	bt_dev_dbg(hdev, "add monitor %d complete, status %d",
Signature · 1 line
2.51.0
author maintainer
#124 lore raw

PATCH 124/220 Bluetooth: HIDP: Fix possible UAF

In reply to Greg Kroah-Hartman

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

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

From: Luiz Augusto von Dentz <[email protected]>

[ Upstream commit dbf666e4fc9bdd975a61bf682b3f75cb0145eedd ]

This fixes the following trace caused by not dropping l2cap_conn reference when user->remove callback is called:

[   97.809249] l2cap_conn_free: freeing conn ffff88810a171c00
[   97.809907] CPU: 1 UID: 0 PID: 1419 Comm: repro_standalon Not tainted 7.0.0-rc1-dirty #14 PREEMPT(lazy)
[   97.809935] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014
[   97.809947] Call Trace:
[   97.809954]  <TASK>
[   97.809961]  dump_stack_lvl (lib/dump_stack.c:122)
[   97.809990]  l2cap_conn_free (net/bluetooth/l2cap_core.c:1808)
[   97.810017]  l2cap_conn_del (./include/linux/kref.h:66 net/bluetooth/l2cap_core.c:1821 net/bluetooth/l2cap_core.c:1798)
[   97.810055]  l2cap_disconn_cfm (net/bluetooth/l2cap_core.c:7347 (discriminator 1) net/bluetooth/l2cap_core.c:7340 (discriminator 1))
[   97.810086]  ? __pfx_l2cap_disconn_cfm (net/bluetooth/l2cap_core.c:7341)
[   97.810117]  hci_conn_hash_flush (./include/net/bluetooth/hci_core.h:2152 (discriminator 2) net/bluetooth/hci_conn.c:2644 (discriminator 2))
[   97.810148]  hci_dev_close_sync (net/bluetooth/hci_sync.c:5360)
[   97.810180]  ? __pfx_hci_dev_close_sync (net/bluetooth/hci_sync.c:5285)
[   97.810212]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.810242]  ? up_write (./arch/x86/include/asm/atomic64_64.h:87 (discriminator 5) ./include/linux/atomic/atomic-arch-fallback.h:2852 (discriminator 5) ./include/linux/atomic/atomic-long.h:268 (discriminator 5) ./include/linux/atomic/atomic-instrumented.h:3391 (discriminator 5) kernel/locking/rwsem.c:1385 (discriminator 5) kernel/locking/rwsem.c:1643 (discriminator 5))
[   97.810267]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.810290]  ? rcu_is_watching (./arch/x86/include/asm/atomic.h:23 ./include/linux/atomic/atomic-arch-fallback.h:457 ./include/linux/context_tracking.h:128 kernel/rcu/tree.c:752)
[   97.810320]  hci_unregister_dev (net/bluetooth/hci_core.c:504 net/bluetooth/hci_core.c:2716)
[   97.810346]  vhci_release (drivers/bluetooth/hci_vhci.c:691)
[   97.810375]  ? __pfx_vhci_release (drivers/bluetooth/hci_vhci.c:678)
[   97.810404]  __fput (fs/file_table.c:470)
[   97.810430]  task_work_run (kernel/task_work.c:235)
[   97.810451]  ? __pfx_task_work_run (kernel/task_work.c:201)
[   97.810472]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.810495]  ? do_raw_spin_unlock (./include/asm-generic/qspinlock.h:128 (discriminator 5) kernel/locking/spinlock_debug.c:142 (discriminator 5))
[   97.810527]  do_exit (kernel/exit.c:972)
[   97.810547]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.810574]  ? __pfx_do_exit (kernel/exit.c:897)
[   97.810594]  ? lock_acquire (kernel/locking/lockdep.c:470 (discriminator 6) kernel/locking/lockdep.c:5870 (discriminator 6) kernel/locking/lockdep.c:5825 (discriminator 6))
[   97.810616]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.810639]  ? do_raw_spin_lock (kernel/locking/spinlock_debug.c:95 (discriminator 4) kernel/locking/spinlock_debug.c:118 (discriminator 4))
[   97.810664]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.810688]  ? find_held_lock (kernel/locking/lockdep.c:5350 (discriminator 1))
[   97.810721]  do_group_exit (kernel/exit.c:1093)
[   97.810745]  get_signal (kernel/signal.c:3007 (discriminator 1))
[   97.810772]  ? security_file_permission (./arch/x86/include/asm/jump_label.h:37 security/security.c:2366)
[   97.810803]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.810826]  ? vfs_read (fs/read_write.c:555)
[   97.810854]  ? __pfx_get_signal (kernel/signal.c:2800)
[   97.810880]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.810905]  ? __pfx_vfs_read (fs/read_write.c:555)
[   97.810932]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.810960]  arch_do_signal_or_restart (arch/x86/kernel/signal.c:337 (discriminator 1))
[   97.810990]  ? __pfx_arch_do_signal_or_restart (arch/x86/kernel/signal.c:334)
[   97.811021]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.811055]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.811078]  ? ksys_read (fs/read_write.c:707)
[   97.811106]  ? __pfx_ksys_read (fs/read_write.c:707)
[   97.811137]  exit_to_user_mode_loop (kernel/entry/common.c:66 kernel/entry/common.c:98)
[   97.811169]  ? rcu_is_watching (./arch/x86/include/asm/atomic.h:23 ./include/linux/atomic/atomic-arch-fallback.h:457 ./include/linux/context_tracking.h:128 kernel/rcu/tree.c:752)
[   97.811192]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.811215]  ? trace_hardirqs_off (./include/trace/events/preemptirq.h:36 (discriminator 33) kernel/trace/trace_preemptirq.c:95 (discriminator 33) kernel/trace/trace_preemptirq.c:90 (discriminator 33))
[   97.811240]  do_syscall_64 (./include/linux/irq-entry-common.h:226 ./include/linux/irq-entry-common.h:256 ./include/linux/entry-common.h:325 arch/x86/entry/syscall_64.c:100)
[   97.811268]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   97.811292]  ? exc_page_fault (arch/x86/mm/fault.c:1480 (discriminator 3) arch/x86/mm/fault.c:1527 (discriminator 3))
[   97.811318]  entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130)
[   97.811338] RIP: 0033:0x445cfe
[   97.811352] Code: Unable to access opcode bytes at 0x445cd4.

Code starting with the faulting instruction
===========================================

[   97.811360] RSP: 002b:00007f65c41c6dc8 EFLAGS: 00000246 ORIG_RAX: 0000000000000000
[   97.811378] RAX: fffffffffffffe00 RBX: 00007f65c41c76c0 RCX: 0000000000445cfe
[   97.811391] RDX: 0000000000000400 RSI: 00007f65c41c6e40 RDI: 0000000000000004
[   97.811403] RBP: 00007f65c41c7250 R08: 0000000000000000 R09: 0000000000000000
[   97.811415] R10: 0000000000000000 R11: 0000000000000246 R12: ffffffffffffffe8
[   97.811428] R13: 0000000000000000 R14: 00007fff780a8c00 R15: 00007f65c41c76c0
[   97.811453]  </TASK>
[   98.402453] ==================================================================
[   98.403560] BUG: KASAN: use-after-free in __mutex_lock (kernel/locking/mutex.c:199 kernel/locking/mutex.c:694 kernel/locking/mutex.c:776)
[   98.404541] Read of size 8 at addr ffff888113ee40a8 by task khidpd_00050004/1430
[   98.405361]
[   98.405563] CPU: 1 UID: 0 PID: 1430 Comm: khidpd_00050004 Not tainted 7.0.0-rc1-dirty #14 PREEMPT(lazy)
[   98.405588] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014
[   98.405600] Call Trace:
[   98.405607]  <TASK>
[   98.405614]  dump_stack_lvl (lib/dump_stack.c:122)
[   98.405641]  print_report (mm/kasan/report.c:379 mm/kasan/report.c:482)
[   98.405667]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.405691]  ? __virt_addr_valid (arch/x86/mm/physaddr.c:55)
[   98.405724]  ? __mutex_lock (kernel/locking/mutex.c:199 kernel/locking/mutex.c:694 kernel/locking/mutex.c:776)
[   98.405748]  kasan_report (mm/kasan/report.c:221 mm/kasan/report.c:597)
[   98.405778]  ? __mutex_lock (kernel/locking/mutex.c:199 kernel/locking/mutex.c:694 kernel/locking/mutex.c:776)
[   98.405807]  __mutex_lock (kernel/locking/mutex.c:199 kernel/locking/mutex.c:694 kernel/locking/mutex.c:776)
[   98.405832]  ? do_raw_spin_lock (kernel/locking/spinlock_debug.c:95 (discriminator 4) kernel/locking/spinlock_debug.c:118 (discriminator 4))
[   98.405859]  ? l2cap_unregister_user (./include/linux/list.h:381 (discriminator 2) net/bluetooth/l2cap_core.c:1723 (discriminator 2))
[   98.405888]  ? __pfx_do_raw_spin_lock (kernel/locking/spinlock_debug.c:114)
[   98.405915]  ? __pfx___mutex_lock (kernel/locking/mutex.c:775)
[   98.405939]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.405963]  ? lock_acquire (kernel/locking/lockdep.c:470 (discriminator 6) kernel/locking/lockdep.c:5870 (discriminator 6) kernel/locking/lockdep.c:5825 (discriminator 6))
[   98.405984]  ? find_held_lock (kernel/locking/lockdep.c:5350 (discriminator 1))
[   98.406015]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.406038]  ? lock_release (kernel/locking/lockdep.c:5536 kernel/locking/lockdep.c:5889 kernel/locking/lockdep.c:5875)
[   98.406061]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.406085]  ? _raw_spin_unlock_irqrestore (./arch/x86/include/asm/irqflags.h:42 ./arch/x86/include/asm/irqflags.h:119 ./arch/x86/include/asm/irqflags.h:159 ./include/linux/spinlock_api_smp.h:178 kernel/locking/spinlock.c:194)
[   98.406107]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.406130]  ? __timer_delete_sync (kernel/time/timer.c:1592)
[   98.406158]  ? l2cap_unregister_user (./include/linux/list.h:381 (discriminator 2) net/bluetooth/l2cap_core.c:1723 (discriminator 2))
[   98.406186]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.406210]  l2cap_unregister_user (./include/linux/list.h:381 (discriminator 2) net/bluetooth/l2cap_core.c:1723 (discriminator 2))
[   98.406263]  hidp_session_thread (./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 ./include/linux/kref.h:64 net/bluetooth/hidp/core.c:996 net/bluetooth/hidp/core.c:1305)
[   98.406293]  ? __pfx_hidp_session_thread (net/bluetooth/hidp/core.c:1264)
[   98.406323]  ? kthread (kernel/kthread.c:433)
[   98.406340]  ? __pfx_hidp_session_wake_function (net/bluetooth/hidp/core.c:1251)
[   98.406370]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.406393]  ? find_held_lock (kernel/locking/lockdep.c:5350 (discriminator 1))
[   98.406424]  ? __pfx_hidp_session_wake_function (net/bluetooth/hidp/core.c:1251)
[   98.406453]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.406476]  ? trace_hardirqs_on (kernel/trace/trace_preemptirq.c:79 (discriminator 1))
[   98.406499]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.406523]  ? kthread (kernel/kthread.c:433)
[   98.406539]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.406565]  ? kthread (kernel/kthread.c:433)
[   98.406581]  ? __pfx_hidp_session_thread (net/bluetooth/hidp/core.c:1264)
[   98.406610]  kthread (kernel/kthread.c:467)
[   98.406627]  ? __pfx_kthread (kernel/kthread.c:412)
[   98.406645]  ret_from_fork (arch/x86/kernel/process.c:164)
[   98.406674]  ? __pfx_ret_from_fork (arch/x86/kernel/process.c:153)
[   98.406704]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.406728]  ? __pfx_kthread (kernel/kthread.c:412)
[   98.406747]  ret_from_fork_asm (arch/x86/entry/entry_64.S:258)
[   98.406774]  </TASK>
[   98.406780]
[   98.433693] The buggy address belongs to the physical page:
[   98.434405] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffff888113ee7c40 pfn:0x113ee4
[   98.435557] flags: 0x200000000000000(node=0|zone=2)
[   98.436198] raw: 0200000000000000 ffffea0004244308 ffff8881f6f3ebc0 0000000000000000
[   98.437195] raw: ffff888113ee7c40 0000000000000000 00000000ffffffff 0000000000000000
[   98.438115] page dumped because: kasan: bad access detected
[   98.438951]
[   98.439211] Memory state around the buggy address:
[   98.439871]  ffff888113ee3f80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[   98.440714]  ffff888113ee4000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[   98.441580] >ffff888113ee4080: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[   98.442458]                                   ^
[   98.443011]  ffff888113ee4100: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[   98.443889]  ffff888113ee4180: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
[   98.444768] ==================================================================
[   98.445719] Disabling lock debugging due to kernel taint
[   98.448074] l2cap_conn_free: freeing conn ffff88810c22b400
[   98.450012] CPU: 1 UID: 0 PID: 1430 Comm: khidpd_00050004 Tainted: G    B               7.0.0-rc1-dirty #14 PREEMPT(lazy)
[   98.450040] Tainted: [B]=BAD_PAGE
[   98.450047] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014
[   98.450059] Call Trace:
[   98.450065]  <TASK>
[   98.450071]  dump_stack_lvl (lib/dump_stack.c:122)
[   98.450099]  l2cap_conn_free (net/bluetooth/l2cap_core.c:1808)
[   98.450125]  l2cap_conn_put (net/bluetooth/l2cap_core.c:1822)
[   98.450154]  session_free (net/bluetooth/hidp/core.c:990)
[   98.450181]  hidp_session_thread (net/bluetooth/hidp/core.c:1307)
[   98.450213]  ? __pfx_hidp_session_thread (net/bluetooth/hidp/core.c:1264)
[   98.450271]  ? kthread (kernel/kthread.c:433)
[   98.450293]  ? __pfx_hidp_session_wake_function (net/bluetooth/hidp/core.c:1251)
[   98.450339]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.450368]  ? find_held_lock (kernel/locking/lockdep.c:5350 (discriminator 1))
[   98.450406]  ? __pfx_hidp_session_wake_function (net/bluetooth/hidp/core.c:1251)
[   98.450442]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.450471]  ? trace_hardirqs_on (kernel/trace/trace_preemptirq.c:79 (discriminator 1))
[   98.450499]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.450528]  ? kthread (kernel/kthread.c:433)
[   98.450547]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.450578]  ? kthread (kernel/kthread.c:433)
[   98.450598]  ? __pfx_hidp_session_thread (net/bluetooth/hidp/core.c:1264)
[   98.450637]  kthread (kernel/kthread.c:467)
[   98.450657]  ? __pfx_kthread (kernel/kthread.c:412)
[   98.450680]  ret_from_fork (arch/x86/kernel/process.c:164)
[   98.450715]  ? __pfx_ret_from_fork (arch/x86/kernel/process.c:153)
[   98.450752]  ? srso_alias_return_thunk (arch/x86/lib/retpoline.S:221)
[   98.450782]  ? __pfx_kthread (kernel/kthread.c:412)
[   98.450804]  ret_from_fork_asm (arch/x86/entry/entry_64.S:258)
[   98.450836]  </TASK>
Fixes b4f34d8d9d26 ("Bluetooth: hidp: add new session-management helpers")
---
 net/bluetooth/hidp/core.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)
net/bluetooth/hidp/core.c +14 -2
index 6724adce615b6..e0e4003815500 100644
@@ -986,7 +986,8 @@ static void session_free(struct kref *ref)
 	skb_queue_purge(&session->intr_transmit);
 	fput(session->intr_sock->file);
 	fput(session->ctrl_sock->file);
-	l2cap_conn_put(session->conn);
+	if (session->conn)
+		l2cap_conn_put(session->conn);
 	kfree(session);
 }
 
@@ -1164,6 +1165,15 @@ static void hidp_session_remove(struct l2cap_conn *conn,
 
 	down_write(&hidp_session_sem);
 
+	/* Drop L2CAP reference immediately to indicate that
+	 * l2cap_unregister_user() shall not be called as it is already
+	 * considered removed.
+	 */
+	if (session->conn) {
+		l2cap_conn_put(session->conn);
+		session->conn = NULL;
+	}
+
 	hidp_session_terminate(session);
 
 	cancel_work_sync(&session->dev_init);
@@ -1301,7 +1311,9 @@ static int hidp_session_thread(void *arg)
 	 * Instead, this call has the same semantics as if user-space tried to
 	 * delete the session.
 	 */
-	l2cap_unregister_user(session->conn, &session->user);
+	if (session->conn)
+		l2cap_unregister_user(session->conn, &session->user);
+
 	hidp_session_put(session);
 
 	module_put_and_kthread_exit(0);
Signature · 1 line
2.51.0
author maintainer
#125 lore raw

PATCH 125/220 Bluetooth: L2CAP: Fix use-after-free in l2cap_unregister_user

In reply to Greg Kroah-Hartman

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

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

From: Shaurya Rane <[email protected]>

[ Upstream commit 752a6c9596dd25efd6978a73ff21f3b592668f4a ]

After commit ab4eedb790ca ("Bluetooth: L2CAP: Fix corrupted list in hci_chan_del"), l2cap_conn_del() uses conn->lock to protect access to conn->users. However, l2cap_register_user() and l2cap_unregister_user() don't use conn->lock, creating a race condition where these functions can access conn->users and conn->hchan concurrently with l2cap_conn_del().

This can lead to use-after-free and list corruption bugs, as reported by syzbot.

Fix this by changing l2cap_register_user() and l2cap_unregister_user() to use conn->lock instead of hci_dev_lock(), ensuring consistent locking for the l2cap_conn structure.

Reported-by [email protected]
Fixes ab4eedb790ca ("Bluetooth: L2CAP: Fix corrupted list in hci_chan_del")
---
 net/bluetooth/l2cap_core.c | 20 ++++++++------------
 1 file changed, 8 insertions(+), 12 deletions(-)
net/bluetooth/l2cap_core.c +8 -12
index 05acc2e98f58f..9ea030fc9a9cc 100644
@@ -1686,17 +1686,15 @@ static void l2cap_info_timeout(struct work_struct *work)
 
 int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user)
 {
-	struct hci_dev *hdev = conn->hcon->hdev;
 	int ret;
 
 	/* We need to check whether l2cap_conn is registered. If it is not, we
-	 * must not register the l2cap_user. l2cap_conn_del() is unregisters
-	 * l2cap_conn objects, but doesn't provide its own locking. Instead, it
-	 * relies on the parent hci_conn object to be locked. This itself relies
-	 * on the hci_dev object to be locked. So we must lock the hci device
-	 * here, too. */
+	 * must not register the l2cap_user. l2cap_conn_del() unregisters
+	 * l2cap_conn objects under conn->lock, and we use the same lock here
+	 * to protect access to conn->users and conn->hchan.
+	 */
 
-	hci_dev_lock(hdev);
+	mutex_lock(&conn->lock);
 
 	if (!list_empty(&user->list)) {
 		ret = -EINVAL;
@@ -1717,16 +1715,14 @@ int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user)
 	ret = 0;
 
 out_unlock:
-	hci_dev_unlock(hdev);
+	mutex_unlock(&conn->lock);
 	return ret;
 }
 EXPORT_SYMBOL(l2cap_register_user);
 
 void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user)
 {
-	struct hci_dev *hdev = conn->hcon->hdev;
-
-	hci_dev_lock(hdev);
+	mutex_lock(&conn->lock);
 
 	if (list_empty(&user->list))
 		goto out_unlock;
@@ -1735,7 +1731,7 @@ void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user)
 	user->remove(conn, user);
 
 out_unlock:
-	hci_dev_unlock(hdev);
+	mutex_unlock(&conn->lock);
 }
 EXPORT_SYMBOL(l2cap_unregister_user);
 
Signature · 1 line
2.51.0
author maintainer
#126 lore raw

PATCH 126/220 Bluetooth: qca: fix ROM version reading on WCN3998 chips

In reply to Greg Kroah-Hartman

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

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

From: Dmitry Baryshkov <[email protected]>

[ Upstream commit 99b2c531e0e797119ae1b9195a8764ee98b00e65 ]

WCN3998 uses a bit different format for rom version:

[    5.479978] Bluetooth: hci0: setting up wcn399x
[    5.633763] Bluetooth: hci0: QCA Product ID   :0x0000000a
[    5.645350] Bluetooth: hci0: QCA SOC Version  :0x40010224
[    5.650906] Bluetooth: hci0: QCA ROM Version  :0x00001001
[    5.665173] Bluetooth: hci0: QCA Patch Version:0x00006699
[    5.679356] Bluetooth: hci0: QCA controller version 0x02241001
[    5.691109] Bluetooth: hci0: QCA Downloading qca/crbtfw21.tlv
[    6.680102] Bluetooth: hci0: QCA Downloading qca/crnv21.bin
[    6.842948] Bluetooth: hci0: QCA setup on UART is completed
Fixes 523760b7ff88 ("Bluetooth: hci_qca: Added support for WCN3998")
---
 drivers/bluetooth/btqca.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/bluetooth/btqca.c +2 -0
index 7c958d6065bec..86a48d009d1ba 100644
@@ -804,6 +804,8 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
 	 */
 	if (soc_type == QCA_WCN3988)
 		rom_ver = ((soc_ver & 0x00000f00) >> 0x05) | (soc_ver & 0x0000000f);
+	else if (soc_type == QCA_WCN3998)
+		rom_ver = ((soc_ver & 0x0000f000) >> 0x07) | (soc_ver & 0x0000000f);
 	else
 		rom_ver = ((soc_ver & 0x00000f00) >> 0x04) | (soc_ver & 0x0000000f);
 
Signature · 1 line
2.51.0
author maintainer
#127 lore raw

PATCH 127/220 af_unix: Give up GC if MSG_PEEK intervened.

In reply to Greg Kroah-Hartman

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

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

From: Kuniyuki Iwashima <[email protected]>

[ Upstream commit e5b31d988a41549037b8d8721a3c3cae893d8670 ]

Igor Ushakov reported that GC purged the receive queue of an alive socket due to a race with MSG_PEEK with a nice repro.

This is the exact same issue previously fixed by commit cbcf01128d0a ("af_unix: fix garbage collect vs MSG_PEEK").

After GC was replaced with the current algorithm, the cited commit removed the locking dance in unix_peek_fds() and reintroduced the same issue.

The problem is that MSG_PEEK bumps a file refcount without interacting with GC.

Consider an SCC containing sk-A and sk-B, where sk-A is close()d but can be recv()ed via sk-B.

The bad thing happens if sk-A is recv()ed with MSG_PEEK from sk-B and sk-B is close()d while GC is checking unix_vertex_dead() for sk-A and sk-B.

  GC thread                    User thread
  ---------                    -----------
  unix_vertex_dead(sk-A)
  -> true   <------.
                    \
                     `------   recv(sk-B, MSG_PEEK)
              invalidate !!    -> sk-A's file refcount : 1 -> 2
                               close(sk-B)
                               -> sk-B's file refcount : 2 -> 1

unix_vertex_dead(sk-B)
-> true

Initially, sk-A's file refcount is 1 by the inflight fd in sk-B recvq. GC thinks sk-A is dead because the file refcount is the same as the number of its inflight fds.

However, sk-A's file refcount is bumped silently by MSG_PEEK, which invalidates the previous evaluation.

At this moment, sk-B's file refcount is 2; one by the open fd, and one by the inflight fd in sk-A. The subsequent close() releases one refcount by the former.

Finally, GC incorrectly concludes that both sk-A and sk-B are dead.

One option is to restore the locking dance in unix_peek_fds(), but we can resolve this more elegantly thanks to the new algorithm.

The point is that the issue does not occur without the subsequent close() and we actually do not need to synchronise MSG_PEEK with the dead SCC detection.

When the issue occurs, close() and GC touch the same file refcount. If GC sees the refcount being decremented by close(), it can just give up garbage-collecting the SCC.

Therefore, we only need to signal the race during MSG_PEEK with a proper memory barrier to make it visible to the GC.

Let's use seqcount_t to notify GC when MSG_PEEK occurs and let it defer the SCC to the next run.

This way no locking is needed on the MSG_PEEK side, and we can avoid imposing a penalty on every MSG_PEEK unnecessarily.

Note that we can retry within unix_scc_dead() if MSG_PEEK is detected, but we do not do so to avoid hung task splat from abusive MSG_PEEK calls.

Fixes 118f457da9ed ("af_unix: Remove lock dance in unix_peek_fds().")
---
 net/unix/af_unix.c |  2 ++
 net/unix/af_unix.h |  1 +
 net/unix/garbage.c | 79 ++++++++++++++++++++++++++++++----------------
 3 files changed, 54 insertions(+), 28 deletions(-)
net/unix/af_unix.c +2 -0
index 6965b9a49d68a..3db79e83d2114 100644
@@ -1958,6 +1958,8 @@ static void unix_detach_fds(struct scm_cookie *scm, struct sk_buff *skb)
 static void unix_peek_fds(struct scm_cookie *scm, struct sk_buff *skb)
 {
 	scm->fp = scm_fp_dup(UNIXCB(skb).fp);
+
+	unix_peek_fpl(scm->fp);
 }
 
 static void unix_destruct_scm(struct sk_buff *skb)
net/unix/af_unix.h +1 -0
index c4f1b2da363de..8119dbeef3a3c 100644
@@ -29,6 +29,7 @@ void unix_del_edges(struct scm_fp_list *fpl);
 void unix_update_edges(struct unix_sock *receiver);
 int unix_prepare_fpl(struct scm_fp_list *fpl);
 void unix_destroy_fpl(struct scm_fp_list *fpl);
+void unix_peek_fpl(struct scm_fp_list *fpl);
 void unix_schedule_gc(struct user_struct *user);
 
 /* SOCK_DIAG */
net/unix/garbage.c +51 -28

126 lines not on this page · raw message

Signature · 1 line
2.51.0
author maintainer
#128 lore raw

PATCH 128/220 bridge: cfm: Fix race condition in peer_mep deletion

In reply to Greg Kroah-Hartman

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

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

From: Hyunwoo Kim <[email protected]>

[ Upstream commit 3715a00855316066cdda69d43648336367422127 ]

When a peer MEP is being deleted, cancel_delayed_work_sync() is called on ccm_rx_dwork before freeing. However, br_cfm_frame_rx() runs in softirq context under rcu_read_lock (without RTNL) and can re-schedule ccm_rx_dwork via ccm_rx_timer_start() between cancel_delayed_work_sync() returning and kfree_rcu() being called.

The following is a simple race scenario:

cpu0 cpu1

mep_delete_implementation()

  cancel_delayed_work_sync(ccm_rx_dwork);
                                           br_cfm_frame_rx()
                                             // peer_mep still in hlist
                                             if (peer_mep->ccm_defect)
                                               ccm_rx_timer_start()
                                                 queue_delayed_work(ccm_rx_dwork)
  hlist_del_rcu(&peer_mep->head);
  kfree_rcu(peer_mep, rcu);
                                           ccm_rx_work_expired()
                                             // on freed peer_mep

To prevent this, cancel_delayed_work_sync() is replaced with disable_delayed_work_sync() in both peer MEP deletion paths, so that subsequent queue_delayed_work() calls from br_cfm_frame_rx() are silently rejected.

The cc_peer_disable() helper retains cancel_delayed_work_sync() because it is also used for the CC enable/disable toggle path where the work must remain re-schedulable.

Fixes dc32cbb3dbd7 ("bridge: cfm: Kernel space implementation of CFM. CCM frame RX added.")
---
 net/bridge/br_cfm.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
net/bridge/br_cfm.c +2 -2
index c2c1c7d44c615..f4ca77d9b0e96 100644
@@ -576,7 +576,7 @@ static void mep_delete_implementation(struct net_bridge *br,
 
 	/* Empty and free peer MEP list */
 	hlist_for_each_entry_safe(peer_mep, n_store, &mep->peer_mep_list, head) {
-		cancel_delayed_work_sync(&peer_mep->ccm_rx_dwork);
+		disable_delayed_work_sync(&peer_mep->ccm_rx_dwork);
 		hlist_del_rcu(&peer_mep->head);
 		kfree_rcu(peer_mep, rcu);
 	}
@@ -732,7 +732,7 @@ int br_cfm_cc_peer_mep_remove(struct net_bridge *br, const u32 instance,
 		return -ENOENT;
 	}
 
-	cc_peer_disable(peer_mep);
+	disable_delayed_work_sync(&peer_mep->ccm_rx_dwork);
 
 	hlist_del_rcu(&peer_mep->head);
 	kfree_rcu(peer_mep, rcu);
Signature · 1 line
2.51.0
author maintainer
#129 lore raw

PATCH 129/220 net/rose: fix NULL pointer dereference in rose_transmit_link on reconnect

In reply to Greg Kroah-Hartman

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

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

From: Jiayuan Chen <[email protected]>

[ Upstream commit e1f0a18c9564cdb16523c802e2c6fe5874e3d944 ]

syzkaller reported a bug [1], and the reproducer is available at [2].

ROSE sockets use four sk->sk_state values: TCP_CLOSE, TCP_LISTEN, TCP_SYN_SENT, and TCP_ESTABLISHED. rose_connect() already rejects calls for TCP_ESTABLISHED (-EISCONN) and TCP_CLOSE with SS_CONNECTING (-ECONNREFUSED), but lacks a check for TCP_SYN_SENT.

When rose_connect() is called a second time while the first connection attempt is still in progress (TCP_SYN_SENT), it overwrites rose->neighbour via rose_get_neigh(). If that returns NULL, the socket is left with rose->state == ROSE_STATE_1 but rose->neighbour == NULL. When the socket is subsequently closed, rose_release() sees ROSE_STATE_1 and calls rose_write_internal() -> rose_transmit_link(skb, NULL), causing a NULL pointer dereference.

Per connect(2), a second connect() while a connection is already in progress should return -EALREADY. Add this missing check for TCP_SYN_SENT to complete the state validation in rose_connect().

[1] https://syzkaller.appspot.com/bug?extid=d00f90e0af54102fb271
[2] https://gist.github.com/mrpre/9e6779e0d13e2c66779b1653fef80516

---
 net/rose/af_rose.c | 5 +++++
 1 file changed, 5 insertions(+)
net/rose/af_rose.c +5 -0
index c0f5a515a8ce5..de18af4e40660 100644
@@ -811,6 +811,11 @@ static int rose_connect(struct socket *sock, struct sockaddr_unsized *uaddr, int
 		goto out_release;
 	}
 
+	if (sk->sk_state == TCP_SYN_SENT) {
+		err = -EALREADY;
+		goto out_release;
+	}
+
 	sk->sk_state   = TCP_CLOSE;
 	sock->state = SS_UNCONNECTED;
 
Signature · 1 line
2.51.0
author maintainer
#130 lore raw

PATCH 130/220 ip_tunnel: adapt iptunnel_xmit_stats() to NETDEV_PCPU_STAT_DSTATS

In reply to Greg Kroah-Hartman

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

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

From: Eric Dumazet <[email protected]>

[ Upstream commit 8431c602f551549f082bbfa67f3003f2d8e3e132 ]

Blamed commits forgot that vxlan/geneve use udp_tunnel[6]_xmit_skb() which call iptunnel_xmit_stats().

iptunnel_xmit_stats() was assuming tunnels were only using NETDEV_PCPU_STAT_TSTATS.

@syncp offset in pcpu_sw_netstats and pcpu_dstats is different.

32bit kernels would either have corruptions or freezes if the syncp sequence was overwritten.

This patch also moves pcpu_stat_type closer to dev->{t,d}stats to avoid a potential cache line miss since iptunnel_xmit_stats() needs to read it.

Fixes 6fa6de302246 ("geneve: Handle stats using NETDEV_PCPU_STAT_DSTATS.")
Fixes be226352e8dc ("vxlan: Handle stats using NETDEV_PCPU_STAT_DSTATS.")
---
 include/linux/netdevice.h |  3 +--
 include/net/ip_tunnels.h  | 30 +++++++++++++++++++++++-------
 2 files changed, 24 insertions(+), 9 deletions(-)
include/linux/netdevice.h +1 -2
index 65d85dc9c8f05..444e52eb8ed99 100644
@@ -2153,6 +2153,7 @@ struct net_device {
 	unsigned long		state;
 	unsigned int		flags;
 	unsigned short		hard_header_len;
+	enum netdev_stat_type	pcpu_stat_type:8;
 	netdev_features_t	features;
 	struct inet6_dev __rcu	*ip6_ptr;
 	__cacheline_group_end(net_device_read_txrx);
@@ -2401,8 +2402,6 @@ struct net_device {
 	void				*ml_priv;
 	enum netdev_ml_priv_type	ml_priv_type;
 
-	enum netdev_stat_type		pcpu_stat_type:8;
-
 #if IS_ENABLED(CONFIG_GARP)
 	struct garp_port __rcu	*garp_port;
 #endif
include/net/ip_tunnels.h +23 -7
index 80662f8120803..1f577a4f8ce9b 100644
@@ -665,13 +665,29 @@ static inline int iptunnel_pull_offloads(struct sk_buff *skb)
 static inline void iptunnel_xmit_stats(struct net_device *dev, int pkt_len)
 {
 	if (pkt_len > 0) {
-		struct pcpu_sw_netstats *tstats = get_cpu_ptr(dev->tstats);
-
-		u64_stats_update_begin(&tstats->syncp);
-		u64_stats_add(&tstats->tx_bytes, pkt_len);
-		u64_stats_inc(&tstats->tx_packets);
-		u64_stats_update_end(&tstats->syncp);
-		put_cpu_ptr(tstats);
+		if (dev->pcpu_stat_type == NETDEV_PCPU_STAT_DSTATS) {
+			struct pcpu_dstats *dstats = get_cpu_ptr(dev->dstats);
+
+			u64_stats_update_begin(&dstats->syncp);
+			u64_stats_add(&dstats->tx_bytes, pkt_len);
+			u64_stats_inc(&dstats->tx_packets);
+			u64_stats_update_end(&dstats->syncp);
+			put_cpu_ptr(dstats);
+			return;
+		}
+		if (dev->pcpu_stat_type == NETDEV_PCPU_STAT_TSTATS) {
+			struct pcpu_sw_netstats *tstats = get_cpu_ptr(dev->tstats);
+
+			u64_stats_update_begin(&tstats->syncp);
+			u64_stats_add(&tstats->tx_bytes, pkt_len);
+			u64_stats_inc(&tstats->tx_packets);
+			u64_stats_update_end(&tstats->syncp);
+			put_cpu_ptr(tstats);
+			return;
+		}
+		pr_err_once("iptunnel_xmit_stats pcpu_stat_type=%d\n",
+			    dev->pcpu_stat_type);
+		WARN_ON_ONCE(1);
 		return;
 	}
 
Signature · 1 line
2.51.0
author maintainer
#131 lore raw

PATCH 131/220 mpls: add missing unregister_netdevice_notifier to mpls_init

In reply to Greg Kroah-Hartman

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

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

From: Sabrina Dubroca <[email protected]>

[ Upstream commit 99600f79b28c83c68bae199a3d8e95049a758308 ]

If mpls_init() fails after registering mpls_dev_notifier, it never gets removed. Add the missing unregister_netdevice_notifier() call to the error handling path.

---
 net/mpls/af_mpls.c | 1 +
 1 file changed, 1 insertion(+)
net/mpls/af_mpls.c +1 -0
index 580aac112dd21..c57f10e2ef269 100644
@@ -2854,6 +2854,7 @@ static int __init mpls_init(void)
 	rtnl_af_unregister(&mpls_af_ops);
 out_unregister_dev_type:
 	dev_remove_pack(&mpls_packet_type);
+	unregister_netdevice_notifier(&mpls_dev_notifier);
 out_unregister_pernet:
 	unregister_pernet_subsys(&mpls_net_ops);
 	goto out;
Signature · 1 line
2.51.0
author maintainer
#132 lore raw

PATCH 132/220 netfilter: ctnetlink: fix use-after-free in ctnetlink_dump_exp_ct()

In reply to Greg Kroah-Hartman

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

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

From: Hyunwoo Kim <[email protected]>

[ Upstream commit 5cb81eeda909dbb2def209dd10636b51549a3f8a ]

ctnetlink_dump_exp_ct() stores a conntrack pointer in cb->data for the netlink dump callback ctnetlink_exp_ct_dump_table(), but drops the conntrack reference immediately after netlink_dump_start(). When the dump spans multiple rounds, the second recvmsg() triggers the dump callback which dereferences the now-freed conntrack via nfct_help(ct), leading to a use-after-free on ct->ext.

The bug is that the netlink_dump_control has no .start or .done callbacks to manage the conntrack reference across dump rounds. Other dump functions in the same file (e.g. ctnetlink_get_conntrack) properly use .start/.done callbacks for this purpose.

Fix this by adding .start and .done callbacks that hold and release the conntrack reference for the duration of the dump, and move the nfct_help() call after the cb->args[0] early-return check in the dump callback to avoid dereferencing ct->ext unnecessarily.

 BUG: KASAN: slab-use-after-free in ctnetlink_exp_ct_dump_table+0x4f/0x2e0
 Read of size 8 at addr ffff88810597ebf0 by task ctnetlink_poc/133

 CPU: 1 UID: 0 PID: 133 Comm: ctnetlink_poc Not tainted 7.0.0-rc2+ #3 PREEMPTLAZY
 Call Trace:
  <TASK>
  ctnetlink_exp_ct_dump_table+0x4f/0x2e0
  netlink_dump+0x333/0x880
  netlink_recvmsg+0x3e2/0x4b0
  ? aa_sk_perm+0x184/0x450
  sock_recvmsg+0xde/0xf0

 Allocated by task 133:
  kmem_cache_alloc_noprof+0x134/0x440
  __nf_conntrack_alloc+0xa8/0x2b0
  ctnetlink_create_conntrack+0xa1/0x900
  ctnetlink_new_conntrack+0x3cf/0x7d0
  nfnetlink_rcv_msg+0x48e/0x510
  netlink_rcv_skb+0xc9/0x1f0
  nfnetlink_rcv+0xdb/0x220
  netlink_unicast+0x3ec/0x590
  netlink_sendmsg+0x397/0x690
  __sys_sendmsg+0xf4/0x180

 Freed by task 0:
  slab_free_after_rcu_debug+0xad/0x1e0
  rcu_core+0x5c3/0x9c0
Fixes e844a928431f ("netfilter: ctnetlink: allow to dump expectation per master conntrack")
---
 net/netfilter/nf_conntrack_netlink.c | 26 +++++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)
net/netfilter/nf_conntrack_netlink.c +25 -1
index 3a04665adf992..f261dd48973fe 100644
@@ -3211,7 +3211,7 @@ ctnetlink_exp_ct_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
 {
 	struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
 	struct nf_conn *ct = cb->data;
-	struct nf_conn_help *help = nfct_help(ct);
+	struct nf_conn_help *help;
 	u_int8_t l3proto = nfmsg->nfgen_family;
 	unsigned long last_id = cb->args[1];
 	struct nf_conntrack_expect *exp;
@@ -3219,6 +3219,10 @@ ctnetlink_exp_ct_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
 	if (cb->args[0])
 		return 0;
 
+	help = nfct_help(ct);
+	if (!help)
+		return 0;
+
 	rcu_read_lock();
 
 restart:
@@ -3248,6 +3252,24 @@ ctnetlink_exp_ct_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
 	return skb->len;
 }
 
+static int ctnetlink_dump_exp_ct_start(struct netlink_callback *cb)
+{
+	struct nf_conn *ct = cb->data;
+
+	if (!refcount_inc_not_zero(&ct->ct_general.use))
+		return -ENOENT;
+	return 0;
+}
+
+static int ctnetlink_dump_exp_ct_done(struct netlink_callback *cb)
+{
+	struct nf_conn *ct = cb->data;
+
+	if (ct)
+		nf_ct_put(ct);
+	return 0;
+}
+
 static int ctnetlink_dump_exp_ct(struct net *net, struct sock *ctnl,
 				 struct sk_buff *skb,
 				 const struct nlmsghdr *nlh,
@@ -3263,6 +3285,8 @@ static int ctnetlink_dump_exp_ct(struct net *net, struct sock *ctnl,
 	struct nf_conntrack_zone zone;
 	struct netlink_dump_control c = {
 		.dump = ctnetlink_exp_ct_dump_table,
+		.start = ctnetlink_dump_exp_ct_start,
+		.done = ctnetlink_dump_exp_ct_done,
 	};
 
 	err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER,
Signature · 1 line
2.51.0
author maintainer
#133 lore raw

PATCH 133/220 netfilter: conntrack: add missing netlink policy validations

In reply to Greg Kroah-Hartman

6.19-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 f261dd48973fe..d9f33a6c807c8 100644
@@ -3488,7 +3488,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 7c6f7c9f73320..645d2c43ebf7a 100644
@@ -582,7 +582,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.51.0
author maintainer
#134 lore raw

PATCH 134/220 netfilter: nf_conntrack_sip: fix Content-Length u32 truncation in sip_help_tcp()

In reply to Greg Kroah-Hartman

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

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

From: Lukas Johannes Möller <[email protected]>

[ Upstream commit fbce58e719a17aa215c724473fd5baaa4a8dc57c ]

sip_help_tcp() parses the SIP Content-Length header with simple_strtoul(), which returns unsigned long, but stores the result in unsigned int clen. On 64-bit systems, values exceeding UINT_MAX are silently truncated before computing the SIP message boundary.

For example, Content-Length 4294967328 (2^32 + 32) is truncated to 32, causing the parser to miscalculate where the current message ends. The loop then treats trailing data in the TCP segment as a second SIP message and processes it through the SDP parser.

Fix this by changing clen to unsigned long to match the return type of simple_strtoul(), and reject Content-Length values that exceed the remaining TCP payload length.

Fixes f5b321bd37fb ("netfilter: nf_conntrack_sip: add TCP support")
---
 net/netfilter/nf_conntrack_sip.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
net/netfilter/nf_conntrack_sip.c +5 -1
index ca748f8dbff13..4ab5ef71d96db 100644
@@ -1534,11 +1534,12 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff,
 {
 	struct tcphdr *th, _tcph;
 	unsigned int dataoff, datalen;
-	unsigned int matchoff, matchlen, clen;
+	unsigned int matchoff, matchlen;
 	unsigned int msglen, origlen;
 	const char *dptr, *end;
 	s16 diff, tdiff = 0;
 	int ret = NF_ACCEPT;
+	unsigned long clen;
 	bool term;
 
 	if (ctinfo != IP_CT_ESTABLISHED &&
@@ -1573,6 +1574,9 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff,
 		if (dptr + matchoff == end)
 			break;
 
+		if (clen > datalen)
+			break;
+
 		term = false;
 		for (; end + strlen("\r\n\r\n") <= dptr + datalen; end++) {
 			if (end[0] == '\r' && end[1] == '\n' &&
Signature · 1 line
2.51.0
author maintainer
#135 lore raw

PATCH 135/220 netfilter: nf_flow_table_ip: reset mac header before vlan push

In reply to Greg Kroah-Hartman

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

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

From: Eric Woudstra <[email protected]>

[ Upstream commit a3aca98aec9a278ee56da4f8013bfa1dd1a1c298 ]

With double vlan tagged packets in the fastpath, getting the error:

skb_vlan_push got skb with skb->data not at mac header (offset 18)

Call skb_reset_mac_header() before calling skb_vlan_push().

Fixes c653d5a78f34 ("netfilter: flowtable: inline vlan encapsulation in xmit path")
---
 net/netfilter/nf_flow_table_ip.c | 1 +
 1 file changed, 1 insertion(+)
net/netfilter/nf_flow_table_ip.c +1 -0
index 78883343e5d68..458895e9e1f85 100644
@@ -576,6 +576,7 @@ static int nf_flow_encap_push(struct sk_buff *skb,
 		switch (tuple->encap[i].proto) {
 		case htons(ETH_P_8021Q):
 		case htons(ETH_P_8021AD):
+			skb_reset_mac_header(skb);
 			if (skb_vlan_push(skb, tuple->encap[i].proto,
 					  tuple->encap[i].id) < 0)
 				return -1;
Signature · 1 line
2.51.0
author maintainer
#136 lore raw

PATCH 136/220 netfilter: nf_conntrack_h323: fix OOB read in decode_int() CONS case

In reply to Greg Kroah-Hartman

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

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

From: Jenny Guanni Qu <[email protected]>

[ Upstream commit 1e3a3593162c96e8a8de48b1e14f60c3b57fca8a ]

In decode_int(), the CONS case calls get_bits(bs, 2) to read a length value, then calls get_uint(bs, len) without checking that len bytes remain in the buffer. The existing boundary check only validates the 2 bits for get_bits(), not the subsequent 1-4 bytes that get_uint() reads. This allows a malformed H.323/RAS packet to cause a 1-4 byte slab-out-of-bounds read.

Add a boundary check for len bytes after get_bits() and before get_uint().

Fixes 5e35941d9901 ("[NETFILTER]: Add H.323 conntrack/NAT helper")
---
 net/netfilter/nf_conntrack_h323_asn1.c | 2 ++
 1 file changed, 2 insertions(+)
net/netfilter/nf_conntrack_h323_asn1.c +2 -0
index 62aa22a078769..c972e9488e16f 100644
@@ -331,6 +331,8 @@ static int decode_int(struct bitstr *bs, const struct field_t *f,
 		if (nf_h323_error_boundary(bs, 0, 2))
 			return H323_ERROR_BOUND;
 		len = get_bits(bs, 2) + 1;
+		if (nf_h323_error_boundary(bs, len, 0))
+			return H323_ERROR_BOUND;
 		BYTE_ALIGN(bs);
 		if (base && (f->attr & DECODE)) {	/* timeToLive */
 			unsigned int v = get_uint(bs, len) + f->lb;
Signature · 1 line
2.51.0
author maintainer
#137 lore raw

PATCH 137/220 nf_tables: nft_dynset: fix possible stateful expression memleak in error path

In reply to Greg Kroah-Hartman

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

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

From: Pablo Neira Ayuso <[email protected]>

[ Upstream commit 0548a13b5a145b16e4da0628b5936baf35f51b43 ]

If cloning the second stateful expression in the element via GFP_ATOMIC fails, then the first stateful expression remains in place without being released.

  unreferenced object (percpu) 0x607b97e9cab8 (size 16):
    comm "softirq", pid 0, jiffies 4294931867 hex dump (first 16 bytes on cpu 3):
      00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 backtrace (crc 0):

       pcpu_alloc_noprof+0x453/0xd80
       nft_counter_clone+0x9c/0x190 [nf_tables]
       nft_expr_clone+0x8f/0x1b0 [nf_tables]
       nft_dynset_new+0x2cb/0x5f0 [nf_tables]
       nft_rhash_update+0x236/0x11c0 [nf_tables]
       nft_dynset_eval+0x11f/0x670 [nf_tables]
       nft_do_chain+0x253/0x1700 [nf_tables]
       nft_do_chain_ipv4+0x18d/0x270 [nf_tables]
       nf_hook_slow+0xaa/0x1e0
       ip_local_deliver+0x209/0x330
Fixes 563125a73ac3 ("netfilter: nftables: generalize set extension to support for several expressions")
---
 include/net/netfilter/nf_tables.h |  2 ++
 net/netfilter/nf_tables_api.c     |  4 ++--
 net/netfilter/nft_dynset.c        | 10 +++++++++-
 3 files changed, 13 insertions(+), 3 deletions(-)
include/net/netfilter/nf_tables.h +2 -0
index c18cffafc9696..4dc080f7f27c6 100644
@@ -875,6 +875,8 @@ struct nft_elem_priv *nft_set_elem_init(const struct nft_set *set,
 					u64 timeout, u64 expiration, gfp_t gfp);
 int nft_set_elem_expr_clone(const struct nft_ctx *ctx, struct nft_set *set,
 			    struct nft_expr *expr_array[]);
+void nft_set_elem_expr_destroy(const struct nft_ctx *ctx,
+			       struct nft_set_elem_expr *elem_expr);
 void nft_set_elem_destroy(const struct nft_set *set,
 			  const struct nft_elem_priv *elem_priv,
 			  bool destroy_expr);
net/netfilter/nf_tables_api.c +2 -2
index c9a76c760b17c..03321b800707c 100644
@@ -6744,8 +6744,8 @@ static void __nft_set_elem_expr_destroy(const struct nft_ctx *ctx,
 	}
 }
 
-static void nft_set_elem_expr_destroy(const struct nft_ctx *ctx,
-				      struct nft_set_elem_expr *elem_expr)
+void nft_set_elem_expr_destroy(const struct nft_ctx *ctx,
+			       struct nft_set_elem_expr *elem_expr)
 {
 	struct nft_expr *expr;
 	u32 size;
net/netfilter/nft_dynset.c +9 -1
index 7807d81296646..9123277be03ce 100644
@@ -30,18 +30,26 @@ static int nft_dynset_expr_setup(const struct nft_dynset *priv,
 				 const struct nft_set_ext *ext)
 {
 	struct nft_set_elem_expr *elem_expr = nft_set_ext_expr(ext);
+	struct nft_ctx ctx = {
+		.net	= read_pnet(&priv->set->net),
+		.family	= priv->set->table->family,
+	};
 	struct nft_expr *expr;
 	int i;
 
 	for (i = 0; i < priv->num_exprs; i++) {
 		expr = nft_setelem_expr_at(elem_expr, elem_expr->size);
 		if (nft_expr_clone(expr, priv->expr_array[i], GFP_ATOMIC) < 0)
-			return -1;
+			goto err_out;
 
 		elem_expr->size += priv->expr_array[i]->ops->size;
 	}
 
 	return 0;
+err_out:
+	nft_set_elem_expr_destroy(&ctx, elem_expr);
+
+	return -1;
 }
 
 struct nft_elem_priv *nft_dynset_new(struct nft_set *set,
Signature · 1 line
2.51.0
author maintainer
#138 lore raw

PATCH 138/220 netfilter: nft_ct: drop pending enqueued packets on removal

In reply to Greg Kroah-Hartman

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

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

From: Pablo Neira Ayuso <[email protected]>

[ Upstream commit 36eae0956f659e48d5366d9b083d9417f3263ddc ]

Packets sitting in nfqueue might hold a reference to:

- templates that specify the conntrack zone, because a percpu area is used and module removal is possible.
- conntrack timeout policies and helper, where object removal leave a stale reference.

Since these objects can just go away, drop enqueued packets to avoid stale reference to them.

If there is a need for finer grain removal, this logic can be revisited to make selective packet drop upon dependencies.

Fixes 7e0b2b57f01d ("netfilter: nft_ct: add ct timeout support")
---
 net/netfilter/nft_ct.c | 4 ++++
 1 file changed, 4 insertions(+)
net/netfilter/nft_ct.c +4 -0
index 6f2ae7cad7310..db1bf69f87750 100644
@@ -23,6 +23,7 @@
 #include <net/netfilter/nf_conntrack_l4proto.h>
 #include <net/netfilter/nf_conntrack_expect.h>
 #include <net/netfilter/nf_conntrack_seqadj.h>
+#include "nf_internals.h"
 
 struct nft_ct_helper_obj  {
 	struct nf_conntrack_helper *helper4;
@@ -543,6 +544,7 @@ static void __nft_ct_set_destroy(const struct nft_ctx *ctx, struct nft_ct *priv)
 #endif
 #ifdef CONFIG_NF_CONNTRACK_ZONES
 	case NFT_CT_ZONE:
+		nf_queue_nf_hook_drop(ctx->net);
 		mutex_lock(&nft_ct_pcpu_mutex);
 		if (--nft_ct_pcpu_template_refcnt == 0)
 			nft_ct_tmpl_put_pcpu();
@@ -1016,6 +1018,7 @@ static void nft_ct_timeout_obj_destroy(const struct nft_ctx *ctx,
 	struct nft_ct_timeout_obj *priv = nft_obj_data(obj);
 	struct nf_ct_timeout *timeout = priv->timeout;
 
+	nf_queue_nf_hook_drop(ctx->net);
 	nf_ct_untimeout(ctx->net, timeout);
 	nf_ct_netns_put(ctx->net, ctx->family);
 	kfree(priv->timeout);
@@ -1148,6 +1151,7 @@ static void nft_ct_helper_obj_destroy(const struct nft_ctx *ctx,
 {
 	struct nft_ct_helper_obj *priv = nft_obj_data(obj);
 
+	nf_queue_nf_hook_drop(ctx->net);
 	if (priv->helper4)
 		nf_conntrack_helper_put(priv->helper4);
 	if (priv->helper6)
Signature · 1 line
2.51.0
author maintainer
#139 lore raw

PATCH 139/220 netfilter: xt_CT: drop pending enqueued packets on template removal

In reply to Greg Kroah-Hartman

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

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

From: Pablo Neira Ayuso <[email protected]>

[ Upstream commit f62a218a946b19bb59abdd5361da85fa4606b96b ]

Templates refer to objects that can go away while packets are sitting in nfqueue refer to:

- helper, this can be an issue on module removal.
- timeout policy, nfnetlink_cttimeout might remove it.

The use of templates with zone and event cache filter are safe, since this just copies values.

Flush these enqueued packets in case the template rule gets removed.

Fixes 24de58f46516 ("netfilter: xt_CT: allow to attach timeout policy + glue code")
---
 net/netfilter/xt_CT.c | 4 ++++
 1 file changed, 4 insertions(+)
net/netfilter/xt_CT.c +4 -0
index 3ba94c34297cf..498f5871c84a0 100644
@@ -16,6 +16,7 @@
 #include <net/netfilter/nf_conntrack_ecache.h>
 #include <net/netfilter/nf_conntrack_timeout.h>
 #include <net/netfilter/nf_conntrack_zones.h>
+#include "nf_internals.h"
 
 static inline int xt_ct_target(struct sk_buff *skb, struct nf_conn *ct)
 {
@@ -283,6 +284,9 @@ static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par,
 	struct nf_conn_help *help;
 
 	if (ct) {
+		if (info->helper[0] || info->timeout[0])
+			nf_queue_nf_hook_drop(par->net);
+
 		help = nfct_help(ct);
 		xt_ct_put_helper(help);
 
Signature · 1 line
2.51.0
author maintainer
#140 lore raw

PATCH 140/220 netfilter: xt_time: use unsigned int for monthday bit shift

In reply to Greg Kroah-Hartman

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

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

From: Jenny Guanni Qu <[email protected]>

[ Upstream commit 00050ec08cecfda447e1209b388086d76addda3a ]

The monthday field can be up to 31, and shifting a signed integer 1 by 31 positions (1 << 31) is undefined behavior in C, as the result overflows a 32-bit signed int. Use 1U to ensure well-defined behavior for all valid monthday values.

Change the weekday shift to 1U as well for consistency.

---
 net/netfilter/xt_time.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
net/netfilter/xt_time.c +2 -2
index 6aa12d0f54e23..61de85e02a40f 100644
@@ -227,13 +227,13 @@ time_mt(const struct sk_buff *skb, struct xt_action_param *par)
 
 	localtime_2(&current_time, stamp);
 
-	if (!(info->weekdays_match & (1 << current_time.weekday)))
+	if (!(info->weekdays_match & (1U << current_time.weekday)))
 		return false;
 
 	/* Do not spend time computing monthday if all days match anyway */
 	if (info->monthdays_match != XT_TIME_ALL_MONTHDAYS) {
 		localtime_3(&current_time, stamp);
-		if (!(info->monthdays_match & (1 << current_time.monthday)))
+		if (!(info->monthdays_match & (1U << current_time.monthday)))
 			return false;
 	}
 
Signature · 1 line
2.51.0
author maintainer
#141 lore raw

PATCH 141/220 netfilter: nf_conntrack_h323: check for zero length in DecodeQ931()

In reply to Greg Kroah-Hartman

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

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

From: Jenny Guanni Qu <[email protected]>

[ Upstream commit f173d0f4c0f689173f8cdac79991043a4a89bf66 ]

In DecodeQ931(), the UserUserIE code path reads a 16-bit length from the packet, then decrements it by 1 to skip the protocol discriminator byte before passing it to DecodeH323_UserInformation(). If the encoded length is 0, the decrement wraps to -1, which is then passed as a large value to the decoder, leading to an out-of-bounds read.

Add a check to ensure len is positive after the decrement.

Fixes 5e35941d9901 ("[NETFILTER]: Add H.323 conntrack/NAT helper")
---
 net/netfilter/nf_conntrack_h323_asn1.c | 2 ++
 1 file changed, 2 insertions(+)
net/netfilter/nf_conntrack_h323_asn1.c +2 -0
index c972e9488e16f..7b1497ed97d26 100644
@@ -924,6 +924,8 @@ int DecodeQ931(unsigned char *buf, size_t sz, Q931 *q931)
 				break;
 			p++;
 			len--;
+			if (len <= 0)
+				break;
 			return DecodeH323_UserInformation(buf, p, len,
 							  &q931->UUIE);
 		}
Signature · 1 line
2.51.0
author maintainer
#142 lore raw

PATCH 142/220 crypto: ccp - Fix leaking the same page twice

In reply to Greg Kroah-Hartman

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

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

From: Guenter Roeck <[email protected]>

[ Upstream commit 5c52607c43c397b79a9852ce33fc61de58c3645c ]

Commit 551120148b67 ("crypto: ccp - Fix a case where SNP_SHUTDOWN is missed") fixed a case where SNP is left in INIT state if page reclaim fails. It removes the transition to the INIT state for this command and adjusts the page state management.

While doing this, it added a call to snp_leak_pages() after a call to snp_reclaim_pages() failed. Since snp_reclaim_pages() already calls snp_leak_pages() internally on the pages it fails to reclaim, calling it again leaks the exact same page twice.

Fix by removing the extra call to snp_leak_pages().

The problem was found by an experimental code review agent based on gemini-3.1-pro while reviewing backports into v6.18.y.

Assisted-by Gemini:gemini-3.1-pro
Fixes 551120148b67 ("crypto: ccp - Fix a case where SNP_SHUTDOWN is missed")
Cc Tycho Andersen (AMD) <[email protected]>
Cc Tom Lendacky <[email protected]>
---
 drivers/crypto/ccp/sev-dev.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
drivers/crypto/ccp/sev-dev.c +1 -3
index 0d90b5f6a4548..a554fe3de3fd2 100644
@@ -2408,10 +2408,8 @@ static int sev_ioctl_do_snp_platform_status(struct sev_issue_cmd *argp)
 		 * in Firmware state on failure. Use snp_reclaim_pages() to
 		 * transition either case back to Hypervisor-owned state.
 		 */
-		if (snp_reclaim_pages(__pa(data), 1, true)) {
-			snp_leak_pages(__page_to_pfn(status_page), 1);
+		if (snp_reclaim_pages(__pa(data), 1, true))
 			return -EFAULT;
-		}
 	}
 
 	if (ret)
Signature · 1 line
2.51.0
author maintainer
#143 lore raw

PATCH 143/220 net: bcmgenet: increase WoL poll timeout

In reply to Greg Kroah-Hartman

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

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

From: Justin Chen <[email protected]>

[ Upstream commit 6cfc3bc02b977f2fba5f7268e6504d1931a774f7 ]

Some systems require more than 5ms to get into WoL mode. Increase the timeout value to 50ms.

Fixes c51de7f3976b ("net: bcmgenet: add Wake-on-LAN support code")
---
 drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c +1 -1
index 8fb5512882980..96d5d4f7f51fe 100644
@@ -123,7 +123,7 @@ static int bcmgenet_poll_wol_status(struct bcmgenet_priv *priv)
 	while (!(bcmgenet_rbuf_readl(priv, RBUF_STATUS)
 		& RBUF_STATUS_WOL)) {
 		retries++;
-		if (retries > 5) {
+		if (retries > 50) {
 			netdev_crit(dev, "polling wol mode timeout\n");
 			return -ETIMEDOUT;
 		}
Signature · 1 line
2.51.0
author maintainer
#144 lore raw

PATCH 144/220 net: mana: fix use-after-free in mana_hwc_destroy_channel() by reordering teardown

In reply to Greg Kroah-Hartman

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

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

From: Dipayaan Roy <[email protected]>

[ Upstream commit fa103fc8f56954a60699a29215cb713448a39e87 ]

A potential race condition exists in mana_hwc_destroy_channel() where hwc->caller_ctx is freed before the HWC's Completion Queue (CQ) and Event Queue (EQ) are destroyed. This allows an in-flight CQ interrupt handler to dereference freed memory, leading to a use-after-free or NULL pointer dereference in mana_hwc_handle_resp().

mana_smc_teardown_hwc() signals the hardware to stop but does not synchronize against IRQ handlers already executing on other CPUs. The IRQ synchronization only happens in mana_hwc_destroy_cq() via mana_gd_destroy_eq() -> mana_gd_deregister_irq(). Since this runs after kfree(hwc->caller_ctx), a concurrent mana_hwc_rx_event_handler() can dereference freed caller_ctx (and rxq->msg_buf) in mana_hwc_handle_resp().

Fix this by reordering teardown to reverse-of-creation order: destroy the TX/RX work queues and CQ/EQ before freeing hwc->caller_ctx. This ensures all in-flight interrupt handlers complete before the memory they access is freed.

---
 drivers/net/ethernet/microsoft/mana/hw_channel.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/net/ethernet/microsoft/mana/hw_channel.c +3 -3
index aa4e2731e2ba7..840c6b8957c90 100644
@@ -814,9 +814,6 @@ void mana_hwc_destroy_channel(struct gdma_context *gc)
 		gc->max_num_cqs = 0;
 	}
 
-	kfree(hwc->caller_ctx);
-	hwc->caller_ctx = NULL;
-
 	if (hwc->txq)
 		mana_hwc_destroy_wq(hwc, hwc->txq);
 
@@ -826,6 +823,9 @@ void mana_hwc_destroy_channel(struct gdma_context *gc)
 	if (hwc->cq)
 		mana_hwc_destroy_cq(hwc->gdma_dev->gdma_context, hwc->cq);
 
+	kfree(hwc->caller_ctx);
+	hwc->caller_ctx = NULL;
+
 	mana_gd_free_res_map(&hwc->inflight_msg_res);
 
 	hwc->num_inflight_msg = 0;
Signature · 1 line
2.51.0
author maintainer
#145 lore raw

PATCH 145/220 net: ti: icssg-prueth: Fix memory leak in XDP_DROP for non-zero-copy mode

In reply to Greg Kroah-Hartman

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

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

From: Meghana Malladi <[email protected]>

[ Upstream commit 719d3e71691db7c4f1658ba5a6d1472928121594 ]

Page recycling was removed from the XDP_DROP path in emac_run_xdp() to avoid conflicts with AF_XDP zero-copy mode, which uses xsk_buff_free() instead.

However, this causes a memory leak when running XDP programs that drop packets in non-zero-copy mode (standard page pool mode). The pages are never returned to the page pool, leading to OOM conditions.

Fix this by handling cleanup in the caller, emac_rx_packet(). When emac_run_xdp() returns ICSSG_XDP_CONSUMED for XDP_DROP, the caller now recycles the page back to the page pool. The zero-copy path, emac_rx_packet_zc() already handles cleanup correctly with xsk_buff_free().

Fixes 7a64bb388df3 ("net: ti: icssg-prueth: Add AF_XDP zero copy for RX")
---
 drivers/net/ethernet/ti/icssg/icssg_common.c | 5 +++++
 1 file changed, 5 insertions(+)
drivers/net/ethernet/ti/icssg/icssg_common.c +5 -0
index 090aa74d3ce72..a9b5f86bc71bc 100644
@@ -1075,6 +1075,11 @@ static int emac_rx_packet(struct prueth_emac *emac, u32 flow_id, u32 *xdp_state)
 		xdp_prepare_buff(&xdp, pa, PRUETH_HEADROOM, pkt_len, false);
 
 		*xdp_state = emac_run_xdp(emac, &xdp, &pkt_len);
+		if (*xdp_state == ICSSG_XDP_CONSUMED) {
+			page_pool_recycle_direct(pool, page);
+			goto requeue;
+		}
+
 		if (*xdp_state != ICSSG_XDP_PASS)
 			goto requeue;
 		headroom = xdp.data - xdp.data_hard_start;
Signature · 1 line
2.51.0
author maintainer
#146 lore raw

PATCH 146/220 sched: idle: Consolidate the handling of two special cases

In reply to Greg Kroah-Hartman

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

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

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

[ Upstream commit f4c31b07b136839e0fb3026f8a5b6543e3b14d2f ]

There are two special cases in the idle loop that are handled inconsistently even though they are analogous.

The first one is when a cpuidle driver is absent and the default CPU idle time power management implemented by the architecture code is used. In that case, the scheduler tick is stopped every time before invoking default_idle_call().

The second one is when a cpuidle driver is present, but there is only one idle state in its table. In that case, the scheduler tick is never stopped at all.

Since each of these approaches has its drawbacks, reconcile them with the help of one simple heuristic. Namely, stop the tick if the CPU has been woken up by it in the previous iteration of the idle loop, or let it tick otherwise.

Fixes ed98c3491998 ("sched: idle: Do not stop the tick before cpuidle_idle_call()")
[ rjw: Added Fixes tag, changelog edits ]
---
 kernel/sched/idle.c | 30 +++++++++++++++++++++---------
 1 file changed, 21 insertions(+), 9 deletions(-)
kernel/sched/idle.c +21 -9
index 69c70d509e1cf..8e00d95fb3388 100644
@@ -161,6 +161,14 @@ static int call_cpuidle(struct cpuidle_driver *drv, struct cpuidle_device *dev,
 	return cpuidle_enter(drv, dev, next_state);
 }
 
+static void idle_call_stop_or_retain_tick(bool stop_tick)
+{
+	if (stop_tick || tick_nohz_tick_stopped())
+		tick_nohz_idle_stop_tick();
+	else
+		tick_nohz_idle_retain_tick();
+}
+
 /**
  * cpuidle_idle_call - the main idle function
  *
@@ -170,7 +178,7 @@ static int call_cpuidle(struct cpuidle_driver *drv, struct cpuidle_device *dev,
  * set, and it returns with polling set.  If it ever stops polling, it
  * must clear the polling bit.
  */
-static void cpuidle_idle_call(void)
+static void cpuidle_idle_call(bool stop_tick)
 {
 	struct cpuidle_device *dev = cpuidle_get_device();
 	struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
@@ -186,7 +194,7 @@ static void cpuidle_idle_call(void)
 	}
 
 	if (cpuidle_not_available(drv, dev)) {
-		tick_nohz_idle_stop_tick();
+		idle_call_stop_or_retain_tick(stop_tick);
 
 		default_idle_call();
 		goto exit_idle;
@@ -222,17 +230,19 @@ static void cpuidle_idle_call(void)
 		next_state = cpuidle_find_deepest_state(drv, dev, max_latency_ns);
 		call_cpuidle(drv, dev, next_state);
 	} else if (drv->state_count > 1) {
-		bool stop_tick = true;
+		/*
+		 * stop_tick is expected to be true by default by cpuidle
+		 * governors, which allows them to select idle states with
+		 * target residency above the tick period length.
+		 */
+		stop_tick = true;
 
 		/*
 		 * Ask the cpuidle framework to choose a convenient idle state.
 		 */
 		next_state = cpuidle_select(drv, dev, &stop_tick);
 
-		if (stop_tick || tick_nohz_tick_stopped())
-			tick_nohz_idle_stop_tick();
-		else
-			tick_nohz_idle_retain_tick();
+		idle_call_stop_or_retain_tick(stop_tick);
 
 		entered_state = call_cpuidle(drv, dev, next_state);
 		/*
@@ -240,7 +250,7 @@ static void cpuidle_idle_call(void)
 		 */
 		cpuidle_reflect(dev, entered_state);
 	} else {
-		tick_nohz_idle_retain_tick();
+		idle_call_stop_or_retain_tick(stop_tick);
 
 		/*
 		 * If there is only a single idle state (or none), there is
@@ -268,6 +278,7 @@ static void cpuidle_idle_call(void)
 static void do_idle(void)
 {
 	int cpu = smp_processor_id();
+	bool got_tick = false;
 
 	/*
 	 * Check if we need to update blocked load
@@ -338,8 +349,9 @@ static void do_idle(void)
 			tick_nohz_idle_restart_tick();
 			cpu_idle_poll();
 		} else {
-			cpuidle_idle_call();
+			cpuidle_idle_call(got_tick);
 		}
+		got_tick = tick_nohz_idle_got_tick();
 		arch_cpu_idle_exit();
 	}
 
Signature · 1 line
2.51.0
author maintainer
#147 lore raw

PATCH 147/220 PM: runtime: Fix a race condition related to device removal

In reply to Greg Kroah-Hartman

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

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

From: Bart Van Assche <[email protected]>

[ Upstream commit 29ab768277617452d88c0607c9299cdc63b6e9ff ]

The following code in pm_runtime_work() may dereference the dev->parent pointer after the parent device has been freed:

	/* Maybe the parent is now able to suspend. */
	if (parent && !parent->power.ignore_children) {
		spin_unlock(&dev->power.lock);

		spin_lock(&parent->power.lock);
		rpm_idle(parent, RPM_ASYNC);
		spin_unlock(&parent->power.lock);

		spin_lock(&dev->power.lock);
	}

Fix this by inserting a flush_work() call in pm_runtime_remove().

Without this patch blktest block/001 triggers the following complaint sporadically:

BUG: KASAN: slab-use-after-free in lock_acquire+0x70/0x160
Read of size 1 at addr ffff88812bef7198 by task kworker/u553:1/3081
Workqueue: pm pm_runtime_work
Call Trace:
 <TASK>
 dump_stack_lvl+0x61/0x80
 print_address_description.constprop.0+0x8b/0x310
 print_report+0xfd/0x1d7
 kasan_report+0xd8/0x1d0
 __kasan_check_byte+0x42/0x60
 lock_acquire.part.0+0x38/0x230
 lock_acquire+0x70/0x160
 _raw_spin_lock+0x36/0x50
 rpm_suspend+0xc6a/0xfe0
 rpm_idle+0x578/0x770
 pm_runtime_work+0xee/0x120
 process_one_work+0xde3/0x1410
 worker_thread+0x5eb/0xfe0
 kthread+0x37b/0x480
 ret_from_fork+0x6cb/0x920
 ret_from_fork_asm+0x11/0x20
 </TASK>

Allocated by task 4314:
 kasan_save_stack+0x2a/0x50
 kasan_save_track+0x18/0x40
 kasan_save_alloc_info+0x3d/0x50
 __kasan_kmalloc+0xa0/0xb0
 __kmalloc_noprof+0x311/0x990
 scsi_alloc_target+0x122/0xb60 [scsi_mod]
 __scsi_scan_target+0x101/0x460 [scsi_mod]
 scsi_scan_channel+0x179/0x1c0 [scsi_mod]
 scsi_scan_host_selected+0x259/0x2d0 [scsi_mod]
 store_scan+0x2d2/0x390 [scsi_mod]
 dev_attr_store+0x43/0x80
 sysfs_kf_write+0xde/0x140
 kernfs_fop_write_iter+0x3ef/0x670
 vfs_write+0x506/0x1470
 ksys_write+0xfd/0x230
 __x64_sys_write+0x76/0xc0
 x64_sys_call+0x213/0x1810
 do_syscall_64+0xee/0xfc0
 entry_SYSCALL_64_after_hwframe+0x4b/0x53

Freed by task 4314:
 kasan_save_stack+0x2a/0x50
 kasan_save_track+0x18/0x40
 kasan_save_free_info+0x3f/0x50
 __kasan_slab_free+0x67/0x80
 kfree+0x225/0x6c0
 scsi_target_dev_release+0x3d/0x60 [scsi_mod]
 device_release+0xa3/0x220
 kobject_cleanup+0x105/0x3a0
 kobject_put+0x72/0xd0
 put_device+0x17/0x20
 scsi_device_dev_release+0xacf/0x12c0 [scsi_mod]
 device_release+0xa3/0x220
 kobject_cleanup+0x105/0x3a0
 kobject_put+0x72/0xd0
 put_device+0x17/0x20
 scsi_device_put+0x7f/0xc0 [scsi_mod]
 sdev_store_delete+0xa5/0x120 [scsi_mod]
 dev_attr_store+0x43/0x80
 sysfs_kf_write+0xde/0x140
 kernfs_fop_write_iter+0x3ef/0x670
 vfs_write+0x506/0x1470
 ksys_write+0xfd/0x230
 __x64_sys_write+0x76/0xc0
 x64_sys_call+0x213/0x1810
---
 drivers/base/power/runtime.c | 1 +
 1 file changed, 1 insertion(+)
drivers/base/power/runtime.c +1 -0
index 0ee8ea971aa46..335288e8b5b31 100644
@@ -1895,6 +1895,7 @@ void pm_runtime_reinit(struct device *dev)
 void pm_runtime_remove(struct device *dev)
 {
 	__pm_runtime_disable(dev, false);
+	flush_work(&dev->power.work);
 	pm_runtime_reinit(dev);
 }
 
Signature · 1 line
2.51.0
author maintainer
#148 lore raw

PATCH 148/220 bonding: prevent potential infinite loop in bond_header_parse()

In reply to Greg Kroah-Hartman

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

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

From: Eric Dumazet <[email protected]>

[ Upstream commit b7405dcf7385445e10821777143f18c3ce20fa04 ]

bond_header_parse() can loop if a stack of two bonding devices is setup, because skb->dev always points to the hierarchy top.

Add new "const struct net_device *dev" parameter to (struct header_ops)->parse() method to make sure the recursion is bounded, and that the final leaf parse method is called.

Fixes 950803f72547 ("bonding: fix type confusion in bond_setup_by_slave()")
Cc Jay Vosburgh <[email protected]>
Cc Andrew Lunn <[email protected]>
---
 drivers/firewire/net.c          | 5 +++--
 drivers/net/bonding/bond_main.c | 8 +++++---
 include/linux/etherdevice.h     | 3 ++-
 include/linux/if_ether.h        | 3 ++-
 include/linux/netdevice.h       | 6 ++++--
 net/ethernet/eth.c              | 9 +++------
 net/ipv4/ip_gre.c               | 3 ++-
 net/mac802154/iface.c           | 4 +++-
 net/phonet/af_phonet.c          | 5 ++++-
 9 files changed, 28 insertions(+), 18 deletions(-)
drivers/firewire/net.c +3 -2
index 6d64467135395..e829454089550 100644
@@ -257,9 +257,10 @@ static void fwnet_header_cache_update(struct hh_cache *hh,
 	memcpy((u8 *)hh->hh_data + HH_DATA_OFF(FWNET_HLEN), haddr, net->addr_len);
 }
 
-static int fwnet_header_parse(const struct sk_buff *skb, unsigned char *haddr)
+static int fwnet_header_parse(const struct sk_buff *skb, const struct net_device *dev,
+			      unsigned char *haddr)
 {
-	memcpy(haddr, skb->dev->dev_addr, FWNET_ALEN);
+	memcpy(haddr, dev->dev_addr, FWNET_ALEN);
 
 	return FWNET_ALEN;
 }
drivers/net/bonding/bond_main.c +5 -3
index e8e261e0cb4e1..106cfe732a15e 100644
@@ -1497,9 +1497,11 @@ static int bond_header_create(struct sk_buff *skb, struct net_device *bond_dev,
 	return ret;
 }
 
-static int bond_header_parse(const struct sk_buff *skb, unsigned char *haddr)
+static int bond_header_parse(const struct sk_buff *skb,
+			     const struct net_device *dev,
+			     unsigned char *haddr)
 {
-	struct bonding *bond = netdev_priv(skb->dev);
+	struct bonding *bond = netdev_priv(dev);
 	const struct header_ops *slave_ops;
 	struct slave *slave;
 	int ret = 0;
@@ -1509,7 +1511,7 @@ static int bond_header_parse(const struct sk_buff *skb, unsigned char *haddr)
 	if (slave) {
 		slave_ops = READ_ONCE(slave->dev->header_ops);
 		if (slave_ops && slave_ops->parse)
-			ret = slave_ops->parse(skb, haddr);
+			ret = slave_ops->parse(skb, slave->dev, haddr);
 	}
 	rcu_read_unlock();
 	return ret;
include/linux/etherdevice.h +2 -1
index 9a1eacf35d370..df8f88f63a706 100644
@@ -42,7 +42,8 @@ extern const struct header_ops eth_header_ops;
 
 int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
 	       const void *daddr, const void *saddr, unsigned len);
-int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr);
+int eth_header_parse(const struct sk_buff *skb, const struct net_device *dev,
+		     unsigned char *haddr);
 int eth_header_cache(const struct neighbour *neigh, struct hh_cache *hh,
 		     __be16 type);
 void eth_header_cache_update(struct hh_cache *hh, const struct net_device *dev,
include/linux/if_ether.h +2 -1
index 61b7335aa037c..ca9afa824aa4f 100644
@@ -40,7 +40,8 @@ static inline struct ethhdr *inner_eth_hdr(const struct sk_buff *skb)
 	return (struct ethhdr *)skb_inner_mac_header(skb);
 }
 
-int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr);
+int eth_header_parse(const struct sk_buff *skb, const struct net_device *dev,
+		     unsigned char *haddr);
 
 extern ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len);
 
include/linux/netdevice.h +4 -2
index 444e52eb8ed99..1216f050f0699 100644
@@ -311,7 +311,9 @@ struct header_ops {
 	int	(*create) (struct sk_buff *skb, struct net_device *dev,
 			   unsigned short type, const void *daddr,
 			   const void *saddr, unsigned int len);
-	int	(*parse)(const struct sk_buff *skb, unsigned char *haddr);
+	int	(*parse)(const struct sk_buff *skb,
+			 const struct net_device *dev,
+			 unsigned char *haddr);
 	int	(*cache)(const struct neighbour *neigh, struct hh_cache *hh, __be16 type);
 	void	(*cache_update)(struct hh_cache *hh,
 				const struct net_device *dev,
@@ -3442,7 +3444,7 @@ static inline int dev_parse_header(const struct sk_buff *skb,
 
 	if (!dev->header_ops || !dev->header_ops->parse)
 		return 0;
-	return dev->header_ops->parse(skb, haddr);
+	return dev->header_ops->parse(skb, dev, haddr);
 }
 
 static inline __be16 dev_parse_header_protocol(const struct sk_buff *skb)
net/ethernet/eth.c +3 -6
index 13a63b48b7eeb..d9faadbe9b6c8 100644
@@ -193,14 +193,11 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
 }
 EXPORT_SYMBOL(eth_type_trans);
 
-/**
- * eth_header_parse - extract hardware address from packet
- * @skb: packet to extract header from
- * @haddr: destination buffer
- */
-int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr)
+int eth_header_parse(const struct sk_buff *skb, const struct net_device *dev,
+		     unsigned char *haddr)
 {
 	const struct ethhdr *eth = eth_hdr(skb);
+
 	memcpy(haddr, eth->h_source, ETH_ALEN);
 	return ETH_ALEN;
 }
net/ipv4/ip_gre.c +2 -1
index e13244729ad8d..35f0baa99d409 100644
@@ -919,7 +919,8 @@ static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
 	return -(t->hlen + sizeof(*iph));
 }
 
-static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
+static int ipgre_header_parse(const struct sk_buff *skb, const struct net_device *dev,
+			      unsigned char *haddr)
 {
 	const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb);
 	memcpy(haddr, &iph->saddr, 4);
net/mac802154/iface.c +3 -1
index 9e4631fade90c..000be60d95803 100644
@@ -469,7 +469,9 @@ static int mac802154_header_create(struct sk_buff *skb,
 }
 
 static int
-mac802154_header_parse(const struct sk_buff *skb, unsigned char *haddr)
+mac802154_header_parse(const struct sk_buff *skb,
+		       const struct net_device *dev,
+		       unsigned char *haddr)
 {
 	struct ieee802154_hdr hdr;
 
net/phonet/af_phonet.c +4 -1
index 238a9638d2b0f..d89225d6bfd3b 100644
@@ -129,9 +129,12 @@ static int pn_header_create(struct sk_buff *skb, struct net_device *dev,
 	return 1;
 }
 
-static int pn_header_parse(const struct sk_buff *skb, unsigned char *haddr)
+static int pn_header_parse(const struct sk_buff *skb,
+			   const struct net_device *dev,
+			   unsigned char *haddr)
 {
 	const u8 *media = skb_mac_header(skb);
+
 	*haddr = *media;
 	return 1;
 }
Signature · 1 line
2.51.0