6.18.50-rc1 review
Subsystems (5)
Greg Kroah-Hartman
maintainercover 6.18.50-rc1 review
This is the start of the stable review cycle for the 6.18.50 release. There are 552 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 Sun, 06 Sep 2026 04:56:59 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.18.50-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.18.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 6.18.50-rc1
Tzung-Bi Shih <[email protected]>
platform/chrome: sensorhub: Fix dropped timestamp events and log spam
Injae Ryou <[email protected]>
selftests/mm: fix on-fault-limit false failure under sudo-rs
Zhan Xusheng <[email protected]>
udf: Fix i_lenExtents truncation on 32-bit kernels
Thomas Gleixner <[email protected]>
timer: Keep debugobjects state consistent in migrate_timer_list()
Thomas Weißschuh (Schneider Electric) <[email protected]>
timekeeping: Check the return value of tk_get_aux_ts64 in __do_adjtimex()
Bradley Morgan <[email protected]>
taskstats: fix cpumask parsing cutting off the last character
Jann Horn <[email protected]>
smack: fix cred UAF in smack_file_send_sigiotask()
Bradley Morgan <[email protected]>
signal: avoid shared siginfo namespace rewrites
Helge Deller <[email protected]>
sticon/parisc: Detect default STI graphics card for console output
Oleg Nesterov <[email protected]>
sysctl: move the "cad_pid" entry from pid_table[] to kern_reboot_table[]
Myeonghun Pak <[email protected]>
tpm: tpm_i2c_nuvoton: disable IRQ on wait timeout
Xu Rao <[email protected]>
zloop: truncate finished zones to zone capacity
Zi Yan <[email protected]>
xarray: honor XA_FLAGS_ACCOUNT in xas_split_alloc()
Maoyi Xie <[email protected]>
w1: ds28e17: reject an oversize length on an I2C block read
Chengfeng Ye <[email protected]>
vsock/virtio: flush works in dependency order
Laxman Acharya Padhya <[email protected]>
wifi: mt76: mt7996: validate default EEPROM firmware size
Felix Fietkau <[email protected]>
wifi: mt76: mt7996: fix TX DMA mapping leak for AddBA req frames
Devin Wittmayer <[email protected]>
wifi: mt76: mt7925: cancel mlo_pm_work on stop
Bryam Vargas <[email protected]>
wifi: mt76: mt7915: bound the device EEPROM address before the EFUSE copy
Runyu Xiao <[email protected]>
wifi: mt76: mt7615: avoid waiting for mac work under the mt76 mutex
Dawei Feng <[email protected]>
wifi: rtw88: pci: fix resource leak on failed NAPI setup
Abdun Nihaal <[email protected]>
wifi: rtw88: Fix potential memory leak in rtw_txq_push_skb()
Abdun Nihaal <[email protected]>
wifi: rtlwifi: rtl8192du: Fix possible memory leak in rtl92du_init_sw_vars()
Runyu Xiao <[email protected]>
wifi: rtlwifi: rtl8192du: check QoS TID before indexing tids
Stanislaw Gruszka <[email protected]>
wifi: rtl818x: initialize eeprom_93cx6 struct to zero
Fabio Estevam <[email protected]>
wifi: mwifiex: Detach sync cmd buffer on interrupted wait
Eric Biggers <[email protected]>
crypto: sun8i-ss - Remove crypto_rng interface
Eric Biggers <[email protected]>
crypto: sun8i-ce - Remove crypto_rng interface
Fan Wu <[email protected]>
wifi: rtl8xxxu: fix use-after-free from rx_urb_wq on stop
Dawei Feng <[email protected]>
wifi: iwlwifi: dvm: fix memory leak in iwl_op_mode_dvm_start()
Abdun Nihaal <[email protected]>
wifi: brcmfmac: Fix memory leak in brcmf_sdio_read_control()
Claudiu Beznea <[email protected]>
i3c: renesas: Reconfigure the DATBAS register on re-attach
Claudiu Beznea <[email protected]>
i3c: renesas: Clean DATBAS register on detach
Claudiu Beznea <[email protected]>
i3c: renesas: Check that the transfer is valid before accessing it
Adrian Hunter <[email protected]>
i3c: master: Fix potential UAF in i3c_device_uevent()
Maoyi Xie <[email protected]>
i3c: master: svc: bound IBI payload to the requested max_payload_len
Adrian Hunter <[email protected]>
i3c: master: Fix info leak and UAF in device unregister path
Runyu Xiao <[email protected]>
i3c: master: adi: initialize the lock before enabling interrupts
Jianyun Gao <[email protected]>
dm-pcache: fix use-after-free and invalid seg operations in kset_replay()
Jianyun Gao <[email protected]>
dm-pcache: fix implicit u8 truncation of gc_percent in message handler
Bryam Vargas <[email protected]>
dm-pcache: only hand out initialized cache segments
Bryam Vargas <[email protected]>
dm-pcache: detect a cycle in the last-kset chain during replay
Bryam Vargas <[email protected]>
dm-pcache: clamp the tail kset read to the segment data region
Bryam Vargas <[email protected]>
dm-pcache: bound the persisted tail-position offset
Bryam Vargas <[email protected]>
dm-pcache: validate on-media seg_num against the cache device size
Bryam Vargas <[email protected]>
dm-pcache: validate kset key_num and intra-segment bounds
Bryam Vargas <[email protected]>
dm-pcache: validate geometry fields from on-disk cache_info
Haotian Zhang <[email protected]>
dm-switch: use WRITE_ONCE() in switch_region_table_write()
Mikulas Patocka <[email protected]>
dm-stats: fix a crash if allocation of per-cpu data fails
Nathan Chancellor <[email protected]>
arch_numa: avoid false positive fortify warning in setup_node_to_cpumask_map()
Yehyeong Lee <[email protected]>
net/smc: carry oversized SMC-Rv2 LLC messages in the queue entry
Miguel Ojeda <[email protected]>
rust: rust_is_available: warn for `bindgen` < 0.72.1 && libclang >= 22
Ralf Lici <[email protected]>
ovpn: run deferred work on a module-owned workqueue
Vincent Donnefort <[email protected]>
ring-buffer: Fix subbuf resize race with ring buffer readers
Zhang Heng <[email protected]>
ALSA: hda/realtek: Fix Lenovo Yoga Slim 7 14AKP10 quirk ordering
Denis Batishchev <[email protected]>
ALSA: hda/realtek: Enable micmute LED on HP EliteBook 6 G1a p/n: AD3Q9ET#UUG
Eckhart Mohr <[email protected]>
ALSA: hda/realtek: Add quirk for TongFang XxAF5xxx
Takashi Iwai <[email protected]>
ALSA: virmidi: Check card index validity at probe
Takashi Iwai <[email protected]>
ALSA: serial-u16550: Check card index validity at probe
Takashi Iwai <[email protected]>
ALSA: portman2x4: Check card index validity at probe
Runyu Xiao <[email protected]>
ALSA: pcxhr: initialize mutexes before requesting threaded IRQ
Takashi Iwai <[email protected]>
ALSA: mts64: Check card index validity at probe
Takashi Iwai <[email protected]>
ALSA: mpu401: Check card index validity at probe
Xu Rao <[email protected]>
ALSA: hda/ext: preserve PPLCCTL bits when clearing reset
Baul Lee <[email protected]>
ALSA: bcd2000: clear the URB pointers on disconnect
Takashi Iwai <[email protected]>
ALSA: aloop: Check card index validity at probe
Baul Lee <[email protected]>
ALSA: 6fire: bound the MIDI event length from the device
Abdun Nihaal <[email protected]>
mfd: sm501: Fix potential memory leaks during remove
Thomas Richard <[email protected]>
mfd: cgbc: Fix teardown ordering in cgbc_remove()
Can Peng <[email protected]>
hwrng: stm32 - Fix runtime PM cleanup on registration failure
Zhiling Zou <[email protected]>
seg6: reset IP6CB after IPv6 decapsulation
Norbert Szetei <[email protected]>
net: skbuff: don't touch shared zerocopy state in skb_tx_error()
Breno Leitao <[email protected]>
net: fix spurious TX timeout after dev_activate()
Zhiling Zou <[email protected]>
net: cap advertised IP tunnel headroom
Bryam Vargas <[email protected]>
net/smc: unregister the connection before draining the rx tasklet
Hidayath Khan <[email protected]>
net/smc: stop killed, freed and out_of_sync sharing a byte
Yehyeong Lee <[email protected]>
net/smc: fix use-after-free of the LLC qentry in smc_llc_srv_add_link()
Hidayath Khan <[email protected]>
net/smc: fix use-after-free in smc_rx_pipe_buf_release()
Hidayath Khan <[email protected]>
net/smc: fix socket refcount leak in smc_switch_conns()
Bryam Vargas <[email protected]>
net/smc: do not dereference an unset send buffer on the SMC-D teardown path
Yehyeong Lee <[email protected]>
net/smc: bound the peer rkey counts in SMC-Rv2 LLC messages
Koichiro Den <[email protected]>
net: ntb_netdev: Count packets dropped on RX refill failure
Koichiro Den <[email protected]>
net: ntb_netdev: Avoid double-accounting netif_rx() drops
Koichiro Den <[email protected]>
net: ntb_netdev: Fix TX busy and drop handling
Koichiro Den <[email protected]>
NTB: ntb_transport: Reject oversized TX buffers
Koichiro Den <[email protected]>
NTB: ntb_transport: Fail TX enqueue when the QP link is down
Koichiro Den <[email protected]>
NTB: ntb_transport: Recycle TX entries before client callbacks
Fan Ye <[email protected]>
net: thunderbolt: Mark the connection down when bringing it up fails
Fan Ye <[email protected]>
net: thunderbolt: Release the Rx HopID that was handed out on mismatch
Xuanqiang Luo <[email protected]>
net: ravb: serialize PTP clock teardown
Xuanqiang Luo <[email protected]>
net: ravb: avoid dereferencing an invalid PTP clock
Christian Marangi <[email protected]>
net: phylink: correctly validate returned PCS in phylink_inband_caps
Ruoyu Wang <[email protected]>
net: openvswitch: fix nf_connlabels leak in ovs_ct_init
Ilya Maximets <[email protected]>
net: openvswitch: fix flow mask use-after-free on flow deletion
Zihan Xi <[email protected]>
net: l2tp: do not propagate multicast notification errors
Jorijn van der Graaf <[email protected]>
net: ipa: fix stalled modem TX queue after runtime resume
Runyu Xiao <[email protected]>
net: ibm: emac: mal: fix NAPI locking
Ahmad Fatoum <[email protected]>
net: dsa: realtek: use gpiod_set_value_cansleep for reset GPIO
Asim Viladi Oglu Manizada <[email protected]>
net: tun: bound receive headroom
Fabio Porcedda <[email protected]>
net: usb: qmi_wwan: add Telit Cinterion FE990D50 composition
Aleksandr Khromov <[email protected]>
slip: fix use-after-free in sl_sync()
Weiming Shi <[email protected]>
xdp: fix zero-copy frame layout
Alexandra Winter <[email protected]>
net/iucv: filter frames in afiucv_hs_rcv() by ingress device
Corey Minyard <[email protected]>
ipmi:msghandler: Cancel work cleanly on an error
Seiji Nishikawa <[email protected]>
ipmi: si: Fix NULL pointer dereference after failed registration
Yuho Choi <[email protected]>
ipmi: Remove all sysfs files on registration failure
Yousef Alhouseen <[email protected]>
ipmi: ipmb: validate write message length
Kuan-Wei Chiu <[email protected]>
interconnect: Fix use after free in icc_get() and of_icc_get_by_index()
Laxman Acharya Padhya <[email protected]>
io_uring/query: cap user size passed to copy_struct_to_user
Muhammad Bilal <[email protected]>
platform/x86: hp-bioscfg: warn on element type mismatch instead of failing
Muhammad Bilal <[email protected]>
platform/x86: hp-bioscfg: pass validated element count to package parsers
Muhammad Bilal <[email protected]>
platform/x86: hp-bioscfg: fix ORD_LIST_ELEMENTS never being parsed
Muhammad Bilal <[email protected]>
platform/x86: hp-bioscfg: fix off-by-one write in hp_get_string_from_buffer()
Muhammad Bilal <[email protected]>
platform/x86: hp-bioscfg: fix new_password_store() overwriting current_password
Muhammad Bilal <[email protected]>
platform/x86: hp-bioscfg: fix heap OOB read on empty password write
Muhammad Bilal <[email protected]>
platform/x86: hp-bioscfg: fix heap OOB read in sk_store() and kek_store()
Muhammad Bilal <[email protected]>
platform/x86: hp-bioscfg: bound ordered-list parsing by the package count
Muhammad Bilal <[email protected]>
platform/x86: hp-bioscfg: advance elem past consumed array elements
Muhammad Bilal <[email protected]>
platform/x86: hp-bioscfg: accept reduced ACPI packages from older HP BIOS
Mario Limonciello <[email protected]>
platform/x86/amd/pmc: Fix LPS0 and debugfs leaks when STB init fails
Mario Limonciello <[email protected]>
platform/x86/amd/pmc: Propagate SMU errors and validate S2D address
Mario Limonciello <[email protected]>
platform/x86/amd/pmc: Restore msg_port on amd_stb_s2d_init() error paths
Bryam Vargas <[email protected]>
platform/chrome: sensorhub: Bound the EC-reported sensor number
Thorsten Blum <[email protected]>
platform/x86: think-lmi: Fix current password length check
Thorsten Blum <[email protected]>
platform/x86: think-lmi: Free system certificate signatures
Thorsten Blum <[email protected]>
platform/x86: think-lmi: Fix certificate thumbprint sysfs output
Julian Haarmann <[email protected]>
platform/x86: lenovo/ymc: Only match lower byte in WMI lid switch query response
Ma Ke <[email protected]>
platform/x86: ishtp_eclite: Fix ACPI device reference leak in probe error path
Srinivas Pandruvada <[email protected]>
platform/x86: ISST: Return error during profile addition
Srinivas Pandruvada <[email protected]>
platform/x86: ISST: Validate parameter for frequency and priority
Srinivas Pandruvada <[email protected]>
platform/x86: ISST: Validate parameter for core power state
Srinivas Pandruvada <[email protected]>
platform/x86: ISST: Validate logical CPU id and clos id
Srinivas Pandruvada <[email protected]>
platform/x86: ISST: Use PP level enable mask
Srinivas Pandruvada <[email protected]>
platform/x86: ISST: Just allow 2 bits for SST feature enable
Srinivas Pandruvada <[email protected]>
platform/x86: ISST: Add a NULL check for sst_inst[]
Fan Wu <[email protected]>
mmc: via-sdmmc: stop card-detect handling on probe failure
Fan Wu <[email protected]>
mmc: via-sdmmc: cancel card-detect work on remove
HyeongJun An <[email protected]>
platform/x86: ISST: Validate socket ID in clos_assoc ioctl
HyeongJun An <[email protected]>
platform/x86: ISST: Validate level in perf mask ioctls
HyeongJun An <[email protected]>
platform/x86: dell-wmi-sysman: Don't hex dump attribute security buffer
Peiyang He <[email protected]>
iommufd: Fix UAF in selftest IOPF reporting
Shuai Xue <[email protected]>
iommufd: Release current IOAS on xa_store() failure
Shuai Xue <[email protected]>
iommufd: Avoid locking internal accesses during unmap
Kevin Tian <[email protected]>
iommu/vt-d: Force requesting ACS when tboot is enabled
Kevin Tian <[email protected]>
iommu/vt-d: Fix no_iommu to disable platform opt-in
Peiyang He <[email protected]>
iommu: Fix dev_iommu memory leak when device_add fails in iommu_mock_device_add
Shameer Kolothum <[email protected]>
iommu/arm-smmu-v3: Manage teardown with devm
Nicolin Chen <[email protected]>
iommu/tegra241-cmdqv: Reject a vSID wider than the SID_MATCH field
Shuai Xue <[email protected]>
iommu/sva: Set handle->dev before the SVA handle is visible
Weimin Xiong <[email protected]>
iommu/msm: Unwind probe state on registration failure
Shuai Xue <[email protected]>
iommu/amd: Put PCI device after handling PPR faults
Krzysztof Wilczyński <[email protected]>
PCI/proc: Warn on writes to kernel-exclusive config space regions
Krzysztof Wilczyński <[email protected]>
PCI/proc: Use file_ns_capable() when checking config space read access
Krzysztof Wilczyński <[email protected]>
PCI/proc: Avoid spurious runtime PM wakeup on config space accesses
Farhan Ali <[email protected]>
PCI/MSI: Enable memory decoding before restoring MSI-X messages
Darshit Shah <[email protected]>
PCI/DPC: Allow DPC on all Downstream Ports when OS controls AER
Max Lee <[email protected]>
PCI/ASPM: Avoid L0s for Realtek RTS525A
Lukas Wunner <[email protected]>
PCI/AER: Fix mapping of errors to agent & layer
Lukas Wunner <[email protected]>
PCI/AER: Emit TLP Log only for unmasked errors
Krzysztof Wilczyński <[email protected]>
PCI/sysfs: Avoid spurious runtime PM wakeup on config space accesses
Krzysztof Wilczyński <[email protected]>
PCI/sysfs: Fix read byte order in pci_read_legacy_io()
Tim Harvey <[email protected]>
PCI: Add ACS quirk for Pericom PI7C9X2G608 switches [12d8:2608]
Ali Tariq <[email protected]>
PCI: plda: Fix IRQ domain leaks in the error paths of plda_init_interrupts()
Ali Tariq <[email protected]>
PCI: plda: Fix use-after-free of event IRQs during teardown
Ronald Claveau <[email protected]>
PCI: meson: Fix GPIO state while requesting PERST#
Mohamad Raizudeen <[email protected]>
PCI: Fix 32-bit config write in Intel PCH Root Port MPC ACS quirk
Naman Jain <[email protected]>
PCI: hv: Set irq_retrigger callback for the Hyper-V PCI MSI irqchip
Stefan Haberland <[email protected]>
s390/dasd: Propagate partial completion length across ERP recovery
Stefan Haberland <[email protected]>
s390/dasd: Guard sysfs discipline callbacks against unallocated private data
Stefan Haberland <[email protected]>
s390/dasd: Do not complete a failed ESE read as successful
Thomas Richter <[email protected]>
s390/cpum_cf: Handle CPU hotplug via prepare/dead callbacks
Jianing Li <[email protected]>
power: supply: max17040: synchronize work cancellation on suspend
Jianing Li <[email protected]>
power: supply: max17040: drop incorrect I2C functionality check
Jianing Li <[email protected]>
power: supply: max17040: propagate register read errors
Fan Wu <[email protected]>
power: supply: ucs1002: fix use-after-free on remove
Maoyi Xie <[email protected]>
power: supply: twl4030_charger: cancel workers via devm
Fan Wu <[email protected]>
power: supply: rt9455: quiesce delayed work before teardown
HyeongJun An <[email protected]>
power: supply: qcom_battmgr: terminate the strings from firmware
Fan Wu <[email protected]>
power: supply: qcom_battmgr: fix use-after-free
Fan Wu <[email protected]>
power: supply: lp8788-charger: fix use-after-free on remove
Fan Wu <[email protected]>
power: supply: lp8727: fix use-after-free in lp8727_release_irq()
Jameson Thies <[email protected]>
power: supply: cros_usbpd: Limit port counts to EC_USB_PD_MAX_PORTS
Bryam Vargas <[email protected]>
power: supply: cros_usbpd-charger: bound the EC-reported port count
Fan Wu <[email protected]>
power: supply: charger-manager: register regulators before exposing sysfs
Ma Ke <[email protected]>
power: supply: bq25890: Fix power_supply reference leak
Fan Wu <[email protected]>
power: supply: bq256xx: drain usb_work before freeing the charger
Fan Wu <[email protected]>
power: supply: bq24257: fix use-after-free on remove
Jun Yang <[email protected]>
sctp: fix stream->outcnt underflow on duplicate RECONF responses
Jun Yang <[email protected]>
sctp: distinguish sequence zero from wildcard in reconf lookup
Weiming Shi <[email protected]>
sctp: fix NULL deref on untransmitted RECONF completion
Hyunwoo Kim <[email protected]>
sctp: drop a chunk if its transport was removed
Hyunwoo Kim <[email protected]>
sctp: stop processing a packet once its association is deleted
Yehyeong Lee <[email protected]>
nvme-tcp: reject a read that transferred too few bytes
Yehyeong Lee <[email protected]>
nvme-tcp: fix host memory disclosure on R2T for a read command
Yehyeong Lee <[email protected]>
nvme-tcp: do not accept C2HData based on blk_rq_payload_bytes() alone
Myeonghun Pak <[email protected]>
nvme-pci: disable controller on admin queue IRQ setup failure
Yehyeong Lee <[email protected]>
nvme: zero the discard fallback page
Ewan D. Milne <[email protected]>
nvme: nvme-fc: Fix nvme_fc_create_hw_io_queues() queue deletion in error path
Shuangpeng Bai <[email protected]>
lockd: fix NULL dereference on lockowner allocation failure
Michael Bommarito <[email protected]>
lockd: pin next file across nlm_inspect_file lock-drop
Yifei Gao <[email protected]>
ipmi: Fix use-after-free of cmd_rcvr in _ipmi_destroy_user()
Ruoyu Wang <[email protected]>
i2c: mxs: fix DMA channel leak on probe error
Cong Nguyen <[email protected]>
hwmon: (max6621) fix temperature clamp range
Cong Nguyen <[email protected]>
hwmon: (max6621) fix negative temperature offset and crit readings
Christopher Tolang <[email protected]>
ASoC: amd: yc: Add DMI entry for MSI Thin A15 B7UC
Karl Mehltretter <[email protected]>
arm64: proton-pack: Restore the nospectre_bhb command-line option
Karl Mehltretter <[email protected]>
arm64: compat: Fix decrementing LDM/STM alignment emulation
HyeongJun An <[email protected]>
ALSA: ump: Fix corrupted data bytes at MIDI 1.0 SysEx to UMP conversion
Norbert Szetei <[email protected]>
openvswitch: only skb_tx_error() a packet we are about to drop
Ali Ahmet Memis <[email protected]>
openrisc: fix arbitrary kernel memory access via or1k_atomic syscall
Zhan Xusheng <[email protected]>
ocfs2: fix readdir position truncation on 32-bit kernels
Joseph Qi <[email protected]>
ocfs2: cluster: fix o2hb_dependent_users leak on pin failure
Joseph Qi <[email protected]>
ocfs2: cluster: avoid lock order inversion in o2hb_region_pin() from drop_item
Joseph Qi <[email protected]>
ocfs2: cluster: don't sleep while holding o2hb_live_lock in o2hb_region_pin()
Ibrahim Hashimov <[email protected]>
ocfs2: validate rl_used against rl_count in refcount block validator
Bryam Vargas <[email protected]>
ocfs2: validate lengths in dlm_mig_lockres_handler
Bryam Vargas <[email protected]>
ocfs2: bound namelen in dlm_migrate_request_handler
Dmitry Antipov <[email protected]>
ocfs2: always run deallocs on copy-on-write completion
Zhiling Zou <[email protected]>
orangefs: skip leading spaces before parsing client debug masks
Yifei Gao <[email protected]>
orangefs: fix double-free of trailer_buf on readdir copy failure
Shibo Zhu <[email protected]>
PM: sleep: Unblock runtime PM when device prepare fails
Vincent Donnefort <[email protected]>
ring-buffer: Hold cpu_buffer::lock when resizing a subbuf
Vincent Donnefort <[email protected]>
ring-buffer: Free cpu_buffer::free_page with subbuf_order
Vincent Donnefort <[email protected]>
ring-buffer: Fix subbuf resize race with ring_buffer_alloc_read_page()
Kathiravan Thirumoorthy <[email protected]>
regulator: qcom-refgen: correct the regulator type to CURRENT
WenTao Liang <[email protected]>
regulator: max8998_pmic_dt_parse_pdata: of_node_put on reg_np after ownership transferred to rdata
WenTao Liang <[email protected]>
regulator: as3722_get_regulator_dt_data: fix premature of_node_put leaving dangling of_node pointer
Jason Gunthorpe <[email protected]>
RDMA/uverbs: Add UVERBS_ATTR_UHW to UVERBS_METHOD_REG_MR
Norbert Szetei <[email protected]>
RDMA/ucma: Lock the handler in ucma_write_cm_event()
Norbert Szetei <[email protected]>
RDMA/ucma: Lock the handler in ucma_set_ib_path()
Brett Creeley <[email protected]>
RDMA/ionic: Cap eq_count to the eth driver's interrupt vector budget
Fan Wu <[email protected]>
RDMA/cxgb4: Cancel reg_work before freeing device on remove
Vaibhav Nagare <[email protected]>
qede: Fix NULL pointer dereference in TPA fragment processing
Abdifatah Suruur <[email protected]>
ptp: vmclock: prevent read-only mappings from becoming writable
Johan Hovold <[email protected]>
remoteproc: scp: Fix device reference leak on failed lookup
Nam Cao <[email protected]>
riscv: unaligned: stop using kthread for check_vector_unaligned_access()
Peixin Xie <[email protected]>
riscv: acpi: Handle LPI architectural context loss flags
Fabio Estevam <[email protected]>
arm64: dts: rockchip: Fix rk3588s-roc-pc audio description
Fabio Estevam <[email protected]>
arm64: dts: rockchip: Fix rk3399-roc-pc-plus analog audio
Jakob Unterwurzacher <[email protected]>
arm64: dts: rockchip: fix emmc reset polarity on px30-cobra
Quentin Schulz <[email protected]>
arm64: dts: rockchip: fix eMMC reset polarity on PX30 Ringneck
Quentin Schulz <[email protected]>
arm64: dts: rockchip: fix eMMC reset polarity on PP-1516
Michael Scott <[email protected]>
arm64: dts: qcom: x1-dell-thena: mark l12b and l15b always-on
Krzysztof Kozlowski <[email protected]>
arm64: dts: qcom: sm6115-pro1x: Correct touchscreen GPIO flags
Oren Klopfer <[email protected]>
Revert "arm64: dts: rockchip: Further describe the WiFi for the Pinephone Pro"
Chunkai Deng <[email protected]>
rpmsg: glink: smem: order FIFO read after availability check
Petr Vaganov <[email protected]>
scsi: core: Fill in DMA padding bytes in scsi_alloc_sgtables()
Cong Nguyen <[email protected]>
media: staging/ipu7: fix async notifier UAF on probe error path
Hao-Qun Huang <[email protected]>
staging: media: tegra-video: vi: fix probe failure on skipped last port
Hao-Qun Huang <[email protected]>
staging: media: tegra-video: fix of_node_put() on VIP parse errors
Wentao Guan <[email protected]>
wifi: mt76: mt7925: cancel pending mlo_pm_work
Doruk Tan Ozturk <[email protected]>
wifi: ath6kl: clamp assoc request/response lengths before subtracting IE offsets
David Lee <[email protected]>
udf: reject VAT indexes equal to the entry count
Chuck Lever <[email protected]>
svcrdma: Validate Read chunk positions before reconstruction
Chuck Lever <[email protected]>
svcrdma: Use svc_xprt_put to free listener on create failure
Chris Mason <[email protected]>
svcrdma: Reject Write/Reply chunks with segcount 0
Chuck Lever <[email protected]>
svcrdma: Reject inline replies that overflow the pull-up buffer
Chuck Lever <[email protected]>
svcrdma: Reject connection when transport allocation fails
Chris Mason <[email protected]>
svcrdma: Fix unmatched rn_unregister on failed accept
Chris Mason <[email protected]>
svcrdma: Fix pcl_for_each_segment for empty chunks
Chris Mason <[email protected]>
svcrdma: Fix offset arithmetic in read_chunk_range
Jérémy Jean <[email protected]>
SUNRPC: wait for in-flight client TLS handshake callback
Chuck Lever <[email protected]>
SUNRPC: Reject krb5 v2 wrap tokens with oversized ec field
Chris Mason <[email protected]>
SUNRPC: reject duplicate CREDS_VALUE options
Chris Mason <[email protected]>
sunrpc: init gssp_lock before publishing proc entry
Chris Mason <[email protected]>
SUNRPC: harden gss_unwrap_resp_priv length checks
Chris Mason <[email protected]>
SUNRPC: harden gss_krb5_unwrap_v2 against short tokens
Chris Mason <[email protected]>
SUNRPC: Guard svcauth_gss_release() dispatch on rq_auth_stat
Luxiao Xu <[email protected]>
sunrpc: fix use-after-free in __rpc_clnt_handle_event and __rpc_clnt_remove_pipedir
Jeff Layton <[email protected]>
sunrpc: defer rq_argp and rq_resp free until after RCU grace period
Chuck Lever <[email protected]>
SUNRPC: Check svc pool percpu counter allocation
Jeff Layton <[email protected]>
SUNRPC: always drain cache_cleaner before destroying a cache_detail
Ameer Hamza <[email protected]>
SUNRPC: Restore NUMA_NO_NODE for svc thread allocations in global mode
Jeff Layton <[email protected]>
sunrpc: route to a populated pool in svc_pool_for_cpu()
Chris Mason <[email protected]>
SUNRPC: svcauth_gss: enforce krb5 token minimum length
Chris Mason <[email protected]>
SUNRPC: Zero rpc_gss_wire_cred at svcauth_gss_decode_credbody() entry
Chris Mason <[email protected]>
SUNRPC: xdr_buf_trim: clamp buf->len to avoid underflow
Felix Gu <[email protected]>
phy: fsl-imx8mq-usb: fix typec switch leak on probe error path
Jiacheng Yu <[email protected]>
params: fix charp corruption on allocation failure
Dave Airlie <[email protected]>
nouveau/gem: reserve the bo in the info ioctl around the vma lookup
Stanislaw Gruszka <[email protected]>
module/kallsyms: fix nextval for data symbol lookup
Harshit Varu <[email protected]>
mptcp: fix uninitialized local_id in syncookie MP_JOIN reconstruction
Qing Ming <[email protected]>
mpls: reload header after pskb_may_pull()
Thiébaud Weksteen <[email protected]>
module: validate string table section types
Coly Li <[email protected]>
md: do overflow check for sb->bblog_shift in super_1_load()
Yunye Zhao <[email protected]>
md/raid10: fix still_degraded being inverted in raid10_sync_request()
Anup Vishwakarma <[email protected]>
mailbox: qcom-ipcc: fix duplicate channel allocation across holes
Bryam Vargas <[email protected]>
libnvdimm/labels: Prevent integer overflow in __nd_label_validate()
Günther Noack <[email protected]>
landlock: Require LANDLOCK_ACCESS_FS_MAKE_REG for whiteout creation
Yuyang Huang <[email protected]>
ipv6: use RCU iterator to dump route exceptions
Andrea Mayer <[email protected]>
ipv6: rpl: fix NULL dereference of idev in ipv6_rpl_srh_rcv()
Zhiling Zou <[email protected]>
ip6_gre: fix hardware header length for NBMA tunnels
Zhiling Zou <[email protected]>
ip6_tunnel: use skb_cow_head() in ip6_tnl_xmit()
Zhiling Zou <[email protected]>
ip: orphan prefetched skbs before multicast forwarding
Anton Danilov <[email protected]>
ipip: fix skb leak in collect_md mode when metadata_dst allocation fails
Max Kellermann <[email protected]>
jbd2: check need_resched() when skipping busy checkpoint buffers
Max Kellermann <[email protected]>
jbd2: bound shrinker scans by examined checkpoint buffers
Hui Su <[email protected]>
kasan: fix cache shrink race with CPU hotplug
Ibrahim Abdelkader <[email protected]>
Bluetooth: hci_sync: Clear HCI_CMD_PENDING when dropping the last request
Guangshuo Li <[email protected]>
Bluetooth: hci_intel: fix usage_count leak when autosuspend_delay is negative
Guangshuo Li <[email protected]>
Bluetooth: hci_h5: fix usage_count leak when autosuspend_delay is negative
Valentin Kindschi <[email protected]>
Bluetooth: hci_event: clear HCI_LE_ADV only on a created connection
Xin Chen <[email protected]>
Bluetooth: hci_core: use skb_get() instead of skb_clone() for req_skb
Valentin Kindschi <[email protected]>
Bluetooth: hci_conn: re-enable advertising only for peripheral role
Chengfeng Ye <[email protected]>
Bluetooth: RFCOMM: serialize security confirmation handling
Hang Nan <[email protected]>
Bluetooth: ISO: fix use-after-free of listener socket in iso_conn_ready
Gongwei Li <[email protected]>
Bluetooth: hci_uart: Fix false success return in hci_uart_setup()
Guangshuo Li <[email protected]>
Bluetooth: hci_bcm: fix usage_count leak when autosuspend_delay is negative
Lorenzo Stoakes (ARM) <[email protected]>
Bluetooth: hci_bcm4377: Ignore reserved PHY in ext adv reports on BCM4378
Alison Schofield <[email protected]>
cxl/pmem: Format the nvdimm serial number as unsigned decimal
Zhenhao Wan <[email protected]>
cxl/features: bound fwctl command payload to the input buffer
Hui Su <[email protected]>
cpufreq: schedutil: Fix rate limit overflow
Kuan-Wei Chiu <[email protected]>
coresight: etm3x: Fix cntr_val_show() to match cntr_val_store() behavior
Bryam Vargas <[email protected]>
dm array: reject an array block whose value size is not the caller's
Bryam Vargas <[email protected]>
dm array: validate array block headers on read
Ilya Krutskih <[email protected]>
dm raid1: reserve space for NUL-terminator in build_constructor_string()
liyouhong <[email protected]>
dm-era: fix shadowed superblock leak on take-snap failure
Mikulas Patocka <[email protected]>
dm-io: report non-retryable errors separatedly
Keith Busch <[email protected]>
dm-io: clone the source bio instead of copying its biovec
Jérémy Jean <[email protected]>
bpf: Harden bloom filter sizing and indexing on 32-bit kernels
Jia Zhu <[email protected]>
buffer: avoid tail commit walk for uptodate folios
Daniel Borkmann <[email protected]>
bpf: Disable preemption in __bpf_get_stack
Vineet Gupta <[email protected]>
bpf, x86: Fix per-CPU address resolution into an extended register
Joe Damato <[email protected]>
bnxt_en: Write doorbell when linearizing skb fails
Jiangshan Yi <[email protected]>
bnx2x: fix double free in bnx2x_init_firmware() error path
HyeongJun An <[email protected]>
Bluetooth: eir: Fix OOB read in eir_get_service_data()
Junjie Cao <[email protected]>
Bluetooth: btusb: limit RTL8761B BROKEN_EXT_SCAN quirk to 0bda:a728
Christoph Zwerschke <[email protected]>
Bluetooth: btusb: Add ASUS USB-BT600 for Realtek 8761CU
Christoph Zwerschke <[email protected]>
Bluetooth: btusb: Add ASUS USB-BT540 for Realtek 8761CU
胡连勤 <[email protected]>
block: set QUEUE_FLAG_DYING unconditionally in blk_mark_disk_dead()
Hongyan Xu <[email protected]>
auxdisplay: charlcd: cancel backlight work on registration failure
Niklas Cassel <[email protected]>
ata: libata-scsi: fix DSM TRIM for sector sizes larger than 2048 bytes
Ethan Nelson-Moore <[email protected]>
ARM: 9477/1: Disable broken eBPF JIT on the Risc PC
Matt Turner <[email protected]>
alpha: marvel: Fix lock ordering in init_io7_irqs()
Matt Turner <[email protected]>
alpha: marvel: Fix irq_set_status_flags to use correct IRQ number
Krzysztof Wilczyński <[email protected]>
alpha/PCI: Fix I/O port accessor argument order in pci_legacy_write()
Anirudh Prasad <[email protected]>
ACPI: pfr_update: fix stack buffer overflow in query_capability()
TanZheng <[email protected]>
ACPI: APEI: GHES: fix ARM section length accounting after header
Nirmoy Das <[email protected]>
ACPI: APEI: Fix ERST timeout unit conversion
Terry Bowman <[email protected]>
acpi/apei/ghes: Use raw_spinlock_t for CXL CPER work locks
ZhaoJinming <[email protected]>
accel/rocket: Fix error path handling in rocket_job_run()
Shuvam Pandey <[email protected]>
accel/rocket: initialize job domain before cleanup paths
Muhammad Bilal <[email protected]>
accel/rocket: fix NULL dereference and integer overflow in rocket_job_push()
Guillaume Morin <[email protected]>
hugetlb: only adjust reservation during unmapping if mapcount is 0
Ivaylo Dimitrov <[email protected]>
hsi: omap_ssi_core: fix missing DMA mask setup for SSI controller device
Tien Sung Ang <[email protected]>
fpga: stratix10-soc: Fix SVC mailbox handling during reconfiguration
Marek Czernohous <[email protected]>
forcedeth: fix off-by-one when saving/restoring non-PCI config space
Myeonghun Pak <[email protected]>
fbdev: uvesafb: unregister connector callback on init failure
Hui Su <[email protected]>
fbdev: ssd1307fb: defer I2C transfers from damage callbacks
Florian Fuchs <[email protected]>
fbdev: pvr2fb: correct user pointer annotation and sentinel initializer
Runyu Xiao <[email protected]>
fbdev: omapfb: panel-dsi-cm: initialize lock before registering display
Yemu Lu <[email protected]>
fat: restore original value when fat_ent_write failed
Chengfeng Ye <[email protected]>
fanotify: fix use-after-free of file range info
Ard Biesheuvel <[email protected]>
efivarfs: Rate limit statfs() handler
Yichong Chen <[email protected]>
ecryptfs: show filename encryption options
Yichong Chen <[email protected]>
ecryptfs: release message context on send failure
Yichong Chen <[email protected]>
ecryptfs: reject too-small tag 70 packets
HanQuan <[email protected]>
ecryptfs: reject oversized encrypted_key_size in parse_tag_3_packet
Yichong Chen <[email protected]>
ecryptfs: pass packet set buffer size to parser
Yichong Chen <[email protected]>
ecryptfs: hold msg ctx list lock when cleaning daemon queue
Yichong Chen <[email protected]>
ecryptfs: fix tag 11 packet exact-fit size check
Pengpeng Hou <[email protected]>
eCryptfs: bound the packet-length peek to the user buffer
Konstantin Komarov <[email protected]>
fs/ntfs3: bound page_lcns[] index by the log record
Samuel Page <[email protected]>
fs/ntfs3: fix info-leak on partial LZNT decompress in ni_read_frame()
Xiang Mei <[email protected]>
fs/ntfs3: validate dirty page table on log replay
Deepanshu Kartikey <[email protected]>
eventfs: Initialize ei->children and ei->list in init_ei()
Guangshuo Li <[email protected]>
HID: intel-thc-hid: intel-quickspi: fix autosuspend cleanup during teardown
Guangshuo Li <[email protected]>
HID: intel-thc-hid: intel-quicki2c: fix autosuspend cleanup during teardown
HyeongJun An <[email protected]>
HID: intel-thc-hid: intel-quickspi: bound GET_REPORT response to the caller buffer
HyeongJun An <[email protected]>
HID: intel-thc-hid: intel-quickspi: validate report size before copy
Jiangshan Yi <[email protected]>
HID: mcp2221: validate report size in mcp2221_raw_event()
Jiangshan Yi <[email protected]>
HID: mcp2221: stop device IO before hid_hw_stop
Baul Lee <[email protected]>
HID: universal-pidff: stop the device when force-feedback init fails
Doruk Tan Ozturk <[email protected]>
HID: sony: fix UAF of ghl_poke_timer / ghl_urb at driver unbind
Haoxiang Li <[email protected]>
HID: sensor: custom: Fix field sysfs group cleanup on failure
Xu Rao <[email protected]>
HID: roccat: free buffered reports when destroying device
Ibrahim Hashimov <[email protected]>
HID: picolcd: clamp eeprom debugfs read to bytes actually received
Stuart Hayhurst <[email protected]>
HID: corsair-void: Check size of status and firmware events before reading them
Andre Eikmeyer <[email protected]>
HID: apple: preserve keyboard backlight across T2 resume
Fredric Cover <[email protected]>
smb: client: harden DFS cache against invalid target hints
Frank Sorenson <[email protected]>
smb: client: fix copy-paste error in WSL EA length accounting for $LXDEV
Frank Sorenson <[email protected]>
smb: client: fix ALIGN() overflow in symlink_data() error context loop
Fredric Cover <[email protected]>
smb: client: clear ce->tgthint in free_tgts()
Frank Sorenson <[email protected]>
cifs: use cifs_invalidate_cache() in cifs_do_truncate() for O_TRUNC
Frank Sorenson <[email protected]>
cifs: fix loff_t underflow in cifs_remap_file_range() when len == 0
Frank Sorenson <[email protected]>
cifs: clear tcon after cifsFileInfo_put() in cifs_file_set_size()
Jérémy Jean <[email protected]>
audit: avoid dropping live tree ref on fsnotify rule autoremove
Qu Wenruo <[email protected]>
btrfs: do not overwrite NODATASUM flag when removing NODATACOW flag
Shuangpeng Bai <[email protected]>
btrfs: fix extent map leak in NOCOW direct I/O write
Guanghui Yang <[email protected]>
btrfs: drop recovered reloc root refs on recovery failure
Matthew Brown <[email protected]>
ceph: fix leaked inode reference on writeback abort at umount
Max Kellermann <[email protected]>
ceph: do not repeat ceph_trim_dentries() if no progress possible
Michael Bommarito <[email protected]>
ceph: bound xattr value length in __build_xattrs()
Michael Bommarito <[email protected]>
ceph: bound num_export_targets array for mds info v2/v3
Michael Bommarito <[email protected]>
ceph: bound MDSCapAuth path and fs_name decode in handle_session()
Michael Bommarito <[email protected]>
ceph: bound copied dentry name length in NFS export get_name
Jérémy Jean <[email protected]>
ceph: reject export_targets ranks >= CEPH_MAX_MDS in mdsmap decode
Xiubo Li <[email protected]>
ceph: fix UAF in __kick_flushing_caps() on cf entry freed during unlock
Jérémy Jean <[email protected]>
libceph: reject buckets with mismatched CRUSH ids
Michael Bommarito <[email protected]>
libceph: validate OSD extent maps before cursor advance
Chuck Lever <[email protected]>
NFSD: Prevent client use-after-free during NFSv4.0 revoked-state cleanup
Chuck Lever <[email protected]>
NFSD: Prevent lock owner use-after-free during client teardown
Jeff Layton <[email protected]>
nfsd: revoke copy-notify stateids before dropping their reference
Jeff Layton <[email protected]>
nfsd: reject reclaim LOCK after RECLAIM_COMPLETE
Robbie Ko <[email protected]>
nfsd: reject out-of-range useconds in NFSv2 SETATTR/CREATE
Robbie Ko <[email protected]>
nfsd: reject out-of-range nseconds in NFSv3 SETATTR and create ops
Jeff Layton <[email protected]>
nfsd: move nfsd_debugfs_init() after nfsd4_init_slabs() in init_nfsd()
Jeff Layton <[email protected]>
nfsd: initialize DRC hash table before registering shrinker
Jeff Layton <[email protected]>
nfsd: initialize copy-notify stateid before publishing it
Chris Mason <[email protected]>
nfsd: hold rcu across localio cmpxchg retry
Chris Mason <[email protected]>
nfsd: gate nfs3 setacl by argp->mask
Chuck Lever <[email protected]>
nfsd: gate nfs2 setacl by argp->mask
Jeff Layton <[email protected]>
nfsd: fix XDR padding calculation in ff_encode_getdeviceinfo
Jeff Layton <[email protected]>
nfsd: fix XDR length calculation in nfsd4_ff_encode_layoutget
Jeff Layton <[email protected]>
nfsd: fix version mismatch loops in nfsd_acl_init_request()
Jeff Layton <[email protected]>
nfsd: fix stale s2s_cp_stateids IDR entry for async COPY
Jeff Layton <[email protected]>
nfsd: fix reply size estimate for GET_DIR_DELEGATION
Jeff Layton <[email protected]>
nfsd: fix refcount leak in nfsd_file_lru_add on insertion failure
Nikol Kuklev <[email protected]>
nfsd: fix null dereference in nfsd4_setattr for deleg timestamp attrs
Jeff Layton <[email protected]>
nfsd: fix nfsd_file leak on inter-server COPY setup failure
Jeff Layton <[email protected]>
nfsd: fix netlink dumpit error handling for rpc_status_get
Jeff Layton <[email protected]>
nfsd: fix FL_SLEEP being set unconditionally for all LOCK types
Jeff Layton <[email protected]>
nfsd: fix dentry ref leak on V4ROOT export filehandle lookup
Chris Mason <[email protected]>
nfsd: fix cpntf publish race in nfs4_init_cp_state
Jeff Layton <[email protected]>
nfsd: fix BUG_ON in nfsd4_alloc_layout_stateid on racing delegation revoke
Jeff Layton <[email protected]>
nfsd: drop the stateid, not the stateowner, on seqid_op replay retry
Jeff Layton <[email protected]>
nfsd: don't free session slots that are still in use
Jeff Layton <[email protected]>
nfsd: defer vfree of compound ops to fix rpc_status UAF
Jeff Layton <[email protected]>
nfsd: defer setting NFSD4_CALLBACK_RUNNING in deleg_reaper
Jeff Layton <[email protected]>
nfsd: clear opcnt on compound arg release to prevent OOB read
Jeff Layton <[email protected]>
nfsd: clear CALLBACK_RUNNING on failed delegation recall queue
Jeff Layton <[email protected]>
nfsd: check client ownership when cancelling a copy-notify stateid
Jeff Layton <[email protected]>
nfsd: block non-SAVEFH ops after FOREIGN PUTFH to prevent NULL deref
Jeff Layton <[email protected]>
nfsd: add missing read barrier to rpc_status_get dumpit seqcount retry
Jeff Layton <[email protected]>
nfsd: add filehandle match check to nfsd4_delegreturn()
Jeff Layton <[email protected]>
nfsd: add fh_want_write() for early-verified SETATTR in nfsd_proc_setattr()
Jeff Layton <[email protected]>
nfsd: validate symlink target length in NFSv4 CREATE
Jeff Layton <[email protected]>
nfsd: validate sockaddr length per family in listener_set
Jeff Layton <[email protected]>
nfsd: validate nseconds in TIME_DELEG decode paths
Chris Mason <[email protected]>
nfsd: size fh_verify server sockaddr slot by xpt_locallen
Zhenghang Xiao <[email protected]>
nfsd: set SC_STATUS_FREED in nfsd4_drop_revoked_stid for delegations
Chuck Lever <[email protected]>
nfsd: sample writeback error cursor before async COPY loop
Jeff Layton <[email protected]>
nfsd: return NFS4ERR_NOTSUPP for unsupported netloc4 types
Chuck Lever <[email protected]>
nfsd: Reset write verifier when async COPY writeback fails
Chris Mason <[email protected]>
nfsd: release path refs on follow_down() error
Jeff Layton <[email protected]>
nfsd: RCU-protect cl_cb_session to fix use-after-free on session teardown
Tim Menninger <[email protected]>
pNFS: Fix EBUSY check in pnfs_layout_need_return
Junrui Luo <[email protected]>
NFSv4.1: fix layout segment leak on the pnfs_layout_process() forget path
Chris Mason <[email protected]>
nfsd: guard nfsd_serv deref in nfsd_file_net_dispose
Mike Snitzer <[email protected]>
NFSD: remove flawed WARN_ON_ONCE from nfsd_mode_check
Michael Bommarito <[email protected]>
NFSD: restart ssc_expire_umount walk after dropping nfsd_ssc_lock
Chuck Lever <[email protected]>
NFSD: Fix off-by-one in DRC bucket pruning limit
Chuck Lever <[email protected]>
NFSD: Encode only the status in NFS-ACL v2 GETACL error replies
Chuck Lever <[email protected]>
NFSD: check truncate permission under inode lock
Nate Prodromou <[email protected]>
NFS: fix delegation_hash_table leak when nfs4_server_common_setup() fails
Chris Mason <[email protected]>
NFS/localio: fix ref leak on nfs_uuid_add_file failure
Longlong Xia <[email protected]>
zsmalloc: account for handle size in class lookup
Sergey Senozhatsky <[email protected]>
zram: validate deflate params
Ibrahim Hashimov <[email protected]>
ubifs: fix out-of-bounds read in signature length check
Jason Yang <[email protected]>
phy: rockchip-samsung-dcphy: fix out-of-range max_register
Krzysztof Wilczyński <[email protected]>
PCI/sysfs: Fix out-of-bounds read in pci_write_legacy_io()
Abdurrahman Hussain <[email protected]>
of: fix out-of-bounds read in of_alias_scan() stem parser
Ryusuke Konishi <[email protected]>
nilfs2: fix slab-out-of-bounds in nilfs_direct_propagate after truncation
Junrui Luo <[email protected]>
media: vicodec: fix out-of-bounds write in FWHT encoder
Weigang He <[email protected]>
media: cec: stm32: prevent out-of-bounds write on RX overflow
Vincent Mailhol <[email protected]>
lib/ucs2_string.c: fix out-of-bounds read in ucs2_strnlen()
Xingrui Li <[email protected]>
HID: sensor-hub: Fix out-of-bounds write in sensor_hub_get_feature
Daisuke Matsuda <[email protected]>
fpga: altera-cvp: Avoid out-of-bounds read in trailing byte write
Neill Kapron <[email protected]>
usb: gadget: f_fs: Prevent deadlock during ep0 read loop
Jeffin Philip <[email protected]>
usb: gadget: uvc: fix dangling pointers in uvc_function_bind() and uvc_function_unbind()
Jeffin Philip <[email protected]>
usb: gadget: uvc: Fix null pointer dereference in uvcg_video_init()
Yun Zhou <[email protected]>
usb: gadget: f_tcm: fix deadlock in usbg_make_tpg()
Joshua Crofts <[email protected]>
usb: gadget: midi2: remove default configfs groups on teardown
Myeonghun Pak <[email protected]>
usb: gadget: snps_udc_plat: clean up PHY on probe deferral
Sonali Pradhan <[email protected]>
usb: gadget: u_audio: Fix use-after-free on sound card disconnect
Huang Wei <[email protected]>
usb: typec: ucsi: use UCSI_TIMEOUT_MS for sync command completion
Fan Wu <[email protected]>
usb: typec: thunderbolt: Disable work before freeing tbt on remove
Xu Yang <[email protected]>
usb: typec: tcpci: pass correct rx_type to tcpm_pd_receive()
Johan Hovold <[email protected]>
USB: phy: fsl-usb: fix missing static keywords
Fan Wu <[email protected]>
usb: gadget: at91_udc: drain polled-VBUS timer/work before udc is freed
Pei Xiao <[email protected]>
usb: dwc3: gadget: Fix use-after-free in dwc3_gadget_free_endpoints due to race condition
Francesco Lavra <[email protected]>
usb: dwc2: gadget: Exit partial power down state when changing USB pull-up
Hao-Qun Huang <[email protected]>
staging: greybus: hid: fix SET_REPORT return value
Karl Mehltretter <[email protected]>
serial: imx: serialize imx_uart_ports[] lifetime
Hans Verkuil <[email protected]>
Revert "media: v4l2-dev: fix error handling in __video_register_device()"
James Kim <[email protected]>
rapidio: mport_cdev: fix use-after-free in dma_req_free()
Bartosz Golaszewski <[email protected]>
powerpc/powermac: fix OF node refcount
Bryam Vargas <[email protected]>
misc: nsm: bound the device-reported response length
Xu Yang <[email protected]>
device property: fix infinite loop in fwnode_for_each_child_node()
Prasanna Kumar T S M <[email protected]>
cdx: Fix double free when sysfs file creation fails
Hui Su <[email protected]>
tracing: Fix use-after-free with same-name named triggers
Deepanshu Kartikey <[email protected]>
tracing: Fix use-after-free in trace_pipe read on sub-buffer order change
Vincent Donnefort <[email protected]>
tracing: Fix logged instance name on creation failure
Hui Su <[email protected]>
tracing: Fix crash passing ERR_PTR to kthread_stop()
Jérémy Jean <[email protected]>
tracing/user_events: Clear copied tracing state before fork duplication
Sanman Pradhan <[email protected]>
hwtracing: hisi_ptt: Propagate DMA reset timeout in trace_start()
Kiryl Shutsemau (Meta) <[email protected]>
x86/tdx: Fix zero-extension for 32-bit port I/O
Kiryl Shutsemau (Meta) <[email protected]>
x86/tdx: Fix off-by-one in port I/O handling
Yao Zi <[email protected]>
x86/locking: Use sfence for wmb() if SSE is available
Kiryl Shutsemau (Meta) <[email protected]>
x86/insn-eval: Move assign_register() out of KVM as insn_assign_reg()
Joy H.J. Lee <[email protected]>
tools/compiler: match glibc 2.42 definition of __attribute_const__
Ridong Chen <[email protected]>
mm: vmscan: fix node reclaim ignoring swappiness parameter
Johannes Weiner <[email protected]>
mm: page_alloc: fix non-movable reclaim storm in defrag_mode
Vlastimil Babka (SUSE) <[email protected]>
mm: page_alloc: move capture_control to the page allocator
Johannes Weiner <[email protected]>
mm: page_alloc: __GFP_FS lockdep annotation for direct compaction
Johannes Weiner <[email protected]>
mm: mempolicy: fix automatic numa balancing for shmem
Guopeng Zhang <[email protected]>
mm: memcontrol: update state_local when flushing NMI stats
Guopeng Zhang <[email protected]>
mm: memcg: stop reclaim when a limit update is superseded
Guopeng Zhang <[email protected]>
mm: memcg-v1: fix memsw and TCP failcnt accounting
Guopeng Zhang <[email protected]>
mm: memcg-v1: fix wrong linux-mm list address in deprecation warnings
Johannes Weiner <[email protected]>
mm: compaction: support non-movable compaction for pageblock requests
Hao Jia <[email protected]>
mm/zswap: fix global shrinker when memory cgroup is disabled
Breno Leitao <[email protected]>
mm/vmscan: report RCU-tasks quiescent states in shrink_lruvec()
Hyunwoo Kim <[email protected]>
mm/pagewalk: fix stale walk->action escaping walk_pmd_range()
Dev Jain <[email protected]>
mm/page_vma_mapped: use huge_ptep_get() for hugetlb
Ye Liu <[email protected]>
mm/page_owner: use memcg_data snapshot to avoid TOCTOU in print_page_owner_memcg()
Alexander Graf <[email protected]>
mm/mm_init: deferred_grow_zone(): fix out-of-range first_deferred_pfn
Dev Jain <[email protected]>
mm/migrate: use huge_ptep_get() in remove_migration_pte()
Breno Leitao <[email protected]>
mm/migrate: report RCU-tasks quiescent states in migrate_pages_batch()
Breno Leitao <[email protected]>
mm/kmemleak: avoid soft lockup when scanning task stacks
David Hildenbrand (Arm) <[email protected]>
mm/gup: fix always draining LRU caches in collect_longterm_unpinnable_folios()
Breno Leitao <[email protected]>
mm, swap: ratelimit bad swap entry reports
Jordan R Abrahams-Whitehead <[email protected]>
include/linux/list.h: mark list_add and __list_add as __always_inline
Hyunwoo Kim <[email protected]>
apparmor: fix out-of-bounds write when null terminating a label vec
Jann Horn <[email protected]>
apparmor: fix cred UAF caused by begin_current_label_crit_section()
Chengfeng Ye <[email protected]>
KEYS: trusted: Fix TPM teardown ordering
Gary Guo <[email protected]>
rust: cfi: disable function merging if CFI is enabled
Nikolai Grlica <[email protected]>
rust: kernel: list: fix incorrect pop_back example comment
FUJITA Tomonori <[email protected]>
rust: bug: fix warn_on macro build error on UML
FUJITA Tomonori <[email protected]>
rust: bug: skip arch-specific asm in testlib builds
Jérémy Jean <[email protected]>
timers/itimer: Zero-init old itimerval before copy to userspace
Gaurav Batra <[email protected]>
powerpc/pseries/iommu: switch to Default DMA window during kdump
Baokun Li <[email protected]>
fs: fix user path of nested backing files
Felix Yan <[email protected]>
clocksource/drivers/timer-sun4i: Advertise a real minimum delta
WenTao Liang <[email protected]>
clocksource/drivers/nxp-pit: Fix IRQ leak on cpuhp_setup_state error path
Matt Turner <[email protected]>
alpha: don't leak hardware-fabricated FP exception bits to user space
FUJITA Tomonori <[email protected]>
rust: time: fix as_micros_ceil() rounding near i64::MAX
Matt Turner <[email protected]>
alpha: fix ieee_swcr_to_fpcr setting FPCR_DNOD unconditionally
Fangzhi Zuo <[email protected]>
drm/amd/display: Prune per-tile Timing from Apple Studio Display Primary Tile
Jerry Zuo <[email protected]>
drm/amd/display: hide Apple Studio Display secondary tile
Timur Kristóf <[email protected]>
drm/amd/display: Refactor amdgpu_dm_connector_detect (v2)
Roman Li <[email protected]>
drm/amd/display: Skip PHY SSC reduction on some 8K panels
David Howells <[email protected]>
netfs: Fix missing locking around retry adding new subreqs
Rong Zhang <[email protected]>
platform/x86: lenovo-wmi-helpers: Fix memory leak in lwmi_dev_evaluate_int()
Srinivasan Shanmugam <[email protected]>
drm/amd/display: Avoid NULL dereference in dc_dmub_srv error paths
Christian Brauner <[email protected]>
nsfs: tighten permission checks for handle opening
Daniel Borkmann <[email protected]>
bpf: Fix incorrect pruning due to atomic fetch precision tracking
Eric Dumazet <[email protected]>
ip_tunnel: adapt iptunnel_xmit_stats() to NETDEV_PCPU_STAT_DSTATS
Rochan Avlur <[email protected]>
fuse: wait for FR_FINISHED on abort_on_kill to prevent use-after-free
Zilin Guan <[email protected]>
wifi: ath11k: fix memory leaks in beacon template setup
Zilin Guan <[email protected]>
wifi: mt76: Fix memory leak after mt76_connac_mcu_alloc_sta_req()
Zide Chen <[email protected]>
perf/x86/intel/uncore: Fix die ID init and look up bugs
-------------
Diffstat:
Documentation/ABI/testing/sysfs-bus-nvdimm | 3 +- Documentation/admin-guide/blockdev/zoned_loop.rst | 9 +- Makefile | 7 +- arch/alpha/include/uapi/asm/fpu.h | 8 +- arch/alpha/kernel/pci-sysfs.c | 6 +- arch/alpha/kernel/sys_marvel.c | 25 +- arch/alpha/kernel/traps.c | 6 +- arch/alpha/math-emu/math.c | 88 ++++++- arch/arm/Kconfig | 2 +- arch/arm64/boot/dts/qcom/sm6115-fxtec-pro1x.dts | 2 +- arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi | 2 + arch/arm64/boot/dts/rockchip/px30-cobra.dtsi | 2 +- arch/arm64/boot/dts/rockchip/px30-pp1516.dtsi | 2 +- arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi | 2 +- .../boot/dts/rockchip/rk3399-pinephone-pro.dts | 18 -- .../arm64/boot/dts/rockchip/rk3399-roc-pc-plus.dts | 12 + arch/arm64/boot/dts/rockchip/rk3588s-roc-pc.dts | 23 +- arch/arm64/kernel/compat_alignment.c | 4 +- arch/arm64/kernel/proton-pack.c | 9 +- arch/openrisc/kernel/entry.S | 43 +++- arch/powerpc/kernel/pci-common.c | 9 +- arch/powerpc/platforms/powermac/low_i2c.c | 2 +- arch/powerpc/platforms/pseries/iommu.c | 23 +- arch/riscv/include/asm/acpi.h | 19 ++ arch/riscv/kernel/unaligned_access_speed.c | 19 +- arch/s390/kernel/perf_cpum_cf.c | 221 +++++++++++------- arch/x86/coco/tdx/tdx.c | 10 +- arch/x86/events/intel/uncore.c | 1 + arch/x86/events/intel/uncore_snbep.c | 13 +- arch/x86/include/asm/barrier.h | 2 +- arch/x86/include/asm/insn-eval.h | 36 +++ arch/x86/kvm/emulate.c | 26 +-- arch/x86/net/bpf_jit_comp.c | 2 +- block/genhd.c | 1 + drivers/accel/rocket/rocket_job.c | 32 ++- drivers/acpi/apei/erst.c | 2 +- drivers/acpi/apei/ghes.c | 52 +++-- drivers/acpi/pfr_update.c | 45 ++-- drivers/ata/libata-scsi.c | 28 +-- drivers/auxdisplay/charlcd.c | 21 +- drivers/base/arch_numa.c | 12 + drivers/base/power/main.c | 1 + drivers/base/property.c | 19 +- drivers/block/zloop.c | 3 +- drivers/block/zram/backend_deflate.c | 10 +- drivers/bluetooth/btrtl.c | 13 -- drivers/bluetooth/btusb.c | 14 ++ drivers/bluetooth/hci_bcm.c | 1 + drivers/bluetooth/hci_bcm4377.c | 1 + drivers/bluetooth/hci_h5.c | 4 +- drivers/bluetooth/hci_intel.c | 1 + drivers/bluetooth/hci_ldisc.c | 2 +- drivers/bluetooth/hci_serdev.c | 2 +- drivers/cdx/cdx.c | 7 +- drivers/char/hw_random/stm32-rng.c | 10 +- drivers/char/ipmi/ipmb_dev_int.c | 5 +- drivers/char/ipmi/ipmi_msghandler.c | 4 + drivers/char/tpm/tpm_i2c_nuvoton.c | 6 +- drivers/clocksource/timer-nxp-pit.c | 4 +- drivers/clocksource/timer-sun4i.c | 2 +- drivers/crypto/allwinner/Kconfig | 16 -- drivers/crypto/allwinner/sun8i-ce/Makefile | 1 - drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c | 57 ----- drivers/crypto/allwinner/sun8i-ce/sun8i-ce-prng.c | 159 ------------- drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h | 29 --- drivers/crypto/allwinner/sun8i-ss/Makefile | 1 - drivers/crypto/allwinner/sun8i-ss/sun8i-ss-core.c | 39 ---- drivers/crypto/allwinner/sun8i-ss/sun8i-ss-prng.c | 177 -------------- drivers/crypto/allwinner/sun8i-ss/sun8i-ss.h | 23 -- drivers/cxl/core/features.c | 8 +- drivers/cxl/core/pmem.c | 10 +- drivers/cxl/core/ras.c | 1 - drivers/cxl/cxl.h | 3 +- drivers/cxl/pci.c | 1 - drivers/cxl/pmem.c | 2 +- drivers/fpga/altera-cvp.c | 10 +- drivers/fpga/stratix10-soc.c | 21 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 114 ++++++++-- .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 24 +- drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 10 +- drivers/gpu/drm/amd/display/dc/dc_types.h | 1 + drivers/gpu/drm/nouveau/nouveau_gem.c | 11 +- drivers/hid/hid-apple.c | 18 +- drivers/hid/hid-corsair-void.c | 17 ++ drivers/hid/hid-mcp2221.c | 9 + drivers/hid/hid-picolcd_debugfs.c | 9 + drivers/hid/hid-roccat.c | 13 +- drivers/hid/hid-sensor-custom.c | 9 +- drivers/hid/hid-sensor-hub.c | 46 ++-- drivers/hid/hid-sony.c | 4 +- drivers/hid/hid-universal-pidff.c | 4 +- .../intel-thc-hid/intel-quicki2c/pci-quicki2c.c | 1 + .../intel-thc-hid/intel-quickspi/pci-quickspi.c | 10 +- .../intel-thc-hid/intel-quickspi/quickspi-dev.h | 1 + .../intel-thc-hid/intel-quickspi/quickspi-hid.c | 2 +- .../intel-quickspi/quickspi-protocol.c | 19 +- .../intel-quickspi/quickspi-protocol.h | 2 +- drivers/hsi/controllers/omap_ssi_core.c | 6 + drivers/hwmon/max6621.c | 8 +- .../hwtracing/coresight/coresight-etm3x-sysfs.c | 15 +- drivers/hwtracing/ptt/hisi_ptt.c | 20 +- drivers/i2c/busses/i2c-mxs.c | 5 +- drivers/i3c/master.c | 12 +- drivers/i3c/master/adi-i3c-master.c | 15 +- drivers/i3c/master/renesas-i3c.c | 70 +++++- drivers/i3c/master/svc-i3c-master.c | 10 +- drivers/infiniband/core/ucma.c | 14 +- drivers/infiniband/core/uverbs_std_types_mr.c | 6 +- drivers/infiniband/hw/cxgb4/device.c | 6 + drivers/infiniband/hw/ionic/ionic_lif_cfg.c | 2 +- drivers/interconnect/core.c | 7 +- drivers/iommu/amd/ppr.c | 3 +- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 56 +++-- drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c | 8 +- drivers/iommu/intel/dmar.c | 15 +- drivers/iommu/intel/iommu.c | 8 +- drivers/iommu/intel/iommu.h | 2 + drivers/iommu/iommu-sva.c | 2 +- drivers/iommu/iommu.c | 2 +- drivers/iommu/iommufd/device.c | 4 +- drivers/iommu/iommufd/ioas.c | 2 + drivers/iommu/iommufd/selftest.c | 31 ++- drivers/iommu/msm_iommu.c | 10 +- drivers/mailbox/qcom-ipcc.c | 17 +- drivers/md/dm-bufio.c | 10 +- drivers/md/dm-era-target.c | 5 + drivers/md/dm-integrity.c | 32 +-- drivers/md/dm-io.c | 96 ++++---- drivers/md/dm-kcopyd.c | 10 +- drivers/md/dm-log-userspace-base.c | 1 + drivers/md/dm-log.c | 4 +- drivers/md/dm-pcache/cache.c | 18 ++ drivers/md/dm-pcache/cache.h | 21 ++ drivers/md/dm-pcache/cache_dev.c | 22 +- drivers/md/dm-pcache/cache_gc.c | 10 +- drivers/md/dm-pcache/cache_key.c | 32 ++- drivers/md/dm-pcache/cache_segment.c | 12 +- drivers/md/dm-pcache/cache_writeback.c | 10 +- drivers/md/dm-pcache/dm_pcache.c | 4 +- drivers/md/dm-raid1.c | 26 ++- drivers/md/dm-snap-persistent.c | 4 +- drivers/md/dm-stats.c | 6 +- drivers/md/dm-switch.c | 2 +- drivers/md/dm-verity-target.c | 2 +- drivers/md/dm-writecache.c | 14 +- drivers/md/md.c | 7 + drivers/md/persistent-data/dm-array.c | 53 ++++- drivers/md/raid10.c | 2 +- drivers/media/cec/platform/stm32/stm32-cec.c | 3 +- drivers/media/test-drivers/vicodec/vicodec-core.c | 4 +- drivers/media/v4l2-core/v4l2-dev.c | 14 +- drivers/mfd/cgbc-core.c | 4 +- drivers/mfd/sm501.c | 2 + drivers/misc/nsm.c | 2 +- drivers/mmc/host/via-sdmmc.c | 12 +- drivers/net/dsa/realtek/rtl83xx.c | 4 +- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 3 + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 7 +- drivers/net/ethernet/ibm/emac/mal.c | 13 +- drivers/net/ethernet/nvidia/forcedeth.c | 4 +- drivers/net/ethernet/qlogic/qede/qede.h | 8 +- drivers/net/ethernet/qlogic/qede/qede_fp.c | 1 + drivers/net/ethernet/renesas/ravb.h | 3 + drivers/net/ethernet/renesas/ravb_main.c | 9 +- drivers/net/ethernet/renesas/ravb_ptp.c | 44 +++- drivers/net/ipa/ipa_modem.c | 18 +- drivers/net/ntb_netdev.c | 38 ++-- drivers/net/ovpn/main.c | 19 +- drivers/net/ovpn/ovpnpriv.h | 4 + drivers/net/ovpn/peer.c | 8 +- drivers/net/ovpn/tcp.c | 9 +- drivers/net/phy/phylink.c | 2 +- drivers/net/slip/slip.c | 11 +- drivers/net/thunderbolt/main.c | 12 + drivers/net/tun.c | 21 +- drivers/net/usb/qmi_wwan.c | 1 + drivers/net/wireless/ath/ath11k/mac.c | 28 ++- drivers/net/wireless/ath/ath6kl/cfg80211.c | 5 + .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 3 +- drivers/net/wireless/intel/iwlwifi/dvm/main.c | 4 +- drivers/net/wireless/marvell/mwifiex/sta_ioctl.c | 12 + drivers/net/wireless/mediatek/mt76/mt7615/main.c | 5 +- .../net/wireless/mediatek/mt76/mt76_connac_mcu.c | 16 +- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 15 +- drivers/net/wireless/mediatek/mt76/mt7925/mac.c | 1 + drivers/net/wireless/mediatek/mt76/mt7925/main.c | 12 +- drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 4 +- drivers/net/wireless/mediatek/mt76/mt7925/pci.c | 2 + drivers/net/wireless/mediatek/mt76/mt7925/usb.c | 1 + drivers/net/wireless/mediatek/mt76/mt7996/eeprom.c | 6 + drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 26 ++- drivers/net/wireless/realtek/rtl818x/rtl8180/dev.c | 2 +- drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c | 2 +- drivers/net/wireless/realtek/rtl8xxxu/core.c | 19 +- .../net/wireless/realtek/rtlwifi/rtl8192du/sw.c | 12 +- .../net/wireless/realtek/rtlwifi/rtl8192du/trx.c | 3 +- drivers/net/wireless/realtek/rtw88/pci.c | 4 +- drivers/net/wireless/realtek/rtw88/tx.c | 1 + drivers/ntb/ntb_transport.c | 38 ++-- drivers/nvdimm/label.c | 2 +- drivers/nvme/host/core.c | 2 +- drivers/nvme/host/fc.c | 2 +- drivers/nvme/host/pci.c | 1 + drivers/nvme/host/tcp.c | 45 +++- drivers/of/base.c | 2 +- drivers/pci/controller/dwc/pci-meson.c | 2 +- drivers/pci/controller/pci-hyperv.c | 1 + drivers/pci/controller/plda/pcie-plda-host.c | 52 ++++- drivers/pci/msi/msi.c | 10 + drivers/pci/pci-sysfs.c | 42 +++- drivers/pci/pcie/aer.c | 29 ++- drivers/pci/pcie/portdrv.c | 2 +- drivers/pci/proc.c | 16 +- drivers/pci/quirks.c | 9 +- drivers/phy/freescale/phy-fsl-imx8mq-usb.c | 21 +- drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c | 2 +- drivers/platform/chrome/cros_ec_sensorhub_ring.c | 19 +- drivers/platform/x86/amd/pmc/mp1_stb.c | 43 ++-- drivers/platform/x86/amd/pmc/pmc.c | 6 +- .../x86/dell/dell-wmi-sysman/biosattr-interface.c | 1 - drivers/platform/x86/hp/hp-bioscfg/bioscfg.c | 18 +- drivers/platform/x86/hp/hp-bioscfg/bioscfg.h | 8 + .../platform/x86/hp/hp-bioscfg/enum-attributes.c | 15 +- .../platform/x86/hp/hp-bioscfg/int-attributes.c | 6 +- .../x86/hp/hp-bioscfg/order-list-attributes.c | 14 +- .../x86/hp/hp-bioscfg/passwdobj-attributes.c | 14 +- .../platform/x86/hp/hp-bioscfg/spmobj-attributes.c | 4 +- .../platform/x86/hp/hp-bioscfg/string-attributes.c | 6 +- drivers/platform/x86/intel/ishtp_eclite.c | 5 +- .../x86/intel/speed_select_if/isst_tpmi_core.c | 77 ++++++- drivers/platform/x86/lenovo/think-lmi.c | 19 +- drivers/platform/x86/lenovo/wmi-helpers.c | 4 +- drivers/platform/x86/lenovo/ymc.c | 8 +- drivers/power/supply/bq24257_charger.c | 16 +- drivers/power/supply/bq256xx_charger.c | 29 +-- drivers/power/supply/bq25890_charger.c | 12 + drivers/power/supply/charger-manager.c | 54 +++-- drivers/power/supply/cros_usbpd-charger.c | 17 +- drivers/power/supply/lp8727_charger.c | 4 +- drivers/power/supply/lp8788-charger.c | 2 +- drivers/power/supply/max17040_battery.c | 32 ++- drivers/power/supply/qcom_battmgr.c | 9 +- drivers/power/supply/rt9455_charger.c | 21 +- drivers/power/supply/twl4030_charger.c | 12 +- drivers/power/supply/ucs1002_power.c | 6 +- drivers/ptp/ptp_vmclock.c | 6 + drivers/rapidio/devices/rio_mport_cdev.c | 10 +- drivers/regulator/as3722-regulator.c | 1 - drivers/regulator/max8998.c | 1 - drivers/regulator/qcom-refgen-regulator.c | 4 +- drivers/remoteproc/mtk_scp.c | 9 +- drivers/rpmsg/qcom_glink_smem.c | 7 + drivers/s390/block/dasd.c | 6 +- drivers/s390/block/dasd_eckd.c | 40 +++- drivers/s390/block/dasd_erp.c | 3 + drivers/scsi/scsi_lib.c | 2 + drivers/staging/greybus/hid.c | 2 +- drivers/staging/media/ipu7/ipu7-isys.c | 1 + drivers/staging/media/tegra-video/vi.c | 9 +- drivers/staging/media/tegra-video/vip.c | 10 +- drivers/tty/serial/imx.c | 20 +- drivers/usb/dwc2/gadget.c | 11 +- drivers/usb/dwc3/gadget.c | 1 + drivers/usb/gadget/function/f_fs.c | 14 +- drivers/usb/gadget/function/f_midi2.c | 2 + drivers/usb/gadget/function/f_tcm.c | 23 +- drivers/usb/gadget/function/f_uvc.c | 7 +- drivers/usb/gadget/function/u_audio.c | 24 +- drivers/usb/gadget/function/uvc_video.c | 2 +- drivers/usb/gadget/udc/at91_udc.c | 20 +- drivers/usb/gadget/udc/snps_udc_plat.c | 5 +- drivers/usb/phy/phy-fsl-usb.c | 52 ++--- drivers/usb/phy/phy-fsl-usb.h | 6 +- drivers/usb/typec/altmodes/thunderbolt.c | 2 + drivers/usb/typec/tcpm/tcpci.c | 12 +- drivers/usb/typec/ucsi/ucsi.c | 3 +- .../fbdev/omap2/omapfb/displays/panel-dsi-cm.c | 4 +- drivers/video/fbdev/pvr2fb.c | 4 +- drivers/video/fbdev/ssd1307fb.c | 72 +++++- drivers/video/fbdev/uvesafb.c | 2 + drivers/video/sticore.c | 22 +- drivers/w1/slaves/w1_ds28e17.c | 8 + fs/backing-file.c | 2 +- fs/btrfs/direct-io.c | 19 +- fs/btrfs/ioctl.c | 23 +- fs/btrfs/relocation.c | 31 ++- fs/buffer.c | 3 + fs/ceph/addr.c | 11 + fs/ceph/caps.c | 11 +- fs/ceph/dir.c | 10 +- fs/ceph/export.c | 26 ++- fs/ceph/mds_client.c | 8 +- fs/ceph/mdsmap.c | 11 +- fs/ceph/xattr.c | 1 + fs/ecryptfs/crypto.c | 2 +- fs/ecryptfs/ecryptfs_kernel.h | 3 +- fs/ecryptfs/keystore.c | 45 +++- fs/ecryptfs/messaging.c | 11 +- fs/ecryptfs/miscdev.c | 5 +- fs/ecryptfs/super.c | 7 + fs/efivarfs/super.c | 30 ++- fs/fat/misc.c | 4 + fs/fuse/dev.c | 3 +- fs/jbd2/checkpoint.c | 28 +-- fs/lockd/clntproc.c | 3 + fs/lockd/svcsubs.c | 53 +++-- fs/netfs/read_retry.c | 6 +- fs/netfs/write_retry.c | 6 +- fs/nfs/nfs4client.c | 17 +- fs/nfs/pnfs.c | 3 +- fs/nfs_common/nfslocalio.c | 16 +- fs/nfsd/filecache.c | 22 +- fs/nfsd/flexfilelayoutxdr.c | 20 +- fs/nfsd/localio.c | 8 +- fs/nfsd/nfs2acl.c | 52 +++-- fs/nfsd/nfs3acl.c | 17 +- fs/nfsd/nfs3proc.c | 40 ++++ fs/nfsd/nfs4callback.c | 113 +++++++-- fs/nfsd/nfs4layouts.c | 12 +- fs/nfsd/nfs4proc.c | 62 +++-- fs/nfsd/nfs4state.c | 253 ++++++++++++++++----- fs/nfsd/nfs4xdr.c | 26 ++- fs/nfsd/nfscache.c | 6 +- fs/nfsd/nfsctl.c | 129 ++++++++--- fs/nfsd/nfsfh.c | 12 +- fs/nfsd/nfsproc.c | 7 + fs/nfsd/nfssvc.c | 4 +- fs/nfsd/nfsxdr.c | 32 ++- fs/nfsd/state.h | 3 +- fs/nfsd/trace.h | 18 +- fs/nfsd/vfs.c | 34 +-- fs/nilfs2/bmap.c | 2 +- fs/nilfs2/bmap.h | 2 +- fs/nilfs2/btree.c | 39 +++- fs/nilfs2/direct.c | 4 +- fs/notify/fanotify/fanotify.c | 3 +- fs/notify/fanotify/fanotify.h | 6 +- fs/notify/fanotify/fanotify_user.c | 5 +- fs/nsfs.c | 2 +- fs/ntfs3/frecord.c | 9 + fs/ntfs3/fslog.c | 34 +++ fs/ocfs2/cluster/heartbeat.c | 150 +++++++++--- fs/ocfs2/cluster/nodemanager.c | 6 + fs/ocfs2/cluster/nodemanager.h | 1 + fs/ocfs2/dir.c | 2 +- fs/ocfs2/dlm/dlmmaster.c | 6 + fs/ocfs2/dlm/dlmrecovery.c | 9 + fs/ocfs2/refcounttree.c | 47 +++- fs/ocfs2/xattr.c | 5 +- fs/orangefs/devorangefs-req.c | 1 + fs/orangefs/orangefs-debugfs.c | 1 + fs/smb/client/cifsfs.c | 15 +- fs/smb/client/dfs_cache.c | 33 ++- fs/smb/client/file.c | 1 + fs/smb/client/inode.c | 1 + fs/smb/client/smb1ops.c | 2 +- fs/smb/client/smb2file.c | 5 +- fs/tracefs/event_inode.c | 7 +- fs/ubifs/auth.c | 2 +- fs/udf/inode.c | 2 +- fs/udf/partition.c | 2 +- include/linux/compaction.h | 3 +- include/linux/dm-io.h | 6 +- include/linux/list.h | 15 +- include/linux/netdevice.h | 3 +- include/linux/sunrpc/svc_rdma_pcl.h | 2 +- include/linux/usb/tcpci.h | 1 + include/net/ip_tunnels.h | 39 +++- include/net/sctp/structs.h | 2 +- include/uapi/linux/landlock.h | 1 + io_uring/query.c | 3 + kernel/auditfilter.c | 6 +- kernel/bpf/bloom_filter.c | 19 +- kernel/bpf/stackmap.c | 3 + kernel/bpf/verifier.c | 27 ++- kernel/module/kallsyms.c | 24 +- kernel/module/main.c | 14 +- kernel/params.c | 14 +- kernel/pid.c | 31 --- kernel/reboot.c | 29 +++ kernel/sched/cpufreq_schedutil.c | 15 +- kernel/signal.c | 4 + kernel/taskstats.c | 3 +- kernel/time/itimer.c | 2 +- kernel/time/timekeeping.c | 8 +- kernel/time/timer.c | 1 + kernel/trace/ring_buffer.c | 177 ++++++++------ kernel/trace/trace.c | 6 +- kernel/trace/trace_events.c | 2 + kernel/trace/trace_events_hist.c | 4 +- kernel/trace/trace_events_user.c | 3 + lib/ucs2_string.c | 2 +- lib/xarray.c | 3 + mm/compaction.c | 98 ++++---- mm/gup.c | 10 +- mm/hugetlb.c | 8 +- mm/internal.h | 10 +- mm/kasan/quarantine.c | 7 +- mm/kmemleak.c | 51 +++-- mm/memcontrol-v1.c | 6 +- mm/memcontrol.c | 13 ++ mm/mempolicy.c | 21 +- mm/migrate.c | 8 +- mm/mm_init.c | 9 +- mm/page_alloc.c | 76 ++++++- mm/page_owner.c | 10 +- mm/page_vma_mapped.c | 8 +- mm/pagewalk.c | 6 +- mm/swapfile.c | 6 +- mm/vmscan.c | 21 +- mm/zsmalloc.c | 11 +- mm/zswap.c | 13 +- net/bluetooth/eir.c | 3 +- net/bluetooth/hci_conn.c | 3 +- net/bluetooth/hci_core.c | 2 +- net/bluetooth/hci_event.c | 7 +- net/bluetooth/hci_sync.c | 2 + net/bluetooth/iso.c | 8 + net/bluetooth/rfcomm/core.c | 8 +- net/ceph/osd_client.c | 30 +++ net/ceph/osdmap.c | 2 + net/core/skbuff.c | 5 +- net/core/xdp.c | 4 +- net/ipv4/ip_tunnel.c | 2 +- net/ipv4/ipip.c | 2 +- net/ipv4/ipmr.c | 3 + net/ipv6/exthdrs.c | 26 +-- net/ipv6/ip6_gre.c | 14 +- net/ipv6/ip6_input.c | 1 + net/ipv6/ip6_tunnel.c | 22 +- net/ipv6/route.c | 2 +- net/ipv6/seg6_local.c | 9 + net/ipv6/sit.c | 2 +- net/iucv/af_iucv.c | 2 + net/l2tp/l2tp_netlink.c | 16 +- net/mpls/af_mpls.c | 2 + net/mptcp/syncookies.c | 1 + net/openvswitch/conntrack.c | 8 +- net/openvswitch/datapath.c | 50 ++-- net/sched/sch_generic.c | 2 +- net/sctp/inqueue.c | 7 +- net/sctp/sm_sideeffect.c | 4 + net/sctp/stream.c | 48 ++-- net/smc/af_smc.c | 3 +- net/smc/smc.h | 6 +- net/smc/smc_core.c | 27 +-- net/smc/smc_llc.c | 122 +++++++--- net/smc/smc_rx.c | 11 +- net/smc/smc_tx.h | 6 +- net/smc/smc_wr.c | 6 +- net/sunrpc/auth_gss/auth_gss.c | 6 +- net/sunrpc/auth_gss/gss_krb5_wrap.c | 13 +- net/sunrpc/auth_gss/gss_rpc_upcall.c | 6 - net/sunrpc/auth_gss/gss_rpc_upcall.h | 1 - net/sunrpc/auth_gss/gss_rpc_xdr.c | 6 + net/sunrpc/auth_gss/svcauth_gss.c | 8 +- net/sunrpc/cache.c | 7 +- net/sunrpc/clnt.c | 22 +- net/sunrpc/sunrpc_syms.c | 1 + net/sunrpc/svc.c | 93 +++++++- net/sunrpc/xdr.c | 2 +- net/sunrpc/xprtrdma/ib_client.c | 24 +- net/sunrpc/xprtrdma/svc_rdma_pcl.c | 2 +- net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 9 +- net/sunrpc/xprtrdma/svc_rdma_rw.c | 47 +++- net/sunrpc/xprtrdma/svc_rdma_sendto.c | 47 ++-- net/sunrpc/xprtrdma/svc_rdma_transport.c | 52 +++-- net/sunrpc/xprtsock.c | 12 +- net/vmw_vsock/virtio_transport.c | 2 +- rust/kernel/bug.rs | 8 +- rust/kernel/list.rs | 2 +- rust/kernel/time.rs | 17 +- scripts/rust_is_available.sh | 14 ++ scripts/rust_is_available_bindgen_libclang_22.h | 5 + scripts/rust_is_available_test.py | 30 ++- security/apparmor/include/cred.h | 6 +- security/apparmor/include/label.h | 6 +- security/apparmor/include/task.h | 15 +- security/apparmor/task.c | 27 +++ security/keys/trusted-keys/trusted_tpm1.c | 2 +- security/landlock/errata/abi-1.h | 23 ++ security/landlock/fs.c | 41 +++- security/smack/smack_lsm.c | 2 +- sound/core/ump_convert.c | 1 + sound/drivers/aloop.c | 6 + sound/drivers/mpu401/mpu401.c | 6 + sound/drivers/mts64.c | 6 + sound/drivers/portman2x4.c | 6 + sound/drivers/serial-u16550.c | 6 + sound/drivers/virmidi.c | 6 + sound/hda/codecs/realtek/alc269.c | 7 +- sound/hda/core/ext/stream.c | 4 +- sound/pci/pcxhr/pcxhr.c | 14 +- sound/soc/amd/yc/acp6x-mach.c | 7 + sound/usb/6fire/comm.c | 9 +- sound/usb/bcd2000/bcd2000.c | 11 +- tools/include/linux/compiler.h | 2 +- tools/testing/selftests/mm/run_vmtests.sh | 2 +- 498 files changed, 5399 insertions(+), 2514 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/552 perf/x86/intel/uncore: Fix die ID init and look up bugs
6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zide Chen <[email protected]>
[ Upstream commit a16d1ec4dd0cdcf689f324adde6067083bce9099 ]
In snbep_pci2phy_map_init(), in the nr_node_ids > 8 path, uncore_device_to_die() may return -1 when all CPUs associated with the UBOX device are offline.
Remove the WARN_ON_ONCE(die_id == -1) check for two reasons:
- The current code breaks out of the loop. This is incorrect because pci_get_device() does not guarantee iteration in domain or bus order, so additional UBOX devices may be skipped during the scan.
- Returning -EINVAL is incorrect, since marking offline buses with die_id == -1 is expected and should not be treated as an error.
Separately, when NUMA is disabled on a NUMA-capable platform, pcibus_to_node() returns NUMA_NO_NODE, causing uncore_device_to_die() to return -1 for all PCI devices. As a result, spr_update_device_location(), used on Intel SPR and EMR, ignores the corresponding PMON units and does not add them to the RB tree.
Fix this by using uncore_pcibus_to_dieid(), which retrieves topology from the UBOX GIDNIDMAP register and works regardless of whether NUMA is enabled in Linux. This requires snbep_pci2phy_map_init() to be added in spr_uncore_pci_init().
Keep uncore_device_to_die() only for the nr_node_ids > 8 case, where NUMA is expected to be enabled.
--- arch/x86/events/intel/uncore.c | 1 + arch/x86/events/intel/uncore_snbep.c | 13 ++++++------- 2 files changed, 7 insertions(+), 7 deletions(-)
arch/x86/events/intel/uncore.c +1 -0
@@ -67,6 +67,7 @@ int uncore_die_to_segment(int die)return bus ?pci_domain_nr (bus) : -EINVAL ; } +/* Note: This API can only be used when NUMA information is available. */ int uncore_device_to_die (struct pci_dev *dev) {int node =pcibus_to_node (dev->bus);
arch/x86/events/intel/uncore_snbep.c +6 -7
@@ -1475,13 +1475,7 @@ static int snbep_pci2phy_map_init(int devid, int nodeid_loc, int idmap_loc, bool } map->pbus_to_dieid[bus] = die_id =uncore_device_to_die (ubox_dev); -raw_spin_unlock (&pci2phy_map_lock); - -if (WARN_ON_ONCE (die_id ==-1 )) { - err = -EINVAL ; -break ; - } } }
@@ -6533,7 +6527,7 @@ static void spr_update_device_location(int type_id)while ((dev =pci_get_device (PCI_VENDOR_ID_INTEL , device, dev)) !=NULL ) { - die =uncore_device_to_die (dev); + die =uncore_pcibus_to_dieid (dev->bus);if (die <0 )continue ;
@@ -6557,6 +6551,11 @@ static void spr_update_device_location(int type_id)int spr_uncore_pci_init (void ) { +int ret =snbep_pci2phy_map_init (0x3250 ,SKX_CPUNODEID ,SKX_GIDNIDMAP , true); + +if (ret) +return ret; +/* * The discovery table of UPI on some SPR variant is broken, * which impacts the detection of both UPI and M3UPI uncore PMON.
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 2/552 wifi: mt76: Fix memory leak after mt76_connac_mcu_alloc_sta_req()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zilin Guan <[email protected]>
[ Upstream commit c41075ce8cf05ed8c0e7b7efef000dce548ffc42 ]
mt76_connac_mcu_alloc_sta_req() allocates an skb which is expected to be freed eventually by mt76_mcu_skb_send_msg(). However, currently if an intermediate function fails before sending, the allocated skb is leaked.
Specifically, mt76_connac_mcu_sta_wed_update() and mt76_connac_mcu_sta_key_tlv() may fail, leading to an immediate memory leak in the error path.
Fix this by explicitly freeing the skb in these error paths. Commit 7c0f63fe37a5 ("wifi: mt76: mt7996: fix memory leak on mt7996_mcu_sta_key_tlv error") made a similar change.
Compile tested only. Issue found using a prototype static analysis tool and code review.
--- .../net/wireless/mediatek/mt76/mt76_connac_mcu.c | 16 ++++++++++++---- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 4 +++- drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 4 +++- 3 files changed, 18 insertions(+), 6 deletions(-)
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +12 -4
@@ -1295,8 +1295,10 @@ int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif_link *mvif, wtbl_hdr); ret =mt76_connac_mcu_sta_wed_update (dev, skb); -if (ret) +if (ret) { +dev_kfree_skb (skb);return ret; + } ret =mt76_mcu_skb_send_msg (dev, skb, cmd, true);if (ret)
@@ -1309,8 +1311,10 @@ int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif_link *mvif,mt76_connac_mcu_sta_ba_tlv (skb, params, enable, tx); ret =mt76_connac_mcu_sta_wed_update (dev, skb); -if (ret) +if (ret) { +dev_kfree_skb (skb);return ret; + }return mt76_mcu_skb_send_msg (dev, skb, cmd, true); }
@@ -2766,12 +2770,16 @@ int mt76_connac_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,return PTR_ERR (skb); ret =mt76_connac_mcu_sta_key_tlv (sta_key_conf, skb, key, cmd); -if (ret) +if (ret) { +dev_kfree_skb (skb);return ret; + } ret =mt76_connac_mcu_sta_wed_update (dev, skb); -if (ret) +if (ret) { +dev_kfree_skb (skb);return ret; + }return mt76_mcu_skb_send_msg (dev, skb, mcu_cmd, true); }
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +3 -1
@@ -1773,8 +1773,10 @@ int mt7915_mcu_add_sta(struct mt7915_dev *dev, struct ieee80211_vif *vif, } out: ret =mt76_connac_mcu_sta_wed_update (&dev->mt76, skb); -if (ret) +if (ret) { +dev_kfree_skb (skb);return ret; + }return mt76_mcu_skb_send_msg (&dev->mt76, skb,MCU_EXT_CMD (STA_REC_UPDATE ), true);
drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +3 -1
@@ -1290,8 +1290,10 @@ int mt7925_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,return PTR_ERR (skb); ret =mt7925_mcu_sta_key_tlv (wcid, sta_key_conf, skb, key, cmd, msta); -if (ret) +if (ret) { +dev_kfree_skb (skb);return ret; + }return mt76_mcu_skb_send_msg (dev, skb, mcu_cmd, true); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 3/552 wifi: ath11k: fix memory leaks in beacon template setup
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zilin Guan <[email protected]>
[ Upstream commit ff49eba595df500e4ddccc593088c8a4ab5f2c27 ]
The functions ath11k_mac_setup_bcn_tmpl_ema() and ath11k_mac_setup_bcn_tmpl_mbssid() allocate memory for beacon templates but fail to free it when parameter setup returns an error.
Since beacon templates must be released during normal execution, they must also be released in the error handling paths to prevent memory leaks.
Fix this by using unified exit paths with proper cleanup in the respective error paths.
Compile tested only. Issue found using a prototype static analysis tool and code review.
--- drivers/net/wireless/ath/ath11k/mac.c | 28 ++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-)
drivers/net/wireless/ath/ath11k/mac.c +17 -11
@@ -1557,12 +1557,15 @@ static int ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif *arvif,if (!beacons || !beacons->cnt) {ath11k_warn (arvif->ar->ab,"failed to get ema beacon templates from mac80211\n" ); -return -EPERM ; + ret = -EPERM ; + goto free; }if (tx_arvif == arvif) { -if (ath11k_mac_set_vif_params (tx_arvif, beacons->bcn[0 ].skb)) -return -EINVAL ; +if (ath11k_mac_set_vif_params (tx_arvif, beacons->bcn[0 ].skb)) { + ret = -EINVAL ; + goto free; + } }else { arvif->wpaie_present = tx_arvif->wpaie_present; }
@@ -1589,11 +1592,11 @@ static int ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif *arvif, } } -ieee80211_beacon_free_ema_list (beacons); -if (tx_arvif != arvif && !nontx_vif_params_set) -return -EINVAL ;/* Profile not found in the beacons */ + ret = -EINVAL ;/* Profile not found in the beacons */ +free: +ieee80211_beacon_free_ema_list (beacons);return ret; }
@@ -1622,19 +1625,22 @@ static int ath11k_mac_setup_bcn_tmpl_mbssid(struct ath11k_vif *arvif, }if (tx_arvif == arvif) { -if (ath11k_mac_set_vif_params (tx_arvif, bcn)) -return -EINVAL ; +if (ath11k_mac_set_vif_params (tx_arvif, bcn)) { + ret = -EINVAL ; + goto free; + } }else if (!ath11k_mac_set_nontx_vif_params (tx_arvif, arvif, bcn)) { -return -EINVAL ; + ret = -EINVAL ; + goto free; } ret =ath11k_wmi_bcn_tmpl (ar, arvif->vdev_id, &offs, bcn,0 ); -kfree_skb (bcn); -if (ret)ath11k_warn (ab,"failed to submit beacon template command: %d\n" , ret); +free: +kfree_skb (bcn);return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 4/552 fuse: wait for FR_FINISHED on abort_on_kill to prevent use-after-free
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rochan Avlur <[email protected]>
[ Upstream commit 64b0b5cacbd2fea88001464cb712c9dfc795b26e ]
The abort_on_kill path in request_wait_answer() calls fuse_abort_conn() and returns without waiting for FR_FINISHED. If fuse_dev_do_write() is concurrently processing the same request (FR_LOCKED set), the caller frees req->args while it is still being accessed, causing a use-after-free.
Fix this by jumping to the existing wait_event(FR_FINISHED) instead of returning early. The wait will not hang because fuse_abort_conn() ensures all requests are ended.
--- fs/fuse/dev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/fuse/dev.c +2 -1
@@ -580,7 +580,7 @@ static void request_wait_answer(struct fuse_req *req)if (req->args->abort_on_kill) {fuse_abort_conn (fc); -return ; + goto wait_for_finish; }if (test_bit (FR_URING , &req->flags))
@@ -591,6 +591,7 @@ static void request_wait_answer(struct fuse_req *req)return ; } +wait_for_finish:/* * Either request is already in userspace, or it was forced. * Wait it out.
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 5/552 ip_tunnel: adapt iptunnel_xmit_stats() to NETDEV_PCPU_STAT_DSTATS
In reply to Greg Kroah-Hartman6.18-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.
--- include/linux/netdevice.h | 3 +-- include/net/ip_tunnels.h | 30 +++++++++++++++++++++++------- 2 files changed, 24 insertions(+), 9 deletions(-)
include/linux/netdevice.h +1 -2
@@ -2145,6 +2145,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);
@@ -2396,8 +2397,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
@@ -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.53.0
Greg Kroah-Hartman
maintainerPATCH 6/552 bpf: Fix incorrect pruning due to atomic fetch precision tracking
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Borkmann <[email protected]>
[ Upstream commit 179ee84a89114b854ac2dd1d293633a7f6c8dac1 ]
When backtrack_insn encounters a BPF_STX instruction with BPF_ATOMIC and BPF_FETCH, the src register (or r0 for BPF_CMPXCHG) also acts as a destination, thus receiving the old value from the memory location.
The current backtracking logic does not account for this. It treats atomic fetch operations the same as regular stores where the src register is only an input. This leads the backtrack_insn to fail to propagate precision to the stack location, which is then not marked as precise!
Later, the verifier's path pruning can incorrectly consider two states equivalent when they differ in terms of stack state. Meaning, two branches can be treated as equivalent and thus get pruned when they should not be seen as such.
Fix it as follows: Extend the BPF_LDX handling in backtrack_insn to also cover atomic fetch operations via is_atomic_fetch_insn() helper. When the fetch dst register is being tracked for precision, clear it, and propagate precision over to the stack slot. For non-stack memory, the precision walk stops at the atomic instruction, same as regular BPF_LDX. This covers all fetch variants.
Before:
0: (b7) r1 = 8 ; R1=8 1: (7b) *(u64 *)(r10 -8) = r1 ; R1=8 R10=fp0 fp-8=8 2: (b7) r2 = 0 ; R2=0
3: (db) r2 = atomic64_fetch_add((u64 *)(r10 -8), r2) ; R2=8 R10=fp0 fp-8=mmmmmmmm
4: (bf) r3 = r10 ; R3=fp0 R10=fp0
5: (0f) r3 += r2
mark_precise: frame0: last_idx 5 first_idx 0 subseq_idx -1
mark_precise: frame0: regs=r2 stack= before 4: (bf) r3 = r10
mark_precise: frame0: regs=r2 stack= before 3: (db) r2 = atomic64_fetch_add((u64 *)(r10 -8), r2)
mark_precise: frame0: regs=r2 stack= before 2: (b7) r2 = 0
6: R2=8 R3=fp8
6: (b7) r0 = 0 ; R0=0
7: (95) exit
After:
0: (b7) r1 = 8 ; R1=8 1: (7b) *(u64 *)(r10 -8) = r1 ; R1=8 R10=fp0 fp-8=8 2: (b7) r2 = 0 ; R2=0
3: (db) r2 = atomic64_fetch_add((u64 *)(r10 -8), r2) ; R2=8 R10=fp0 fp-8=mmmmmmmm
4: (bf) r3 = r10 ; R3=fp0 R10=fp0
5: (0f) r3 += r2
mark_precise: frame0: last_idx 5 first_idx 0 subseq_idx -1
mark_precise: frame0: regs=r2 stack= before 4: (bf) r3 = r10
mark_precise: frame0: regs=r2 stack= before 3: (db) r2 = atomic64_fetch_add((u64 *)(r10 -8), r2)
mark_precise: frame0: regs= stack=-8 before 2: (b7) r2 = 0
mark_precise: frame0: regs= stack=-8 before 1: (7b) *(u64 *)(r10 -8) = r1
mark_precise: frame0: regs=r1 stack= before 0: (b7) r1 = 8
6: R2=8 R3=fp8
6: (b7) r0 = 0 ; R0=0
7: (95) exit
--- kernel/bpf/verifier.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-)
kernel/bpf/verifier.c +24 -3
@@ -611,6 +611,13 @@ static bool is_atomic_load_insn(const struct bpf_insn *insn) insn->imm ==BPF_LOAD_ACQ ; } +static bool is_atomic_fetch_insn (const struct bpf_insn *insn) +{ +return BPF_CLASS (insn->code) ==BPF_STX && +BPF_MODE (insn->code) ==BPF_ATOMIC && + (insn->imm &BPF_FETCH ); +} +static int __get_spi (s32 off) {return (-off -1 ) /BPF_REG_SIZE ;
@@ -4323,10 +4330,24 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,* dreg still needs precision before this insn */ } - }else if (class ==BPF_LDX ||is_atomic_load_insn (insn)) { -if (!bt_is_reg_set (bt, dreg)) + }else if (class ==BPF_LDX || +is_atomic_load_insn (insn) || +is_atomic_fetch_insn (insn)) { +u32 load_reg = dreg; + +/* +* Atomic fetch operation writes the old value into +* a register (sreg or r0) and if it was tracked for +* precision, propagate to the stack slot like we do +* in regular ldx. +*/ +if (is_atomic_fetch_insn (insn)) + load_reg = insn->imm ==BPF_CMPXCHG ? +BPF_REG_0 : sreg; + +if (!bt_is_reg_set (bt, load_reg))return 0 ; -bt_clear_reg (bt, dreg); +bt_clear_reg (bt, load_reg);/* scalars can only be spilled into stack w/o losing precision. * Load from any other memory can be zero extended.
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 7/552 nsfs: tighten permission checks for handle opening
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Brauner <[email protected]>
[ Upstream commit d2324a9317f00013facb0ba00b00440e19d2af5e ]
Even privileged services should not necessarily be able to see other privileged service's namespaces so they can't leak information to each other. Use may_see_all_namespaces() helper that centralizes this policy until the nstree adapts.
--- fs/nsfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nsfs.c +1 -1
@@ -566,7 +566,7 @@ static struct dentry *nsfs_fh_to_dentry(struct super_block *sb, struct fid *fh,return ERR_PTR (-EOPNOTSUPP ); } -if (owning_ns && !ns_capable (owning_ns,CAP_SYS_ADMIN )) { +if (owning_ns && !may_see_all_namespaces ()) { ns->ops->put (ns);return ERR_PTR (-EPERM ); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 8/552 drm/amd/display: Avoid NULL dereference in dc_dmub_srv error paths
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srinivasan Shanmugam <[email protected]>
[ Upstream commit 4ae3e16f4b3bf64140f773629b765d605ee079a9 ]
In dc_dmub_srv_log_diagnostic_data() anddc_dmub_srv_enable_dpia_trace().
Both functions check:
if (!dc_dmub_srv || !dc_dmub_srv->dmub)
and then call DC_LOG_ERROR() inside that block.
DC_LOG_ERROR() uses dc_dmub_srv->ctx internally. So if dc_dmub_srv is NULL, the logging itself can dereference a NULL pointer and cause a crash.
Fix this by splitting the checks.
First check if dc_dmub_srv is NULL and return immediately. Then check dc_dmub_srv->dmub and log the error only when dc_dmub_srv is valid.
Fixes the below:../display/dc/dc_dmub_srv.c:962 dc_dmub_srv_log_diagnostic_data() error: we previously assumed 'dc_dmub_srv' could be null (see line 961) ../display/dc/dc_dmub_srv.c:1167 dc_dmub_srv_enable_dpia_trace() error: we previously assumed 'dc_dmub_srv' could be null (see line 1166)
--- drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +8 -2
@@ -949,7 +949,10 @@ void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv) {uint32_t i; -if (!dc_dmub_srv || !dc_dmub_srv->dmub) { +if (!dc_dmub_srv) +return ; + +if (!dc_dmub_srv->dmub) {DC_LOG_ERROR ("%s: invalid parameters." , __func__);return ; }
@@ -1146,7 +1149,10 @@ void dc_dmub_srv_enable_dpia_trace(const struct dc *dc) {struct dc_dmub_srv *dc_dmub_srv = dc->ctx->dmub_srv; -if (!dc_dmub_srv || !dc_dmub_srv->dmub) { +if (!dc_dmub_srv) +return ; + +if (!dc_dmub_srv->dmub) {DC_LOG_ERROR ("%s: invalid parameters." , __func__);return ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 9/552 platform/x86: lenovo-wmi-helpers: Fix memory leak in lwmi_dev_evaluate_int()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rong Zhang <[email protected]>
[ Upstream commit 0c3887a134f191723b53e2a47e501b534c8723ee ]
lwmi_dev_evaluate_int() leaks output.pointer when retval == NULL (found by sashiko.dev [1]).
Fix it by moving ret_obj = output.pointer' outside of the if (retval)' block so that it is always freed by the __free cleanup callback.
No functional change intended.
--- drivers/platform/x86/lenovo/wmi-helpers.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/platform/x86/lenovo/wmi-helpers.c +2 -2
@@ -45,7 +45,6 @@ int lwmi_dev_evaluate_int(struct wmi_device *wdev, u8 instance, u32 method_id, unsigned char *buf, size_t size, u32 *retval) { struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *ret_obj __free(kfree) = NULL;struct acpi_buffer input = { size, buf };acpi_status status;
@@ -54,8 +53,9 @@ int lwmi_dev_evaluate_int(struct wmi_device *wdev, u8 instance, u32 method_id,if (ACPI_FAILURE (status))return -EIO ; + union acpi_object *ret_obj __free(kfree) = output.pointer; +if (retval) { - ret_obj = output.pointer;if (!ret_obj)return -ENODATA ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 10/552 netfs: Fix missing locking around retry adding new subreqs
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Howells <[email protected]>
[ Upstream commit cce18c263e9623872327ba3c956012f73c1179cc ]
Fix netfs_retry_read_subrequests() and netfs_retry_write_stream() to take the appropriate lock when adding extra subrequests into stream->subrequests.
--- fs/netfs/read_retry.c | 6 +++++- fs/netfs/write_retry.c | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-)
fs/netfs/read_retry.c +5 -1
@@ -175,7 +175,9 @@ static void netfs_retry_read_subrequests(struct netfs_io_request *rreq)list_for_each_entry_safe_from (subreq, tmp, &stream->subrequests, rreq_link) {trace_netfs_sreq (subreq, netfs_sreq_trace_superfluous); +spin_lock (&rreq->lock);list_del (&subreq->rreq_link); +spin_unlock (&rreq->lock);netfs_put_subrequest (subreq, netfs_sreq_trace_put_done);if (subreq == to)break ;
@@ -203,8 +205,10 @@ static void netfs_retry_read_subrequests(struct netfs_io_request *rreq)refcount_read (&subreq->ref), netfs_sreq_trace_new); +spin_lock (&rreq->lock);list_add (&subreq->rreq_link, &to->rreq_link); - to =list_next_entry (to, rreq_link); +spin_unlock (&rreq->lock); + to = subreq;trace_netfs_sreq (subreq, netfs_sreq_trace_retry); stream->sreq_max_len =umin (len, rreq->rsize);
fs/netfs/write_retry.c +5 -1
@@ -130,7 +130,9 @@ static void netfs_retry_write_stream(struct netfs_io_request *wreq,list_for_each_entry_safe_from (subreq, tmp, &stream->subrequests, rreq_link) {trace_netfs_sreq (subreq, netfs_sreq_trace_discard); +spin_lock (&wreq->lock);list_del (&subreq->rreq_link); +spin_unlock (&wreq->lock);netfs_put_subrequest (subreq, netfs_sreq_trace_put_done);if (subreq == to)break ;
@@ -153,8 +155,10 @@ static void netfs_retry_write_stream(struct netfs_io_request *wreq, netfs_sreq_trace_new);trace_netfs_sreq (subreq, netfs_sreq_trace_split); +spin_lock (&wreq->lock);list_add (&subreq->rreq_link, &to->rreq_link); - to =list_next_entry (to, rreq_link); +spin_unlock (&wreq->lock); + to = subreq;trace_netfs_sreq (subreq, netfs_sreq_trace_retry); stream->sreq_max_len = len;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 11/552 drm/amd/display: Skip PHY SSC reduction on some 8K panels
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Roman Li <[email protected]>
[ Upstream commit 144169e7be0831e09958a906d08d1856751aa6c6 ]
[Why]
Some 8K displays cannot tolerate the reduced phy ssc value at high link utilization and show corruption or black screen.
[How]
Add an EDID panel-id quirk to utilize existing skip_phy_ssc_reduction flag.
To pass the link into the quirk handler, change the signature of apply_edid_quirks() to take link as an argument. The dev local in dm_helpers_parse_edid_caps() becomes unused and is removed.
Adjust for lack of HDMI 2.1 FRL in 6.18.y
--- .../drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +10 -3
@@ -56,8 +56,11 @@ static u32 edid_extract_panel_id(struct edid *edid) (u32 )EDID_PRODUCT_ID (edid); } -static void apply_edid_quirks (struct drm_device *dev,struct edid *edid,struct dc_edid_caps *edid_caps) +static void apply_edid_quirks (struct dc_link *link,struct edid *edid, +struct dc_edid_caps *edid_caps) { +struct amdgpu_dm_connector *aconnector = link->priv; +struct drm_device *dev = aconnector->base.dev;uint32_t panel_id =edid_extract_panel_id (edid);switch (panel_id) {
@@ -87,6 +90,11 @@ static void apply_edid_quirks(struct drm_device *dev, struct edid *edid, structdrm_dbg_driver (dev,"Disabling VSC on monitor with panel id %X\n" , panel_id); edid_caps->panel_patch.disable_colorimetry = true;break ; +/* Workaround for monitors that get corrupted by the PHY SSC reduction */ +case drm_edid_encode_panel_id ('D' ,'E' ,'L' ,0x4147 ): +drm_dbg_driver (dev,"Skip PHY SSC reduction on panel id %X\n" , panel_id); + link->wa_flags.skip_phy_ssc_reduction = true; +break ;default :return ; }
@@ -108,7 +116,6 @@ enum dc_edid_status dm_helpers_parse_edid_caps( {struct amdgpu_dm_connector *aconnector = link->priv;struct drm_connector *connector = &aconnector->base; -struct drm_device *dev = connector->dev;struct edid *edid_buf = edid ? (struct edid *) edid->raw_edid :NULL ;struct cea_sad *sads;int sad_count =-1 ;
@@ -138,7 +145,7 @@ enum dc_edid_status dm_helpers_parse_edid_caps( edid_caps->edid_hdmi = connector->display_info.is_hdmi; -apply_edid_quirks (dev, edid_buf, edid_caps); +apply_edid_quirks (link, edid_buf, edid_caps); sad_count =drm_edid_to_sad ((struct edid *) edid->raw_edid, &sads);if (sad_count <=0 )
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 12/552 drm/amd/display: Refactor amdgpu_dm_connector_detect (v2)
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf <[email protected]>
[ Upstream commit 8223a605744bb471f31018eac9075a539415b16f ]
Prepare for polling analog connectors.
Document the function better.
--- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +19 -16
@@ -7327,29 +7327,32 @@ create_stream_for_sink(struct drm_connector *connector,return stream; } +/** +* amdgpu_dm_connector_detect() - Detect whether a DRM connector is connected to a display +* +* A connector is considered connected when it has a sink that is not NULL. +* For connectors that support HPD (hotplug detection), the connection is +* handled in the HPD interrupt. +* +* Notes: +* 1. This interface is NOT called in context of HPD irq. +* 2. This interface *is called* in context of user-mode ioctl. Which +* makes it a bad place for *any* MST-related activity. +*/ static enum drm_connector_status amdgpu_dm_connector_detect (struct drm_connector *connector,bool force) { -bool connected;struct amdgpu_dm_connector *aconnector =to_amdgpu_dm_connector (connector); -/* -* Notes: -* 1. This interface is NOT called in context of HPD irq. -* 2. This interface *is called* in context of user-mode ioctl. Which -* makes it a bad place for *any* MST-related activity. -*/ - -if (aconnector->base.force ==DRM_FORCE_UNSPECIFIED && - !aconnector->fake_enable) - connected = (aconnector->dc_sink !=NULL ); -else - connected = (aconnector->base.force ==DRM_FORCE_ON || - aconnector->base.force ==DRM_FORCE_ON_DIGITAL ); -update_subconnector_property (aconnector); -return (connected ? connector_status_connected : +if (aconnector->base.force ==DRM_FORCE_ON || + aconnector->base.force ==DRM_FORCE_ON_DIGITAL ) +return connector_status_connected; +else if (aconnector->base.force ==DRM_FORCE_OFF ) +return connector_status_disconnected; + +return (aconnector->dc_sink ? connector_status_connected : connector_status_disconnected); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 13/552 drm/amd/display: hide Apple Studio Display secondary tile
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jerry Zuo <[email protected]>
[ Upstream commit 49521be4809d63fe3efb6bc68ee11cb1e1ef3d63 ]
The Apple Studio Display exposes a 2x1 tiled panel over two SST DP links. The primary tile advertises the full 5120x2880 mode (with DSC on the bandwidth-sufficient link) while the secondary carries a per-tile 2560x2880 timing on a link without sufficient bandwidth. Report the non-primary tile connector as disconnected during detect so compositors only see the primary DP link and configure a single 5K mode instead of driving both tiled streams independently.
Drive the behaviour from an EDID quirk: add a disable_second_tile panel patch that apply_edid_quirks() sets for the affected Apple Studio Display panel IDs (0xAE3A, 0xAE42, 0xAE46), and have detect() hide the secondary tile when the sink carries that quirk.
Adjust for lack of movement from amdgpu_dm.c to amdgpu_dm_connector.c Adjust for lack of analog connector support.
--- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 36 +++++++++++++++++++ .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 11 ++++++ drivers/gpu/drm/amd/display/dc/dc_types.h | 1 + 3 files changed, 48 insertions(+)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +36 -0
@@ -7327,6 +7327,39 @@ create_stream_for_sink(struct drm_connector *connector,return stream; } +/* +* Apple Studio Display exposes two SST DP links for a 2x1 tiled panel. +* The primary tile advertises the full 5120x2880 mode (with DSC on the +* bandwidth-sufficient link) while the secondary carries a per-tile +* 2560x2880 timing on a insufficient bandwidth link. Hide the secondary +* connector from userspace so compositors configure a single 5K stream +* on the primary link only. +*/ +static bool amdgpu_dm_hide_secondary_tile_from_userspace (struct drm_connector *connector) +{ +struct amdgpu_dm_connector *aconnector =to_amdgpu_dm_connector (connector); + +if (!aconnector->dc_sink) +return false; + +if (!aconnector->dc_sink->edid_caps.panel_patch.disable_second_tile) +return false; + +drm_edid_connector_update (connector, aconnector->drm_edid); + +if (!connector->has_tile) +return false; + +if (!connector->tile_h_loc && !connector->tile_v_loc) +return false; + +drm_dbg_kms (connector->dev, +"[CONNECTOR:%d:%s] hiding secondary Apple Studio Display tile from userspace\n" , + connector->base.id, connector->name); + +return true; +} +/** * amdgpu_dm_connector_detect() - Detect whether a DRM connector is connected to a display *
@@ -7352,6 +7385,9 @@ amdgpu_dm_connector_detect(struct drm_connector *connector, bool force)else if (aconnector->base.force ==DRM_FORCE_OFF )return connector_status_disconnected; +if (amdgpu_dm_hide_secondary_tile_from_userspace (connector)) +return connector_status_disconnected; +return (aconnector->dc_sink ? connector_status_connected : connector_status_disconnected); }
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +11 -0
@@ -95,6 +95,17 @@ static void apply_edid_quirks(struct dc_link *link, struct edid *edid,drm_dbg_driver (dev,"Skip PHY SSC reduction on panel id %X\n" , panel_id); link->wa_flags.skip_phy_ssc_reduction = true;break ; +/* +* Workaround for Apple Studio Display which exposes a 2x1 tiled panel +* over two SST DP links. Hide the secondary tile from userspace so +* compositors drive a single 5K stream on the primary link only. +*/ +case drm_edid_encode_panel_id ('A' ,'P' ,'P' ,0xAE3A ): +case drm_edid_encode_panel_id ('A' ,'P' ,'P' ,0xAE42 ): +case drm_edid_encode_panel_id ('A' ,'P' ,'P' ,0xAE46 ): +drm_dbg_driver (dev,"Hiding secondary tile on panel id %X\n" , panel_id); + edid_caps->panel_patch.disable_second_tile = true; +break ;default :return ; }
drivers/gpu/drm/amd/display/dc/dc_types.h +1 -0
@@ -178,6 +178,7 @@ struct dc_panel_patch {unsigned int skip_audio_sab_check;unsigned int mst_start_top_delay;unsigned int remove_sink_ext_caps; +bool disable_second_tile;unsigned int disable_colorimetry;uint8_t blankstream_before_otg_off;bool oled_optimize_display_on;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 14/552 drm/amd/display: Prune per-tile Timing from Apple Studio Display Primary Tile
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fangzhi Zuo <[email protected]>
[ Upstream commit 7a4dd08c3f921576c6a7524f60e4f0e4601835d2 ]
[why]
The Apple Studio Display primary tile advertises both the full 5120x2880 mode and the per-tile 2560x2880 timing. With the secondary tile already hidden from userspace, the stray 2560x2880 mode on the primary connector can still be picked by compositors, defeating the single 5K stream goal.
[how]
Prune the per-tile timing from the primary connector during get_modes:
when the sink carries the disable_second_tile quirk and the connector is the primary tile (tile_h_loc == 0 && tile_v_loc == 0), drop any probed mode matching the advertised tile size (tile_h_size x tile_v_size) so userspace only sees the full 5120x2880 mode.
Adjust for lack of movement from amdgpu_dm.c to amdgpu_dm_connector.c
--- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +43 -0
@@ -8540,6 +8540,47 @@ static void amdgpu_dm_connector_add_common_modes(struct drm_encoder *encoder, } } +/* +* The Apple Studio Display primary tile advertises both the full 5120x2880 +* mode and the per-tile 2560x2880 timing. As the secondary tile is hidden from +* userspace (see amdgpu_dm_hide_secondary_tile_from_userspace()), drop the +* per-tile timing from the primary connector so compositors only pick the full +* 5K mode. +*/ +static void amdgpu_dm_prune_primary_tile_modes (struct drm_connector *connector) +{ +struct amdgpu_dm_connector *aconnector =to_amdgpu_dm_connector (connector); +struct drm_display_mode *mode, *t; + +if (!aconnector->dc_sink) +return ; + +if (!aconnector->dc_sink->edid_caps.panel_patch.disable_second_tile) +return ; + +if (!connector->has_tile) +return ; + +/* Only prune the per-tile timing from the primary tile. */ +if (connector->tile_h_loc || connector->tile_v_loc) +return ; + +list_for_each_entry_safe (mode, t, &connector->probed_modes, head) { +if (mode->hdisplay != connector->tile_h_size || + mode->vdisplay != connector->tile_v_size) +continue ; + +drm_dbg_kms (connector->dev, +"[CONNECTOR:%d:%s] pruning per-tile %dx%d timing from primary Apple Studio Display tile\n" , + connector->base.id, connector->name, + mode->hdisplay, mode->vdisplay); + +list_del (&mode->head); +drm_mode_destroy (connector->dev, mode); + aconnector->num_modes--; + } +} +static void amdgpu_set_panel_orientation (struct drm_connector *connector) {struct drm_encoder *encoder;
@@ -8582,6 +8623,8 @@ static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector, amdgpu_dm_connector->num_modes =drm_edid_connector_add_modes (connector); +amdgpu_dm_prune_primary_tile_modes (connector); +/* sorting the probed modes before calling function * amdgpu_dm_get_native_mode() since EDID can have * more than one preferred mode. The modes that are
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 15/552 alpha: fix ieee_swcr_to_fpcr setting FPCR_DNOD unconditionally
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matt Turner <[email protected]>
commit 49672d026cc4773608e1222b69b29fd70f41336b upstream.
ieee_swcr_to_fpcr() converts the software IEEE trap-enable and status bits kept in thread_info.ieee_state into the hardware FPCR format. It contained:
fp |= (~sw & IEEE_TRAP_ENABLE_DNO) << 41;
FPCR_DNOD (bit 47) disables denormal operand traps: with it set the hardware handles a denormal operand itself, treating it as zero, instead of trapping for software completion. The intent was to set DNOD when the user has not asked for SIGFPE on denormal operands, but IEEE_TRAP_ENABLE_DNO is clear by default, so ieee_swcr_to_fpcr(0) always set DNOD.
Instructions built with the software completion suffix therefore never trapped on a denormal operand. The hardware silently substituted zero and produced wrong results, affecting every program compiled with -mieee and default FPU settings, glibc included.
Set FPCR_DNOD only when IEEE_MAP_DMZ is requested, which is exactly the case where flushing denormal inputs to zero is what the user asked for. DNOD then encodes MAP_DMZ, which ieee_fpcr_to_swcr() already recovers from FPCR_DNZ, so drop its attempt to recover IEEE_TRAP_ENABLE_DNO from DNOD; the DNO trap enable lives solely in ieee_state.
Both functions are in a uapi header, so the encoding change is visible to userspace, but nothing outside the kernel is known to depend on DNOD carrying the DNO trap enable, and the kernel is the only writer of the FPCR.
This must not be backported on its own. Re-enabling denormal operand traps exposes a second bug, fixed in the following patch: those traps usually find an exact result, and for an exact result the emulator did not write the FPCR back, leaving hardware-fabricated exception bits visible to user space. Taken alone this change would make spurious exception flags more common.
The bug predates the git history, so there is no commit to reference in a Fixes tag.
--- arch/alpha/include/uapi/asm/fpu.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
arch/alpha/include/uapi/asm/fpu.h +6 -2
@@ -101,7 +101,12 @@ ieee_swcr_to_fpcr(unsigned long sw) | IEEE_TRAP_ENABLE_OVF)) << 48; fp |= (~sw & (IEEE_TRAP_ENABLE_UNF |IEEE_TRAP_ENABLE_INE )) <<57 ; fp |= (sw &IEEE_MAP_UMZ ?FPCR_UNDZ |FPCR_UNFD :0 ); - fp |= (~sw &IEEE_TRAP_ENABLE_DNO ) <<41 ; +/* +* Disable denormal operand traps only when denormal inputs are to be +* flushed to zero. Otherwise they must keep trapping, so that /S +* instructions reach the kernel emulation handler. +*/ + fp |= (sw &IEEE_MAP_DMZ ?FPCR_DNOD :0 );return fp; }
@@ -116,7 +121,6 @@ ieee_fpcr_to_swcr(unsigned long fp) | IEEE_TRAP_ENABLE_OVF); sw |= (~fp >>57 ) & (IEEE_TRAP_ENABLE_UNF |IEEE_TRAP_ENABLE_INE ); sw |= (fp >>47 ) &IEEE_MAP_UMZ ; - sw |= (~fp >>41 ) &IEEE_TRAP_ENABLE_DNO ;return sw; }
Greg Kroah-Hartman
maintainerPATCH 16/552 rust: time: fix as_micros_ceil() rounding near i64::MAX
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: FUJITA Tomonori <[email protected]>
commit ec90dfcf05f02206c280bb59af660bbb3ae177d0 upstream.
The ceiling adjustment used saturating_add(NSEC_PER_USEC - 1) before dividing. Once the nanosecond value gets within NSEC_PER_USEC - 1 of i64::MAX the addition saturates to i64::MAX, which drops the ceiling bias and can yield a result one microsecond too small.
--- rust/kernel/time.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-)
rust/kernel/time.rs +10 -7
@@ -421,22 +421,25 @@ impl Delta {/// to the value in the [`Delta`]. #[inline] pub fn as_micros_ceil (self) ->i64 { +// Only positive values need to be rounded up: truncating division already +// rounds towards zero, i.e. up, for negative values. +// +// The usual `(nanos + d - 1) / d` is not used because the addition overflows +// once `nanos` exceeds `i64::MAX - (d - 1)`; saturating the addition instead +// would drop the rounding bias and return a result one unit too small. let n = self.as_nanos (); -let n =if n >=0 { - n.saturating_add (NSEC_PER_USEC -1 ) - }else { - n - }; + +let (n, add) =if n >0 { (n -1 ,1 ) }else { (n,0 ) };#[cfg( CONFIG_64BIT )] { - n /NSEC_PER_USEC + n /NSEC_PER_USEC + add }#[cfg(not( CONFIG_64BIT ))] // SAFETY: It is always safe to call `ktime_to_us()` with any value. unsafe { - bindings::ktime_to_us (n) + bindings::ktime_to_us (n) + add } }
Greg Kroah-Hartman
maintainerPATCH 17/552 alpha: dont leak hardware-fabricated FP exception bits to user space
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matt Turner <[email protected]>
commit bcfe3187412e342b4619efb92c945f073855ebc0 upstream.
On EV6 and later the hardware records exception status bits in the FPCR before delivering a software completion trap, and those bits can be wrong for the instruction that trapped. Converting a double that is exactly representable as a subnormal float sets FPCR_UNF even though the result is exact, and an underflow trap additionally sets FPCR_INE even when the emulated operation turns out to be exact.
alpha_fp_emul() only wrote the FPCR when soft-fp raised an exception, so whenever it determined that the instruction was exact the fabricated bits stayed in the FPCR and were reported to user space by fetestexcept().
Pass the exception summary register down from do_entArith() so the handler can tell which exceptions the hardware attributed to the trapping instruction, and always write the FPCR. Clear the exceptions that the trap reported but that soft-fp did not raise. EXC_SUM reports only the underflow or overflow when the hardware also set INE, so treat INE as a candidate in that case, and treat a trap with no reported exception as a denormal operand trap, for which the hardware can fabricate INE and UNF as well. Bits that software has already confirmed in ieee_state belong to this or an earlier instruction and are never cleared.
The imprecise path passes no summary. There the trap was taken somewhere in the trap shadow, so EXC_SUM is not attribution for the instruction being re-executed -- and only EV6, which traps precisely and so never takes that path, has fabricated bits to clear. For the same reason the clearing is guarded by implver(), matching swcr_update_status().
On an UP1500 (EV68) this takes the glibc math testsuite from 831 failures to 28, the remainder being unrelated to exception status.
This belongs with the preceding fix to ieee_swcr_to_fpcr(), and should not be backported without it -- nor it without this. That fix stops FPCR_DNOD being set unconditionally, so denormal operand traps start firing again. Those traps very often find an exact result, which is precisely the case where the old code left the FPCR unwritten and the fabricated bits visible. Applied alone it would make spurious exception flags more common, not less.
One case cannot be resolved here: an inexact instruction without the software completion suffix never traps, so its INE reaches the FPCR without being recorded anywhere else. Such a bit is indistinguishable from an INE the hardware fabricated for a trapping instruction, and is lost if an underflow or overflow trap with an exact result follows it. The FPCR is the only record of those instructions and it carries no attribution.
The bug predates the git history, so there is no commit to reference in a Fixes tag.
--- arch/alpha/kernel/traps.c | 6 +-- arch/alpha/math-emu/math.c | 88 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 80 insertions(+), 14 deletions(-)
arch/alpha/kernel/traps.c +3 -3
@@ -166,12 +166,12 @@ static long dummy_emul(void) { return 0;long (*alpha_fp_emul_imprecise)(struct pt_regs *regs,unsigned long writemask) = (void *)dummy_emul;EXPORT_SYMBOL_GPL (alpha_fp_emul_imprecise); -long (*alpha_fp_emul) (unsigned long pc) +long (*alpha_fp_emul) (unsigned long pc,unsigned long summary) = (void *)dummy_emul;EXPORT_SYMBOL_GPL (alpha_fp_emul);#else long alpha_fp_emul_imprecise (struct pt_regs *regs,unsigned long writemask); -long alpha_fp_emul (unsigned long pc); +long alpha_fp_emul (unsigned long pc,unsigned long summary);#endif asmlinkage void
@@ -185,7 +185,7 @@ do_entArith(unsigned long summary, unsigemulate the instruction. If the processor supports precise exceptions, we don't have to search. */ if (!amask (AMASK_PRECISE_TRAP )) - si_code =alpha_fp_emul (regs->pc -4 ); + si_code =alpha_fp_emul (regs->pc -4 , summary);else si_code =alpha_fp_emul_imprecise (regs, write_mask);if (si_code ==0 )
arch/alpha/math-emu/math.c +77 -11
125 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 18/552 clocksource/drivers/nxp-pit: Fix IRQ leak on cpuhp_setup_state error path
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: WenTao Liang <[email protected]>
commit 05520e035f8332c8e33f3011b5ca016fde61793d upstream.
When cpuhp_setup_state fails after pit_clockevent_per_cpu_init has successfully called request_irq, the error handling jumps directly to out_pit_clocksource_unregister without freeing the registered IRQ.
This leaks the IRQ line and, since kfree(pit) follows, leaves a dangling pointer registered as the interrupt handler's dev_id, potentially leading to a use-after-free if the IRQ fires afterwards.
Fix it by calling pit_clockevent_per_cpu_exit to properly release the IRQ before falling through to the existing cleanup chain.
--- drivers/clocksource/timer-nxp-pit.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/clocksource/timer-nxp-pit.c +3 -1
@@ -328,8 +328,10 @@ static int pit_timer_init(struct device_if (pit_instances == max_pit_instances) { ret =cpuhp_setup_state (CPUHP_AP_ONLINE_DYN ,"PIT timer:starting" , pit_clockevent_starting_cpu,NULL ); -if (ret <0 ) +if (ret <0 ) { +pit_clockevent_per_cpu_exit (pit, pit_instances); goto out_pit_clocksource_unregister; + } }return 0 ;
Greg Kroah-Hartman
maintainerPATCH 19/552 clocksource/drivers/timer-sun4i: Advertise a real minimum delta
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Yan <[email protected]>
commit d21808328225ab8cee46885bf9a0dffcefbe630e upstream.
sun4i_clkevt_next_event() compensates for the timer stop/start synchronization delay by programming evt - TIMER_SYNC_TICKS into the hardware interval register. The clockevent device currently advertises TIMER_SYNC_TICKS as min_delta_ticks, so the clockevents core is allowed to call set_next_event() with evt == TIMER_SYNC_TICKS.
That programs a zero-tick interval. With oneshot/highres/nohz timer operation this can leave the next event stuck, which was observed as a boot hang on Allwinner D1 after the clockevents core started reusing forced minimum-delta events.
Advertise one extra tick instead, so the smallest event accepted by the core still programs at least one hardware tick after the synchronization compensation.
--- drivers/clocksource/timer-sun4i.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/clocksource/timer-sun4i.c +1 -1
@@ -208,7 +208,7 @@ static int __init sun4i_timer_init(strucsun4i_timer_clear_interrupt (timer_of_base (&to));clockevents_config_and_register (&to.clkevt,timer_of_rate (&to), -TIMER_SYNC_TICKS ,0xffffffff ); +TIMER_SYNC_TICKS +1 ,0xffffffff );/* Enable timer0 interrupt */ val =readl (timer_of_base (&to) +TIMER_IRQ_EN_REG );
Greg Kroah-Hartman
maintainerPATCH 20/552 fs: fix user path of nested backing files
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baokun Li <[email protected]>
commit f2381b546e7e6a35c9fcee0d0ccb6c042a9aeb5d upstream.
backing_file_open() derives the path to be stored in the new backing file from user_file->f_path. This is incorrect when user_file itself is a backing file, which is the case for nested stacking filesystems, e.g. overlayfs mounts where the lowerdir of one overlayfs is the merged directory of another. Since commit def3ae83da02 ("fs: store real path instead of fake path in backing file f_path") the f_path of a backing file holds the real path of the intermediate layer, not the path that the user opened.
Commit 924577e4f6ca ("ovl: Fix nested backing file paths") fixed this for such configurations by passing file_user_path() from ovl_open_realfile(). However, commit 6af36aeb147a ("lsm: add backing_file LSM hooks") changed the first argument of backing_file_open() from the user path back to the user file and derived the path from user_file->f_path again, silently re-introducing the problem.
As a result, files mapped through a nested overlayfs show the wrong path in /proc/<pid>/maps and in perf/ftrace mmap records. For example, with two nested overlayfs mounts:
mkdir -p /ovl/{lower,upper,work,merged} /ovl/nested echo hello > /ovl/lower/foo
mount -t overlay overlay \ -o lowerdir=/ovl/lower,upperdir=/ovl/upper,workdir=/ovl/work \ /ovl/merged # at least two lowerdirs are needed when upperdir is nonexistent mount -t overlay overlay \ -o lowerdir=/ovl/merged:/ovl/lower /ovl/nested
mapping /ovl/nested/foo shows a disconnected path instead of the user path:
# readlink /proc/self/fd/3 /ovl/nested/foo # grep foo /proc/self/maps 7f6e2c100000-7f6e2c101000 r--s 00000000 00:24 15813027 /foo
The bogus path is derived from the f_path of the intermediate backing file, whose mount is a private clone that d_path() cannot resolve.
Fix this by using file_user_path(), which returns the outermost user-visible path for backing files and falls back to &user_file->f_path for regular files. This restores the behavior of commit 924577e4f6ca ("ovl: Fix nested backing file paths") for overlayfs and also fixes the same problem for the other backing_file_open() callers, fuse passthrough and erofs ishare, when their user file is itself a backing file.
backing_tmpfile_open() has the same pattern but is not affected: it is only called by ovl_create_tmpfile() for the upper layer, and another overlayfs is rejected as upperdir by the DCACHE_OP_REAL check in ovl_mount_dir_check(), so its user_file can never be a backing file.
--- fs/backing-file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/backing-file.c +1 -1
@@ -34,7 +34,7 @@ struct file *backing_file_open(const strconst struct path *real_path, const struct cred *cred) { - const struct path *user_path = &user_file->f_path; + const struct path *user_path = file_user_path(user_file);struct file *f;int error;
Greg Kroah-Hartman
maintainerPATCH 21/552 powerpc/pseries/iommu: switch to Default DMA window during kdump
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gaurav Batra <[email protected]>
commit 1304643a1c20badbb91b86a5084dd76cb7620c05 upstream.
In PowerPC (pseries) a non-virtualized adapter will have 2 DMA windows - 2GB default and a larger Dynamic DMA Window (DDW). DDW is large enough to map total RAM to a device.
During normal functioning of OS, since RAM is pre-mapped, 2GB default window is not used. The only scenario it might get used is when buffers in pmemory are mapped to the device for DMA.
As of today, during kdump, during early device discovery, pci_dma_find() finds that the device has 2 DMA windows. It selects to use DDW. This is a kdump path and DMA window is needed for IO to the device.
Although commit 09a3c1e46142 ("powerpc/pseries/iommu: IOMMU table is not initialized for kdump over SR-IOV") fixed an issue during kdump with SR-IOV case, but this also made the kdump prefer DDW over the default DMA window when both are present (dedicated adapter case). Since the DDW is fully mapped by the previous kernel, iommu_table_clear() can free only KDUMP_MIN_TCE_ENTRIES (2048) TCEs for use by kdump kernel.
This is not enough when the dump device is NVMe over Fibre Channel. Because nvme-fc driver DMA-maps the cmds and resp IUs of every pre-allocated request and each such mapping consumes roughly:
32 (IO queues, one per cpus = nr_cpus) *
64 (queue_depth, blk-mq kdump limit) *
2 (cmd+resp) = 4096
This is already double of what we have without counting admin queues and lpfc driver's own allocations / mapping requirement. Hence this results into iommu_alloc failures like -
lpfc 0153:70:00.0: iommu_alloc failed,
tbl 0000000034ebcf5e vaddr 00000000d814df0b npages 1 lpfc 0153:70:00.0: FCP Op failed - cmdiu dma mapping failed. lpfc 0153:70:00.0: iommu_alloc failed,
tbl 0000000034ebcf5e vaddr 000000009779e4d2 npages 1 lpfc 0153:70:00.0: FCP Op failed - cmdiu dma mapping failed.
iommu_map_phys+0x1c4/0x1f0 (unreliable) dma_iommu_map_phys+0x54/0xa0 dma_map_phys+0x3f8/0x590 __nvme_fc_init_request+0x110/0x300 [nvme_fc] nvme_fc_init_request+0x60/0xb8 [nvme_fc] blk_mq_alloc_map_and_rqs+0x388/0x510 blk_mq_alloc_tag_set+0x2a4/0x5f0 nvme_alloc_io_tag_set+0xe0/0x1e0 [nvme_core] nvme_fc_connect_ctrl_work+0x85c/0xdac [nvme_fc] process_one_work+0x1e4/0x5a0 worker_thread+0x1ec/0x3e0
Increasing the number of free TCE entries in iommu_table_clear() will increase the probability of hitting EEH since there could still be some active IOs from the previous life of the kernel.
Hence this patch partially reverts the previous fixes commit and switches the kdump's default back to 2GB default DMA window instead of DDW window. This window will mostly be empty. Or, could be slightly used if buffers in pmemory were mapped for IO.
--- arch/powerpc/platforms/pseries/iommu.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-)
arch/powerpc/platforms/pseries/iommu.c +12 -11
@@ -812,18 +812,11 @@ static struct device_node *pci_dma_find(/* parse DMA window property. During normal system boot, only default * DMA window is passed in OF. But, for kdump, a dedicated adapter might -* have both default and DDW in FDT. In this scenario, DDW takes precedence -* over default window. +* have both default and DDW in FDT. In this scenario, default window +* takes precedence over DDW. For a dedicated adapter, default window will +* potentially have more unused TCEs. */ -if (ddw_win) { -struct dynamic_dma_window_prop *p; - - p = (struct dynamic_dma_window_prop *)ddw_prop; - prop->liobn = p->liobn; - prop->dma_base = p->dma_base; - prop->tce_shift = p->tce_shift; - prop->window_shift = p->window_shift; - }else if (default_win) { +if (default_win) {unsigned long offset, size, liobn;of_parse_dma_window (rdn, default_prop, &liobn, &offset, &size);
@@ -832,6 +825,14 @@ static struct device_node *pci_dma_find( prop->dma_base =cpu_to_be64 (offset); prop->tce_shift =cpu_to_be32 (IOMMU_PAGE_SHIFT_4K ); prop->window_shift =cpu_to_be32 (order_base_2 (size)); + }else { +struct dynamic_dma_window_prop *p; + + p = (struct dynamic_dma_window_prop *)ddw_prop; + prop->liobn = p->liobn; + prop->dma_base = p->dma_base; + prop->tce_shift = p->tce_shift; + prop->window_shift = p->window_shift; }return rdn;
Greg Kroah-Hartman
maintainerPATCH 22/552 timers/itimer: Zero-init old itimerval before copy to userspace
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jérémy Jean <[email protected]>
commit 18c7d85864e554adc8fad1e8d2e9d2cb6c3911c8 upstream.
On native sparc64, struct __kernel_old_timeval contains a four-byte hole after tv_usec because tv_sec is 64-bit while __kernel_suseconds_t is 32-bit. put_itimerval() fills only the named fields in a stack-allocated __kernel_old_itimerval and copies the entire object to userspace, so getitimer() can expose the two padding holes.
Zero-initialize the aggregate before assigning the fields so implicit padding is deterministic before it crosses the user/kernel boundary.
--- kernel/time/itimer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/time/itimer.c +1 -1
@@ -100,7 +100,7 @@ static int do_getitimer(int which, strucstatic int put_itimerval (struct __kernel_old_itimerval __user *o,const struct itimerspec64 *i) { -struct __kernel_old_itimerval v; +struct __kernel_old_itimerval v = {}; v.it_interval.tv_sec = i->it_interval.tv_sec; v.it_interval.tv_usec = i->it_interval.tv_nsec /NSEC_PER_USEC ;
Greg Kroah-Hartman
maintainerPATCH 23/552 rust: bug: skip arch-specific asm in `testlib` builds
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: FUJITA Tomonori <[email protected]>
commit 5d9668f3930609ead91f39b059ef4fe53db04942 upstream.
Running make rusttest with ARCH= set to an architecture other than the host's fails, e.g. ARCH=arm64 on an x86_64 host:
error: invalid instruction mnemonic 'brk'
--> rust/kernel/bug.rs:63:17
|
63 | / concat!(
64 | | "/* {size} */",
65 | | include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_warn_asm.rs")),
66 | | include!(concat!(env!("OBJTREE"), "/rust/kernel/generated_arch_reachable_asm.rs")));
| |_______________________________________________________________________________________________________^
|
note: instantiated into assembly here
--> <inline asm>:1:115
|
1 | /* 8 */.pushsection __bug_table,"aw"; .align 2; 14470: .long 14471f - .;.short 2305;.align 2; .popsection; 14471:brk 0x800
| ^^^The reason is that rusttest builds the kernel crate as a host
library: it passes the CONFIG_* cfgs of the configured architecture, but not --target, so code generation happens for the host. warn_flags! then selects the arch-specific inline asm arm based on CONFIG_*, and the host assembler rejects it.
This does not happen with the current master because warn_on! has no user inside the kernel crate itself yet, but it will as soon as one is added.
--- rust/kernel/bug.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
rust/kernel/bug.rs +5 -1
@@ -8,6 +8,7 @@#[macro_export] #[doc(hidden)] +#[cfg(not(testlib))] #[cfg(all( CONFIG_BUG , not( CONFIG_UML ), not( CONFIG_LOONGARCH ), not( CONFIG_ARM )))] #[cfg( CONFIG_DEBUG_BUGVERBOSE )] macro_rules! warn_flags {
@@ -47,6 +48,7 @@ macro_rules! warn_flags {#[macro_export] #[doc(hidden)] +#[cfg(not(testlib))] #[cfg(all( CONFIG_BUG , not( CONFIG_UML ), not( CONFIG_LOONGARCH ), not( CONFIG_ARM )))] #[cfg(not( CONFIG_DEBUG_BUGVERBOSE ))] macro_rules! warn_flags {
@@ -73,6 +75,7 @@ macro_rules! warn_flags {#[macro_export] #[doc(hidden)] +#[cfg(not(testlib))] #[cfg(all( CONFIG_BUG , CONFIG_UML ))] macro_rules! warn_flags { ($flags:expr) => {
@@ -91,6 +94,7 @@ macro_rules! warn_flags {#[macro_export] #[doc(hidden)] +#[cfg(not(testlib))] #[cfg(all( CONFIG_BUG , any( CONFIG_LOONGARCH , CONFIG_ARM )))] macro_rules! warn_flags { ($flags:expr) => {
@@ -101,7 +105,7 @@ macro_rules! warn_flags {#[macro_export] #[doc(hidden)] -#[cfg(not( CONFIG_BUG ))] +#[cfg(any(testlib, not( CONFIG_BUG )))] macro_rules! warn_flags { ($flags:expr) => {}; }
Greg Kroah-Hartman
maintainerPATCH 24/552 rust: bug: fix warn_on macro build error on UML
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: FUJITA Tomonori <[email protected]>
commit 30a449e04a32033d8e4844fdb4938a0ebccfa37b upstream.
Callers that go through kernel::prelude have CStrExt in scope, but code inside the kernel crate imports explicitly and may not. Using warn_on! from such a module fails to build on UML, which is the only configuration where warn_flags! needs a C string pointer rather than an inline asm bug entry:
error[E0599]: no method named as_char_ptr found for reference &ffi::CStr in the current scope
--> linux/rust/kernel/bug.rs:83:49
|
83 | $crate::c_str!(::core::file!()).as_char_ptr(),
| ^^^^^^^^^^^
|
::: linux/rust/kernel/time.rs:427:9
|
427 | warn_on!(self.nanos < 0);
| ------------------------ in this macro invocation
| = help: items from traits can only be used if the trait is in scope
= note: this error originates in the macro $crate::warn_flags which comes from the expansion of the macro warn_on (in Nightly builds, run with -Z mac)
help: trait CStrExt which provides as_char_ptr is implemented but not in scope; perhaps you want to import it
--> linux/rust/kernel/time.rs:27:1
|
27 + use crate::str::CStrExt;
Call the method through its fully qualified path, which resolves without any import at the expansion site.
--- rust/kernel/bug.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
rust/kernel/bug.rs +1 -1
@@ -83,7 +83,7 @@ macro_rules! warn_flags {// with a valid null-terminated string. unsafe { $crate::bindings::warn_slowpath_fmt ( - $crate::c_str!(::core::file!()).as_char_ptr (), + $crate::str::CStrExt ::as_char_ptr ($crate::c_str!(::core::file!())),line! ()as $crate::ffi::c_int , $flagsas $crate::ffi::c_uint , ::core::ptr::null(),
Re: [PATCH 6.18 024/552] rust: bug: fix warn_on macro build error on UML
Quoted 2 lines · Greg Kroah-Hartman
+ $crate::str::CStrExt::as_char_ptr($crate::c_str!(::core::file!())),
In 6.18.y, this needs to be:
$crate::str::CStr::as_char_ptr($crate::c_str!(::core::file!())),
Cheers,
Miguel
Re: [PATCH 6.18 024/552] rust: bug: fix warn_on macro build error on UML
Quoted 4 lines · Miguel Ojeda
In 6.18.y, this needs to be:
$crate::str::CStr::as_char_ptr($crate::c_str!(::core::file!())),
Or we can just drop the patch, since it is still our CStr in this branch.
Cheers,
Miguel
Greg Kroah-Hartman
maintainerRe: [PATCH 6.18 024/552] rust: bug: fix warn_on macro build error on UML
In reply to Miguel OjedaQuoted 8 lines · Miguel Ojeda
Quoted 2 lines · Greg Kroah-Hartman
+ $crate::str::CStrExt::as_char_ptr($crate::c_str!(::core::file!())),
In 6.18.y, this needs to be:
$crate::str::CStr::as_char_ptr($crate::c_str!(::core::file!())),
Ok, now dropped for 6.18 and 6.12.y, thanks.
greg k-h
Greg Kroah-Hartman
maintainerPATCH 25/552 rust: kernel: list: fix incorrect pop_back example comment
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikolai Grlica <[email protected]>
commit a5c7d35e2fd3e24c411816c91f8f6cc78e652e0c upstream.
The example uses pop_back(), but the accompanying comment says pop_front(). Update the comment to match the example.
--- rust/kernel/list.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
rust/kernel/list.rs +1 -1
@@ -233,7 +233,7 @@ pub use self::arc_field::{define_list_ar/// assert_eq!(list.iter().count(), 3); /// } /// -/// // Pop the items from the list using `pop_front()` and verify the content. +/// // Pop the items from the list using `pop_back()` and verify the content. /// { /// assert_eq!(list.pop_back().ok_or(EINVAL)?.value.foo(), ("a", 15)); /// assert_eq!(list.pop_back().ok_or(EINVAL)?.value.foo(), ("a", 32));
Greg Kroah-Hartman
maintainerPATCH 26/552 rust: cfi: disable function merging if CFI is enabled
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gary Guo <[email protected]>
commit 29b03d1de967a177176d12811d970cac7882afcf upstream.
In Rust doc tests, there is a dummy __module_firmware_test_init function generated by the example in module_firmware!'s documentation, which just returns zero. Many other documentation examples generate functions that produce zero. LKP test robot reports [1] a Flags::zeroed instance; my local reproduction has a Bounded::new::<0>.
LLVM's MergeFunctionsPass incorrectly merges functions with different KCFI types, causing __module_firmware_test_init to be merged into one of the zero-returning functions. As module init is invoked via an indirect function call, KCFI is checked and this produces a KCFI failure.
I've reported this bug to upstream LLVM [2]; in the meantime, disable function merging if CFI is enabled. No separate treatment is needed for CONFIG_RUST_INLINE_HELPERS, as Clang does not enable function merging by default.
[ LLVM already has a pending PR:
https://github.com/llvm/llvm-project/pull/217665
which solves the issue. In addition, I asked upstream Rust if the unstable -Zmerge-functions=disabled flag will remain around:
https://rust-lang.zulipchat.com/#narrow/channel/425075-rust-for-linux/topic/.60-Zmerge-functions.3Ddisabled.60/
and it does indeed look like that will be the case. - Miguel ]
--- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
Makefile +2 -1
@@ -1037,7 +1037,8 @@ endif ifdef CONFIG_RUST # Always pass -Zsanitizer-cfi-normalize-integers as CONFIG_RUST selects # CONFIG_CFI_ICALL_NORMALIZE_INTEGERS. - RUSTC_FLAGS_CFI := -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers + # Disable function merging as LLVM incorrectly merges functions with different KCFI types. + RUSTC_FLAGS_CFI := -Zsanitizer=kcfi -Zsanitizer-cfi-normalize-integers -Zmerge-functions=disabled KBUILD_RUSTFLAGS += $(RUSTC_FLAGS_CFI) export RUSTC_FLAGS_CFI endif
Greg Kroah-Hartman
maintainerPATCH 27/552 KEYS: trusted: Fix TPM teardown ordering
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chengfeng Ye <[email protected]>
commit 5e2d672280d97d83de43031d93761b12dadd7b8a upstream.
trusted_tpm_exit() drops the TPM chip reference and frees the digest array before unregistering the trusted key type. key_type_lookup() holds key_types_sem for reading until the key operation finishes, while unregister_key_type() takes it for writing. It therefore provides the synchronization point that must precede backend teardown.
The current order permits this interleaving:
CPU 0 CPU 1
trusted_tpm_exit() key_type_lookup("trusted")
put_device(&chip->dev) trusted_tpm_seal()
kfree(digests) pcrlock()
unregister_key_type() tpm_pcr_extend(..., digests)
CPU 1 can consequently dereference the freed digest array. The chip can also be released before callbacks stop using it.
KASAN reported:
BUG: KASAN: slab-use-after-free in tpm_pcr_extend+0x1f0/0x200
Read of size 2 at addr ffff88810872d000 by task poc/89
Call Trace:
tpm_pcr_extend+0x1f0/0x200
pcrlock+0x42/0x70 [trusted]
trusted_tpm_seal+0x1b6/0x570 [trusted]
trusted_instantiate+0x293/0x340 [trusted]
__key_instantiate_and_link+0xb2/0x2b0
__key_create_or_update+0x61e/0xb50
__do_sys_add_key+0x1b8/0x310
Allocated by task 88:
__kmalloc_noprof+0x1a7/0x490
do_one_initcall+0xa1/0x390
do_init_module+0x2df/0x840
Freed by task 90:
kfree+0x131/0x3c0
trusted_tpm_exit+0x59/0xa0 [trusted]
__do_sys_delete_module+0x346/0x510Move unregister_key_type() before releasing either resource. This stops new lookups and waits for in-flight key operations to finish before the backend state is destroyed.
--- security/keys/trusted-keys/trusted_tpm1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
security/keys/trusted-keys/trusted_tpm1.c +1 -1
@@ -981,9 +981,9 @@ err_put:static void trusted_tpm_exit (void ) {if (chip) { +unregister_key_type (&key_type_trusted);put_device (&chip->dev);kfree (digests); -unregister_key_type (&key_type_trusted); } }
Greg Kroah-Hartman
maintainerPATCH 28/552 apparmor: fix cred UAF caused by begin_current_label_crit_section()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jann Horn <[email protected]>
commit 3f4ae5fab613dca01d6a2a8210dd832e009fcf47 upstream.
AppArmor's begin_current_label_crit_section() is a scary function called from lots of LSM hooks (in particular VFS/socket-related ones) that checks if the label referenced by the current creds is marked FLAG_STALE, and if so, attempts to use aa_replace_current_label() to replace the creds with an updated version that uses a new label.
The first problem with this is that it would directly lead to UAF of struct cred if anything in the kernel takes a pointer to the current creds and accesses these past a security hook invocation that replaces creds, like so:
``` const struct cred *cred = current_cred(); alloc_file_pseudo(...); uid_t uid = cred->euid; ```
I don't know if anything in the kernel actually does this, but I think it is very surprising that this pattern could lead to UAF.
The second problem is that things go wrong when aa_replace_current_label() runs with overridden credentials. aa_replace_current_label() bails out if current_cred() != current_real_cred() (mirroring the check in proc_pid_attr_write()), but this check can't actually reliably detect overridden credentials because the overridden creds can be the same as the objective creds.
So in approximately the following scenario, things go wrong:
1. task begins with <creds A> (as both objective and subjective creds), with refcount=2
2. task grabs an extra reference on <creds A> for overriding
3. task calls override_creds(<creds A>), which returns a pointer to the old subjective creds (<creds A>)
4. task enters AppArmor LSM hook
5. AppArmor checks that objective/subjective creds are equal
6. AppArmor replaces both cred pointers with <creds B> and drops 2 refs on <creds A>
7. task leaves AppArmor LSM hook
8. task calls revert_creds(<creds A>)
9. now task->cred is <creds A> while task->real_cred is <creds B>, but the task_struct logically holds two references to <creds B>
10. another task drops the extra reference on <creds A> that was used for overriding, refcount drops to 0
11. now task->real_cred points to freed creds
At this point, any access to current_cred() will be UAF.
I have a test case where I run aa-disable on a profile while a process using that profile is blocked on splice() from a FUSE passthrough file into a full pipe; after the profile update, the pipe becomes empty, splice() resumes, the credentials go out of sync, and a subsequent getuid() syscall results in a KASAN UAF splat.
To fix this, instead of directly replacing creds, do it via task_work that will run at the end of the current syscall. (The point in time at which the cred replacement happens should have no correctness impact; it is just a performance optimization to avoid unnecessarily touching the refcount of the new label.)
Note that AppArmor still performs direct cred replacements in the sb_pivotroot LSM hook after this change, and that direct cred replacements can still happen in VFS ->write() callbacks via proc_pid_attr_write().
There are two options for what to do with aa_dup_task_ctx(): Either explicitly reset new->label_replacement_pending after the entire aa_task_ctx has been copied, or switch to manually copying members over. I am switching to manually copying members over because that should make bugs more obvious.
--- security/apparmor/include/cred.h | 6 +----- security/apparmor/include/task.h | 15 +++++++++++---- security/apparmor/task.c | 27 +++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 9 deletions(-)
security/apparmor/include/cred.h +1 -5
@@ -184,13 +184,9 @@ static inline struct aa_label *begin_cur {struct aa_label *label =aa_current_raw_label (); -might_sleep (); -if (label_is_stale (label)) { label =aa_get_newest_label (label); -if (aa_replace_current_label (label) ==0 ) -/* task cred will keep the reference */ -aa_put_label (label); +aa_schedule_stale_label_replacement (); }return label;
security/apparmor/include/task.h +11 -4
@@ -21,15 +21,22 @@ static inline struct aa_task_ctx *task_c* @onexec: profile to transition to on next exec (MAY BE NULL) * @previous: profile the task may return to (MAY BE NULL) * @token: magic value the task must know for returning to @previous_profile +* @label_replacement_tw: for aa_schedule_stale_label_replacement() +* @label_replacement_pending: is @label_replacement_tw pending? +* +* When changing this, check if aa_dup_task_ctx() needs to be updated. */ struct aa_task_ctx {struct aa_label *nnp;struct aa_label *onexec;struct aa_label *previous;u64 token; +struct callback_head label_replacement_tw; +bool label_replacement_pending; };int aa_replace_current_label (struct aa_label *label); +void aa_schedule_stale_label_replacement (void );void aa_set_current_onexec (struct aa_label *label,bool stack);int aa_set_current_hat (struct aa_label *label,u64 token);int aa_restore_previous_label (u64 cookie);
@@ -56,10 +63,10 @@ static inline void aa_free_task_ctx(strustatic inline void aa_dup_task_ctx (struct aa_task_ctx *new,const struct aa_task_ctx *old) { - *new = *old; -aa_get_label (new->nnp); -aa_get_label (new->previous); -aa_get_label (new->onexec); + new->nnp =aa_get_label (old->nnp); + new->onexec =aa_get_label (old->onexec); + new->previous =aa_get_label (old->previous); + new->token = old->token; }/**
security/apparmor/task.c +27 -0
@@ -14,6 +14,7 @@#include <linux/gfp.h> #include <linux/ptrace.h> +#include <linux/task_work.h> #include "include/audit.h" #include "include/cred.h"
@@ -88,6 +89,32 @@ int aa_replace_current_label(struct aa_lreturn 0 ; } +static void aa_replace_stale_label_tw_func (struct callback_head *tw) +{ +struct aa_task_ctx *ctx =task_ctx (current); +struct aa_label *label; + + ctx->label_replacement_pending = false; + label =aa_current_raw_label (); +if (!label_is_stale (label)) +return ; + label =aa_get_newest_label (label); +aa_replace_current_label (label); +aa_put_label (label); +} + +/* replace the current task's stale label on syscall return */ +void aa_schedule_stale_label_replacement (void ) +{ +struct aa_task_ctx *ctx =task_ctx (current); + +if (ctx->label_replacement_pending) +return ; +init_task_work (&ctx->label_replacement_tw, aa_replace_stale_label_tw_func); +if (task_work_add (current, &ctx->label_replacement_tw,TWA_RESUME ) ==0 ) + ctx->label_replacement_pending = true; +} +/** * aa_set_current_onexec - set the tasks change_profile to happen onexec
Greg Kroah-Hartman
maintainerPATCH 29/552 apparmor: fix out-of-bounds write when null terminating a label vec
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hyunwoo Kim <[email protected]>
commit 9f1e40193eef7f047e6b77cfb4b4cafdecd7a123 upstream.
aa_vec_unique() null terminates at vec[n - dups] when VEC_FLAG_TERMINATE is passed. If the components are all distinct no duplicates are dropped, dups is 0 and the terminator goes to vec[n], so the caller has to provide room for n + 1 entries.
aa_label_strn_parse() sets up its vector with vec_setup(profile, vec, len, gfp) and then calls aa_vec_unique(vec, len, VEC_FLAG_TERMINATE), but vec_setup() does not reserve the terminator entry. Up to LOCAL_VEC_ENTRIES it uses the local array of LOCAL_VEC_ENTRIES pointers, above that it allocates exactly len pointers. The terminator therefore lands one entry past the end of the local array when len is LOCAL_VEC_ENTRIES, and one entry past the end of the allocation when len is larger.
len comes from the number of "//&" separated components in the label name and label_count_strn_entries() does not bound it. An unprivileged task reaches the parse by writing to /proc/self/attr/apparmor/current or through lsm_set_self_attr(2), both of which go through do_setattr(), and the name is parsed before the change_profile permission is checked.
The query_label() path behind the securityfs .access file, which is mode 0666, performs no permission check at all. Every component has to resolve to a loaded profile, so a system with policy loaded is required.
The other two VEC_FLAG_TERMINATE users work on a label vec that aa_label_alloc() has already sized with "+ 1 for null terminator entry on vec". Reserve the same entry in vec_setup() and DEFINE_VEC(). Passing len + 1 from the caller instead would move len == LOCAL_VEC_ENTRIES out of the local array and into kzalloc().
--- security/apparmor/include/label.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
security/apparmor/include/label.h +3 -3
@@ -23,7 +23,7 @@ struct aa_ruleset;#define LOCAL_VEC_ENTRIES 8#define DEFINE_VEC (T ,V ) \ - struct aa_ ## T *(_ ## V ## _localtmp)[LOCAL_VEC_ENTRIES]; \ + struct aa_ ## T *(_ ## V ## _localtmp)[LOCAL_VEC_ENTRIES + 1]; \ struct aa_ ## T **(V)#define vec_setup (T ,V ,N ,GFP ) \
@@ -31,10 +31,10 @@ struct aa_ruleset;if ((N ) <=LOCAL_VEC_ENTRIES ) { \typeof (N) i; \ (V) = (_ ## V ## _localtmp); \ - for (i = 0; i < (N); i++) \ + for (i = 0; i <= (N); i++) \ (V)[i] = NULL; \ } else \ - (V) = kzalloc(sizeof(struct aa_ ## T *) * (N), (GFP)); \ + (V) = kzalloc_objs(struct aa_ ## T *, (N) + 1, (GFP)); \ (V) ? 0 : -ENOMEM; \ })
Greg Kroah-Hartman
maintainerPATCH 30/552 include/linux/list.h: mark list_add and __list_add as __always_inline
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jordan R Abrahams-Whitehead <[email protected]>
commit 2780860eddecba9ffe210bb9436eee3cf22bfcdd upstream.
This commit resolves an issue where modpost section verification fails due to section mismatches between list_add and its callers.
At present, list_add (and its internal __list_add) are called from both .text and .init code sections. Since inlining can vary per call site, list_add can be 4 different states:
list_add in text with arguments to non-.init.data values list_add in init with arguments to static .init.data values list_add in init with arguments to non-.init.data values list_add in text with arguments to static .init.data values
It is last instance that ends up causing the section mismatch caused by constant propagation of the address of static libs inside the dir_add as seen below (with the dir_list being defined statically in initramfs.c, resting in .init.data).
WARNING: modpost: vmlinux.o: section mismatch in reference: __list_add (section: .text.unlikely.) -> dir_list (section: .init.data)
Because of these section matching requirements, semantically, __list_add and list_add MUST be inlined. This will then ensure callers inside .init will receive a list_add that exists and refers to only .init data, and list_add code in .text sections will only refer to non-init data.
This issue manifests predominently in AutoFDO with clang, which is very hesitant to inline cold functions such as list_add even when marked inline. Marking them as __always_inline therefore matches the existing semantic constraints imposed by modpost's section mismatch checks.
--- include/linux/list.h | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
include/linux/list.h +11 -4
@@ -150,10 +150,13 @@ static inline bool __list_del_entry_vali* * This is only for internal list manipulation where we know * the prev/next entries already! +* +* Must be inlined to ensure it can be safely called +* with initdata arguments. */ -static inline void __list_add (struct list_head *new, -struct list_head *prev, -struct list_head *next) +static __always_inline void __list_add(struct list_head *new, +struct list_head *prev, +struct list_head *next) {if (!__list_add_valid (new, prev, next))return ;
@@ -171,8 +174,12 @@ static inline void __list_add(struct lis* * Insert a new entry after the specified head. * This is good for implementing stacks. +* +* Must be inlined to ensure it can be safely called +* with initdata arguments. */ -static inline void list_add (struct list_head *new,struct list_head *head) +static __always_inline void list_add(struct list_head *new, +struct list_head *head) {__list_add (new, head, head->next); }
Greg Kroah-Hartman
maintainerPATCH 31/552 mm, swap: ratelimit bad swap entry reports
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Breno Leitao <[email protected]>
commit f9dc428249ed962a70acf301f01eae8578449161 upstream.
A corrupt page table hands the same bogus entry to get_swap_device() on every access to the mapping, and every rejection is logged. One machine logged 6185620 copies of the same line in a few hours.
swap_dup_entry_direct() prints the same message from the fork path, once per call: the WARN_ON_ONCE() guarding it warns once, the pr_err() inside does not.
Rate limit all three prints.
--- mm/swapfile.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
mm/swapfile.c +3 -3
@@ -1613,11 +1613,11 @@ struct swap_info_struct *get_swap_devicereturn si; bad_nofile: -pr_err ("%s: %s%08lx\n" , __func__, Bad_file, entry.val); +pr_err_ratelimited ("%s: %s%08lx\n" , __func__, Bad_file, entry.val); out:return NULL ; put_out: -pr_err ("%s: %s%08lx\n" , __func__, Bad_offset, entry.val); +pr_err_ratelimited ("%s: %s%08lx\n" , __func__, Bad_offset, entry.val);percpu_ref_put (&si->users);return NULL ; }
@@ -3753,7 +3753,7 @@ static int __swap_duplicate(swp_entry_t si =swap_entry_to_info (entry);if (WARN_ON_ONCE (!si)) { -pr_err ("%s%08lx\n" , Bad_file, entry.val); +pr_err_ratelimited ("%s%08lx\n" , Bad_file, entry.val);return -EINVAL ; }
Greg Kroah-Hartman
maintainerPATCH 32/552 mm/gup: fix always draining LRU caches in collect_longterm_unpinnable_folios()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Hildenbrand (Arm) <[email protected]>
commit 078e1a0fc41a42baaf113383b52dab8874c0b967 upstream.
folio_may_be_lru_cached() is currently only true for small folios, and for small folios FOLL_PIN adds GUP_PIN_COUNTING_BIAS references instead of 1 in try_grab_folio()/try_grab_folio_fast().
Consequently, our
folio_ref_count(folio) != folio_expected_ref_count(folio) + 1
check in collect_longterm_unpinnable_folios() will currently always identify "reference mismatch" and first drain the local LRU cache to then drain the LRU cache on all CPUs, as collect_longterm_unpinnable_folios() is really called after pinning the folios with FOLL_PIN.
Add a comment because the current code is not quite intuitive: we used to drain only to make sure the folio_isolate_lru() would succeed. But then we also started draining to make later migration more reliable.
We'll refactor that code soon a bit, to also make it usable in other context where we really want to remove any references from LRU caches.
Let's add CC stable, because having an easy way for excessive LRU cache draining on all CPUs does not sound right. In common scenarios we don't expect to ever have to drain.
--- mm/gup.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
mm/gup.c +8 -2
@@ -2273,6 +2273,7 @@ static unsigned long collect_longterm_unfor (folio =pofs_get_folio (pofs, i); folio; folio =pofs_next_folio (folio, pofs, &i)) { +const int pin_refs =folio_has_pincount (folio) ?1 :GUP_PIN_COUNTING_BIAS ;if (folio_is_longterm_pinnable (folio))continue ;
@@ -2287,15 +2288,20 @@ static unsigned long collect_longterm_uncontinue ; } +/* +* We drain not only to make the folio_isolate_lru() succeed, +* but also to remove any other folio references from LRU +* caches. +*/ if (drained ==0 &&folio_may_be_lru_cached (folio) &&folio_ref_count (folio) != -folio_expected_ref_count (folio) +1 ) { +folio_expected_ref_count (folio) + pin_refs) {lru_add_drain (); drained =1 ; }if (drained ==1 &&folio_may_be_lru_cached (folio) &&folio_ref_count (folio) != -folio_expected_ref_count (folio) +1 ) { +folio_expected_ref_count (folio) + pin_refs) {lru_add_drain_all (); drained =2 ; }
Greg Kroah-Hartman
maintainerPATCH 33/552 mm/kmemleak: avoid soft lockup when scanning task stacks
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Breno Leitao <[email protected]>
commit 5d10d4e19e6daa487f0cd0ea6cba472325de92f9 upstream.
Patch series "mm/kmemleak: avoid soft lockup when scanning task", v3.
kmemleak_scan() scans every task stack under one rcu_read_lock() with no reschedule point, which can trip the soft lockup watchdog on hosts with very many threads.
That prints the following message, depending on the workload+host configuration:
watchdog: BUG: soft lockup - CPU#35 stuck for 22s! [kmemleak:537]
scan_block
kmemleak_scan
kmemleak_scan_thread
kthreadPatch 1 walks the tasks with find_ge_pid() so the scan reschedules between tasks
Patches 2-3 let the scan loops stop early once a scan is interrupted.
This patch (of 3):
kmemleak_scan() walks every thread and scans its kernel stack under a single rcu_read_lock() with no reschedule point. On a host with very many threads -- amplified by KASAN/lockdep in debug builds -- this loop can hog a CPU long enough to trip the soft lockup watchdog:
watchdog: BUG: soft lockup - CPU#35 stuck for 22s! [kmemleak:537] scan_block kmemleak_scan kmemleak_scan_thread kthread
A cond_resched() cannot be added directly: the loop runs inside an RCU read-side critical section.
Walk the tasks one PID at a time with find_ge_pid(), taking the RCU read lock only to look up and pin each task. The stack is then scanned with no lock held, so cond_resched() runs between tasks and the scan stops early on scan_should_stop(). This follows the next_tgid()/task_seq_get_next() iteration pattern and keeps each RCU critical section short.
--- mm/kmemleak.c | 51 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 13 deletions(-)
mm/kmemleak.c +38 -13
@@ -1690,6 +1690,42 @@ unlock_put: }/* +* Scan all task kernel stacks, rescheduling between tasks. Each task is looked +* up and pinned within its own RCU read-side section, so no lock is held across +* the scan and the walk cannot trip the soft lockup watchdog. +*/ +static void kmemleak_scan_task_stacks (void ) +{ +struct pid *pid; +int nr =1 ; + +do { +struct task_struct *p =NULL ; + +rcu_read_lock (); + pid =find_ge_pid (nr, &init_pid_ns); +if (pid) { + nr =pid_nr (pid) +1 ; + p =pid_task (pid,PIDTYPE_PID ); +if (p) +get_task_struct (p); + } +rcu_read_unlock (); + +if (p) { +void *stack =try_get_task_stack (p); + +if (stack) { +scan_block (stack, stack +THREAD_SIZE ,NULL ); +put_task_stack (p); + } +put_task_struct (p); + } +cond_resched (); + }while (pid && !scan_should_stop ()); +} + +/* * Scan data sections and all the referenced memory blocks allocated via the * kernel's standard allocators. This function must be called with the * scan_mutex held.
@@ -1780,19 +1816,8 @@ static void kmemleak_scan(void)/* * Scanning the task stacks (may introduce false negatives). */ -if (kmemleak_stack_scan) { -struct task_struct *p, *g; - -rcu_read_lock (); -for_each_process_thread (g, p) { -void *stack =try_get_task_stack (p); -if (stack) { -scan_block (stack, stack +THREAD_SIZE ,NULL ); -put_task_stack (p); - } - } -rcu_read_unlock (); - } +if (kmemleak_stack_scan) +kmemleak_scan_task_stacks ();/* * Scan the objects already referenced from the sections scanned
Greg Kroah-Hartman
maintainerPATCH 34/552 mm/migrate: report RCU-tasks quiescent states in migrate_pages_batch()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Breno Leitao <[email protected]>
commit efe8f86c0916f0f74eea74ae21a3b37f728c6bad upstream.
migrate_pages_batch() unmaps each folio before moving it, and every unmap runs the mmu_notifier invalidate callbacks. On KVM hosts try_to_migrate() ends up in kvm_mmu_notifier_invalidate_range_start() -> tdp_mmu_zap_leafs(), which is expensive, so unmapping a large batch keeps the CPU busy for a long time.
The loop already calls cond_resched(), but on PREEMPTION kernels that is a no-op, and involuntary preemption is not a Tasks-RCU quiescent state.
A long batch therefore never reports a quiescent state, and the migrating task (e.g. kcompactd) becomes a Tasks-RCU holdout, stalling the Tasks-RCU grace period for minutes, which is common at Meta fleet:
INFO: rcu_tasks detected stalls on tasks: 0000000055349ecc: .. nvcsw: 1157401/1157401 holdout: 1 idle_cpu: -1/56 task:kcompactd0 state:R running task Call Trace: tdp_mmu_zap_leafs tdp_mmu_next_root gfn_to_pfn_cache_invalidate_start kvm_mmu_notifier_invalidate_range_start __mmu_notifier_invalidate_range_start try_to_migrate_one try_to_migrate migrate_pages_batch migrate_pages compact_zone compact_node kcompactd kthread
Use cond_resched_tasks_rcu_qs() so a quiescent state is reported even when cond_resched() does nothing.
This has also been discussed at [1]
--- mm/migrate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
mm/migrate.c +1 -1
@@ -1821,7 +1821,7 @@ static int migrate_pages_batch(struct li is_thp =folio_test_pmd_mappable (folio); nr_pages =folio_nr_pages (folio); -cond_resched (); +cond_resched_tasks_rcu_qs ();/* * The rare folio on the deferred split list should
Greg Kroah-Hartman
maintainerPATCH 35/552 mm/migrate: use huge_ptep_get() in remove_migration_pte()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dev Jain <[email protected]>
commit ac1ec50d71b953524100ddc09057ee61a3dfaff3 upstream.
remove_migration_pte() converts migration entries back to present PTEs after folio migration completes. For hugetlb folios, page_vma_mapped_walk() returns the pte pointer to the hugetlb folio in pvmw.pte, but the code reads it with ptep_get().
On arches which provide their own huge_ptep_get() to dereference a huge pte pointer, accessing via ptep_get() would cause pte_pfn(), pte_present() etc to misbehave.
It is not clear whether this has a trivially visible effect to userspace.
Use huge_ptep_get() to dereference a huge pte pointer.
--- mm/migrate.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
mm/migrate.c +5 -1
@@ -370,7 +370,11 @@ static bool remove_migration_pte(struct continue; }#endif - old_pte =ptep_get (pvmw.pte); +if (folio_test_hugetlb (folio)) + old_pte =huge_ptep_get (vma->vm_mm, pvmw.address, + pvmw.pte); +else + old_pte =ptep_get (pvmw.pte);if (rmap_walk_arg->map_unused_to_zeropage &&try_to_map_unused_to_zeropage (&pvmw, folio, old_pte, idx))continue ;
Greg Kroah-Hartman
maintainerPATCH 36/552 mm/mm_init: deferred_grow_zone(): fix out-of-range first_deferred_pfn
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Graf <[email protected]>
commit 97090500d776c3f6d08e857e3a0a7cf092999094 upstream.
With CONFIG_DEFERRED_STRUCT_PAGE_INIT enabled, deferred_grow_zone() initializes struct pages early in boot to satisfy an allocation.
With a large CMA reservation in place, the ranges deferred_init_memmap() finds may not add up to the allocation it was asked for, and the function ends up initializing the memory map of the entire zone and still falls short.
That is fine in itself: the function accounts for it and leaves the caller to decide whether it now has enough memory.
However, the update of pgdat->first_deferred_pfn that tracks where uninitialized memory map starts could overflow.
If the node's RAM end is not aligned on PAGES_PER_SECTION boundaries and some deferred struct pages were initialized, pgdat->first_deferred_pfn would point past the end of the node's memory.
deferred_init_memmap() later picks up from pgdat->first_deferred_pfn and hits a BUG_ON(), because it expects a pfn within its node.
For example, when running a kernel with CONFIG_DEFERRED_STRUCT_PAGE_INIT=y and CONFIG_CMA=y using the following qemu command line
qemu-system-x86_64 -enable-kvm -m 8032M -kernel bzImage \
-append "nokaslr cma=4768M@0x100000000"the kernel panics:
kernel BUG at mm/mm_init.c:2131!
CPU: 3 UID: 0 PID: 36 Comm: pgdatinit0 Not tainted 7.2.0-rc6 #1 RIP: 0010:deferred_init_memmap+0x1b8/0x1c0 RAX: 0000000000236000 R13: 0000000000238000 Call Trace: kthread+0xdf/0x120 ret_from_fork+0x187/0x250
Make sure that the update of pgdta->first_deferred_pfn does not overflow when the entire zone's (and therefore node's) memory map is initialized.
--- mm/mm_init.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
mm/mm_init.c +6 -3
@@ -2238,10 +2238,13 @@ bool __init deferred_grow_zone(struct zo }/* -* There were no pages to initialize and free which means the zone's -* memory map is completely initialized. +* The loop only tests spfn before entering an iteration, so on exit it +* may point up to a section past the end of the zone. When it does, +* the rest of the zone has already been handed to +* deferred_init_memmap_chunk() and nothing is left to initialize. */ - pgdat->first_deferred_pfn = nr_pages ? spfn :ULONG_MAX ; + pgdat->first_deferred_pfn = + spfn <zone_end_pfn (zone) ? spfn :ULONG_MAX ;pgdat_resize_unlock (pgdat, &flags);
Greg Kroah-Hartman
maintainerPATCH 37/552 mm/page_owner: use memcg_data snapshot to avoid TOCTOU in print_page_owner_memcg()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ye Liu <[email protected]>
commit 90f095b816e25c6a9e4446d299bac5007fdcb3df upstream.
print_page_owner_memcg() reads page->memcg_data via READ_ONCE() at the start to guard against tail pages and NULL data. However, it later re-reads page->memcg_data locklessly in two places:
1: page_memcg_check(page)
2: PageMemcgKmem(page) (via folio_memcg_kmem(), which includes
VM_BUG_ON assertions for tail pages and MEMCG_DATA_OBJEXTS)
If the page is concurrently freed and reallocated as a THP tail page or slab page between these calls, the VM_BUG_ON assertions can trigger on CONFIG_DEBUG_VM=y builds, crashing the kernel.
Fix both TOCTOU issues by using the memcg_data snapshot throughout.
--- mm/page_owner.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
mm/page_owner.c +7 -3
@@ -504,6 +504,7 @@ static inline int print_page_owner_memcg {#ifdef CONFIG_MEMCG unsigned long memcg_data; +struct obj_cgroup *objcg;struct mem_cgroup *memcg;bool online;char name[80 ];
@@ -513,11 +514,14 @@ static inline int print_page_owner_memcgif (!memcg_data ||PageTail (page)) goto out_unlock; -if (memcg_data &MEMCG_DATA_OBJEXTS ) +if (memcg_data &MEMCG_DATA_OBJEXTS ) { ret +=scnprintf (kbuf + ret, count - ret,"Slab cache page\n" ); + goto out_unlock; + } - memcg =page_memcg_check (page); + objcg = (void *)(memcg_data & ~OBJEXTS_FLAGS_MASK ); + memcg = objcg ?obj_cgroup_memcg (objcg) :NULL ;if (!memcg) goto out_unlock;
@@ -525,7 +529,7 @@ static inline int print_page_owner_memcgcgroup_name (memcg->css.cgroup, name,sizeof (name)); ret +=scnprintf (kbuf + ret, count - ret,"Charged %sto %smemcg %s\n" , -PageMemcgKmem (page) ?"(via objcg) " :"" , + (memcg_data &MEMCG_DATA_KMEM ) ?"(via objcg) " :"" , online ?"" :"offline " , name); out_unlock:
Greg Kroah-Hartman
maintainerPATCH 38/552 mm/page_vma_mapped: use huge_ptep_get() for hugetlb
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dev Jain <[email protected]>
commit e87df0d5d6962bde50f55f6d02b779daa394f894 upstream.
check_pte() is the final validation step in page_vma_mapped_walk(). It reads pvmw->pte with ptep_get() to decide whether the entry maps the PFN range being walked. For hugetlb VMAs, that pointer refers to a hugetlb entry.
On arches which provide their own huge_ptep_get() to dereference a huge pte pointer, accessing via ptep_get() would cause pte_pfn(), pte_present() etc to misbehave.
It is not clear whether this has a trivially visible effect to userspace.
Use huge_ptep_get() to dereference a huge pte pointer.
--- mm/page_vma_mapped.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
mm/page_vma_mapped.c +7 -1
@@ -104,7 +104,13 @@ again:static bool check_pte (struct page_vma_mapped_walk *pvmw,unsigned long pte_nr) {unsigned long pfn; -pte_t ptent =ptep_get (pvmw->pte); +pte_t ptent; + +if (is_vm_hugetlb_page (pvmw->vma)) + ptent =huge_ptep_get (pvmw->vma->vm_mm, pvmw->address, + pvmw->pte); +else + ptent =ptep_get (pvmw->pte);if (pvmw->flags &PVMW_MIGRATION ) {swp_entry_t entry;
Re: [PATCH 6.18 038/552] mm/page_vma_mapped: use huge_ptep_get() for hugetlb
Le 4/09/26 à 06:53, Greg Kroah-Hartman a écrit :
Quoted 69 lines
6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dev Jain <[email protected]>
commit
e87df0d5d6962bde50f55f6d02b779daa394f894upstream.
check_pte()is the final validation step inpage_vma_mapped_walk(). It readspvmw->ptewithptep_get()to decide whether the entry maps the PFN range being walked. For hugetlb VMAs, that pointer refers to a hugetlb entry.On arches which provide their own
huge_ptep_get()to dereference a huge pte pointer, accessing viaptep_get()would causepte_pfn(),pte_present()etc to misbehave.It is not clear whether this has a trivially visible effect to userspace.
Use
huge_ptep_get()to dereference a huge pte pointer.Fixes ace71a19cec5 ("mm: introduce page_vma_mapped_walk()")Signed-off-by Dev Jain <[email protected]>Reviewed-by Muchun Song <[email protected]>Cc Alistair Popple <[email protected]>Cc Andi Kleen <[email protected]>Cc Anshuman Khandual <[email protected]>Cc Byungchul Park <[email protected]>Cc Catalin Marinas <[email protected]>Cc Dave Hansen <[email protected]>Cc Gregory Price <[email protected]>Cc Harry Yoo <[email protected]>Cc "Huang, Ying" <[email protected]>Cc Jann Horn <[email protected]>Cc Josh Poimboeuf <[email protected]>Cc Joshua Hahn <[email protected]>Cc Jun'ichi "Nick" Nomura <[email protected]>Cc Kiryl Shutsemau <[email protected]>Cc Lance Yang <[email protected]>Cc Liam R. Howlett <[email protected]>Cc Lorenzo Stoakes <[email protected]>Cc Matthew Brost <[email protected]>Cc Mel Gorman <[email protected]>Cc Naoya Horiguchi <[email protected]>Cc Oscar Salvador <[email protected]>Cc Pedro Falcato <[email protected]>Cc Rakie Kim <[email protected]>Cc Ralph Campbell <[email protected]>Cc Rik van Riel <[email protected]>Cc Ryan Roberts <[email protected]>Cc Vlastimil Babka <[email protected]>Cc Will Deacon <[email protected]>Cc Zi Yan <[email protected]>Cc <[email protected]>Signed-off-by Andrew Morton <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- mm/page_vma_mapped.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)mm/page_vma_mapped.c +0
-1@@ -104,7 +104,13 @@ again:static bool check_pte (struct page_vma_mapped_walk *pvmw,unsigned long pte_nr) {unsigned long pfn; -pte_t ptent =ptep_get (pvmw->pte);
mm/page_vma_mapped.c again: · line 116
Quoted 10 lines
mm/page_vma_mapped.c +7
-0+pte_t ptent; + +if (is_vm_hugetlb_page (pvmw->vma)) + ptent =huge_ptep_get (pvmw->vma->vm_mm, pvmw->address, + pvmw->pte); +else + ptent =ptep_get (pvmw->pte);if (pvmw->flags &PVMW_MIGRATION ) {swp_entry_t entry;
This patch causes this build error:mm/page_vma_mapped.omm/page_vma_mapped.c: In function 'check_pte':mm/page_vma_mapped.c:110:25: error: implicit declaration of function 'huge_ptep_get' [-Wimplicit-function-declaration]
110 | ptent = huge_ptep_get(pvmw->vma->vm_mm,pvmw->address,
| ^~~~~~~~~~~~~
mm/page_vma_mapped.c:110:25: error: incompatible types when assigning to type 'pte_t' from type 'int' make[3]: *** [scripts/Makefile.build:287: mm/page_vma_mapped.o] Error 1
make[2]: *** [scripts/Makefile.build:544: mm] Error 2
make[1]: *** [/usr/src/linux-6.18/Makefile:2051: .] Error 2
make: *** [Makefile:248: __sub-make] Error 2
commit 70010ab9a9eb7aee65f42ddc20835806759b4336 ("mm/migrate: use huge_ptep_get() in remove_migration_pte()") gives the same kind error.
If I revert those 2 commits, compilation work fine.
Best regards,
François Valenduc
Greg Kroah-Hartman
maintainerRe: [PATCH 6.18 038/552] mm/page_vma_mapped: use huge_ptep_get() for hugetlb
Quoted 95 lines · François Valenduc
Le 4/09/26 à 06:53, Greg Kroah-Hartman a écrit :
Quoted 68 lines
6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dev Jain <[email protected]>
commit
e87df0d5d6962bde50f55f6d02b779daa394f894upstream.
check_pte()is the final validation step inpage_vma_mapped_walk(). It readspvmw->ptewithptep_get()to decide whether the entry maps the PFN range being walked. For hugetlb VMAs, that pointer refers to a hugetlb entry.On arches which provide their own
huge_ptep_get()to dereference a huge pte pointer, accessing viaptep_get()would causepte_pfn(),pte_present()etc to misbehave.It is not clear whether this has a trivially visible effect to userspace.
Use
huge_ptep_get()to dereference a huge pte pointer.Fixes ace71a19cec5 ("mm: introduce page_vma_mapped_walk()")Signed-off-by Dev Jain <[email protected]>Reviewed-by Muchun Song <[email protected]>Cc Alistair Popple <[email protected]>Cc Andi Kleen <[email protected]>Cc Anshuman Khandual <[email protected]>Cc Byungchul Park <[email protected]>Cc Catalin Marinas <[email protected]>Cc Dave Hansen <[email protected]>Cc Gregory Price <[email protected]>Cc Harry Yoo <[email protected]>Cc "Huang, Ying" <[email protected]>Cc Jann Horn <[email protected]>Cc Josh Poimboeuf <[email protected]>Cc Joshua Hahn <[email protected]>Cc Jun'ichi "Nick" Nomura <[email protected]>Cc Kiryl Shutsemau <[email protected]>Cc Lance Yang <[email protected]>Cc Liam R. Howlett <[email protected]>Cc Lorenzo Stoakes <[email protected]>Cc Matthew Brost <[email protected]>Cc Mel Gorman <[email protected]>Cc Naoya Horiguchi <[email protected]>Cc Oscar Salvador <[email protected]>Cc Pedro Falcato <[email protected]>Cc Rakie Kim <[email protected]>Cc Ralph Campbell <[email protected]>Cc Rik van Riel <[email protected]>Cc Ryan Roberts <[email protected]>Cc Vlastimil Babka <[email protected]>Cc Will Deacon <[email protected]>Cc Zi Yan <[email protected]>Cc <[email protected]>Signed-off-by Andrew Morton <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- mm/page_vma_mapped.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)mm/page_vma_mapped.c +0
-0@@ -104,7 +104,13 @@ again:static bool check_pte (struct page_vma_mapped_walk *pvmw,unsigned long pte_nr) {unsigned long pfn;mm/page_vma_mapped.c again: · line 115
Quoted 10 lines
mm/page_vma_mapped.c +7
-1-pte_t ptent =ptep_get (pvmw->pte); +pte_t ptent; + +if (is_vm_hugetlb_page (pvmw->vma)) + ptent =huge_ptep_get (pvmw->vma->vm_mm, pvmw->address, + pvmw->pte); +else + ptent =ptep_get (pvmw->pte);if (pvmw->flags &PVMW_MIGRATION ) {swp_entry_t entry;This patch causes this build error:
mm/page_vma_mapped.omm/page_vma_mapped.c: In function 'check_pte':mm/page_vma_mapped.c:110:25: error: implicit declaration of function 'huge_ptep_get' [-Wimplicit-function-declaration]
110 | ptent = huge_ptep_get(pvmw->vma->vm_mm,pvmw->address,| ^~~~~~~~~~~~~
mm/page_vma_mapped.c:110:25: error: incompatible types when assigning to type 'pte_t' from type 'int'
make[3]: *** [scripts/Makefile.build:287:mm/page_vma_mapped.o] Error 1 make[2]: *** [scripts/Makefile.build:544: mm] Error 2 make[1]: *** [/usr/src/linux-6.18/Makefile:2051: .] Error 2
make: *** [Makefile:248: __sub-make] Error 2
Quoted 4 lines
commit
70010ab9a9eb7aee65f42ddc20835806759b4336("mm/migrate: usehuge_ptep_get()inremove_migration_pte()") gives the same kind error.If I revert those 2 commits, compilation work fine.
Thanks, I should have this fixed up now in the queue.
greg k-h
Re: [PATCH 6.18 038/552] mm/page_vma_mapped: use huge_ptep_get() for hugetlb
Le 5/09/26 à 13:54, Greg Kroah-Hartman a écrit :
Quoted 95 lines · François Valenduc
Quoted 94 lines
Le 4/09/26 à 06:53, Greg Kroah-Hartman a écrit :
Quoted 68 lines
6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dev Jain <[email protected]>
commit
e87df0d5d6962bde50f55f6d02b779daa394f894upstream.
check_pte()is the final validation step inpage_vma_mapped_walk(). It readspvmw->ptewithptep_get()to decide whether the entry maps the PFN range being walked. For hugetlb VMAs, that pointer refers to a hugetlb entry.On arches which provide their own
huge_ptep_get()to dereference a huge pte pointer, accessing viaptep_get()would causepte_pfn(),pte_present()etc to misbehave.It is not clear whether this has a trivially visible effect to userspace.
Use
huge_ptep_get()to dereference a huge pte pointer.Fixes ace71a19cec5 ("mm: introduce page_vma_mapped_walk()")Signed-off-by Dev Jain <[email protected]>Reviewed-by Muchun Song <[email protected]>Cc Alistair Popple <[email protected]>Cc Andi Kleen <[email protected]>Cc Anshuman Khandual <[email protected]>Cc Byungchul Park <[email protected]>Cc Catalin Marinas <[email protected]>Cc Dave Hansen <[email protected]>Cc Gregory Price <[email protected]>Cc Harry Yoo <[email protected]>Cc "Huang, Ying" <[email protected]>Cc Jann Horn <[email protected]>Cc Josh Poimboeuf <[email protected]>Cc Joshua Hahn <[email protected]>Cc Jun'ichi "Nick" Nomura <[email protected]>Cc Kiryl Shutsemau <[email protected]>Cc Lance Yang <[email protected]>Cc Liam R. Howlett <[email protected]>Cc Lorenzo Stoakes <[email protected]>Cc Matthew Brost <[email protected]>Cc Mel Gorman <[email protected]>Cc Naoya Horiguchi <[email protected]>Cc Oscar Salvador <[email protected]>Cc Pedro Falcato <[email protected]>Cc Rakie Kim <[email protected]>Cc Ralph Campbell <[email protected]>Cc Rik van Riel <[email protected]>Cc Ryan Roberts <[email protected]>Cc Vlastimil Babka <[email protected]>Cc Will Deacon <[email protected]>Cc Zi Yan <[email protected]>Cc <[email protected]>Signed-off-by Andrew Morton <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- mm/page_vma_mapped.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)mm/page_vma_mapped.c +0
-0@@ -104,7 +104,13 @@ again:static bool check_pte (struct page_vma_mapped_walk *pvmw,unsigned long pte_nr) {unsigned long pfn;mm/page_vma_mapped.c again: · line 115
Quoted 10 lines
mm/page_vma_mapped.c +7
-1-pte_t ptent =ptep_get (pvmw->pte); +pte_t ptent; + +if (is_vm_hugetlb_page (pvmw->vma)) + ptent =huge_ptep_get (pvmw->vma->vm_mm, pvmw->address, + pvmw->pte); +else + ptent =ptep_get (pvmw->pte);if (pvmw->flags &PVMW_MIGRATION ) {swp_entry_t entry;This patch causes this build error:
mm/page_vma_mapped.omm/page_vma_mapped.c: In function 'check_pte':mm/page_vma_mapped.c:110:25: error: implicit declaration of function 'huge_ptep_get' [-Wimplicit-function-declaration]
110 | ptent = huge_ptep_get(pvmw->vma->vm_mm,pvmw->address,| ^~~~~~~~~~~~~
mm/page_vma_mapped.c:110:25: error: incompatible types when assigning to type 'pte_t' from type 'int'
make[3]: *** [scripts/Makefile.build:287:mm/page_vma_mapped.o] Error 1 make[2]: *** [scripts/Makefile.build:544: mm] Error 2 make[1]: *** [/usr/src/linux-6.18/Makefile:2051: .] Error 2
make: *** [Makefile:248: __sub-make] Error 2
Quoted 7 lines
Quoted 4 lines
commit
70010ab9a9eb7aee65f42ddc20835806759b4336("mm/migrate: usehuge_ptep_get()inremove_migration_pte()") gives the same kind error.If I revert those 2 commits, compilation work fine.
Thanks, I should have this fixed up now in the queue.
greg k-h
Indeed, it works correctly now.
François Valenduc
Greg Kroah-Hartman
maintainerRe: [PATCH 6.18 038/552] mm/page_vma_mapped: use huge_ptep_get() for hugetlb
Quoted 99 lines · François Valenduc
Le 5/09/26 à 13:54, Greg Kroah-Hartman a écrit :
Quoted 98 lines · François Valenduc
Quoted 97 lines
Le 4/09/26 à 06:53, Greg Kroah-Hartman a écrit :
Quoted 68 lines
6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dev Jain <[email protected]>
commit
e87df0d5d6962bde50f55f6d02b779daa394f894upstream.
check_pte()is the final validation step inpage_vma_mapped_walk(). It readspvmw->ptewithptep_get()to decide whether the entry maps the PFN range being walked. For hugetlb VMAs, that pointer refers to a hugetlb entry.On arches which provide their own
huge_ptep_get()to dereference a huge pte pointer, accessing viaptep_get()would causepte_pfn(),pte_present()etc to misbehave.It is not clear whether this has a trivially visible effect to userspace.
Use
huge_ptep_get()to dereference a huge pte pointer.Fixes ace71a19cec5 ("mm: introduce page_vma_mapped_walk()")Signed-off-by Dev Jain <[email protected]>Reviewed-by Muchun Song <[email protected]>Cc Alistair Popple <[email protected]>Cc Andi Kleen <[email protected]>Cc Anshuman Khandual <[email protected]>Cc Byungchul Park <[email protected]>Cc Catalin Marinas <[email protected]>Cc Dave Hansen <[email protected]>Cc Gregory Price <[email protected]>Cc Harry Yoo <[email protected]>Cc "Huang, Ying" <[email protected]>Cc Jann Horn <[email protected]>Cc Josh Poimboeuf <[email protected]>Cc Joshua Hahn <[email protected]>Cc Jun'ichi "Nick" Nomura <[email protected]>Cc Kiryl Shutsemau <[email protected]>Cc Lance Yang <[email protected]>Cc Liam R. Howlett <[email protected]>Cc Lorenzo Stoakes <[email protected]>Cc Matthew Brost <[email protected]>Cc Mel Gorman <[email protected]>Cc Naoya Horiguchi <[email protected]>Cc Oscar Salvador <[email protected]>Cc Pedro Falcato <[email protected]>Cc Rakie Kim <[email protected]>Cc Ralph Campbell <[email protected]>Cc Rik van Riel <[email protected]>Cc Ryan Roberts <[email protected]>Cc Vlastimil Babka <[email protected]>Cc Will Deacon <[email protected]>Cc Zi Yan <[email protected]>Cc <[email protected]>Signed-off-by Andrew Morton <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- mm/page_vma_mapped.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)mm/page_vma_mapped.c +0
-0@@ -104,7 +104,13 @@ again:static bool check_pte (struct page_vma_mapped_walk *pvmw,unsigned long pte_nr) {unsigned long pfn;mm/page_vma_mapped.c again: · line 115
Quoted 10 lines
mm/page_vma_mapped.c +7
-1-pte_t ptent =ptep_get (pvmw->pte); +pte_t ptent; + +if (is_vm_hugetlb_page (pvmw->vma)) + ptent =huge_ptep_get (pvmw->vma->vm_mm, pvmw->address, + pvmw->pte); +else + ptent =ptep_get (pvmw->pte);if (pvmw->flags &PVMW_MIGRATION ) {swp_entry_t entry;This patch causes this build error:
mm/page_vma_mapped.omm/page_vma_mapped.c: In function 'check_pte':mm/page_vma_mapped.c:110:25: error: implicit declaration of function 'huge_ptep_get' [-Wimplicit-function-declaration]
110 | ptent = huge_ptep_get(pvmw->vma->vm_mm,pvmw->address,| ^~~~~~~~~~~~~
mm/page_vma_mapped.c:110:25: error: incompatible types when assigning to type 'pte_t' from type 'int'
make[3]: *** [scripts/Makefile.build:287:mm/page_vma_mapped.o] Error 1 make[2]: *** [scripts/Makefile.build:544: mm] Error 2 make[1]: *** [/usr/src/linux-6.18/Makefile:2051: .] Error 2
make: *** [Makefile:248: __sub-make] Error 2commit
70010ab9a9eb7aee65f42ddc20835806759b4336("mm/migrate: usehuge_ptep_get()inremove_migration_pte()") gives the same kind error.
Quoted 6 lines
Quoted 4 lines
Quoted 1 line
If I revert those 2 commits, compilation work fine.
Thanks, I should have this fixed up now in the queue.
greg k-h
Indeed, it works correctly now.
Great, thanks for testing and letting us know.
greg k-h
Greg Kroah-Hartman
maintainerPATCH 39/552 mm/pagewalk: fix stale walk->action escaping walk_pmd_range()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hyunwoo Kim <[email protected]>
commit aedf2efd18977e0cef7eb963166e2b1fcc0aa321 upstream.
If ->pmd_entry() sets walk->action = ACTION_AGAIN, the pmd_none() check is retried. The PMD entry may be cleared at the point of retry.
In this case, if walk->ops->install_pte is not specified, the code continues to the next PMD entry in the range without resetting walk->action to ACTION_SUBTREE.
This leaves walk->action erroneously set to ACTION_AGAIN, which is incorrect.
This was incorrect but not problematic up until commit 3b89863c3fa4 ("mm/pagewalk: fix race between concurrent split and refault") which updated walk_pud_range() to check for walk->action == ACTION_AGAIN upon walk_pmd_range()'s return, causing the PUD walk to be retried.
In this case this results in duplicate walk callbacks being invoked, which is erroneous and will break any caller that is not idempotent with respect to this (and waste time for those which are). The result is an out-of-bounds write, triggered by a local fuzzer:
[ 2.272695] ================================================================== [ 2.273471] BUG: KASAN: slab-out-of-bounds in __mincore_unmapped_range+0x14f/0x190 [ 2.274302] Write of size 1 at addr ffff888008d9b000 by task poc/106 [ 2.274966] [ 2.275154] CPU: 0 UID: 1000 PID: 106 Comm: poc Not tainted 7.2.0-rc6-00429-ga7c7074b58d2 #55 PREEMPT(lazy) [ 2.275159] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 [ 2.275164] Call Trace: [ 2.275170] <TASK> [ 2.275172] dump_stack_lvl+0x53/0x70 [ 2.275200] print_report+0xd0/0x630 [ 2.275210] ? __pfx__raw_spin_lock_irqsave+0x10/0x10 [ 2.275219] ? irqentry_exit+0xd2/0x670 [ 2.275224] ? irqentry_exit+0xd2/0x670 [ 2.275226] ? __virt_addr_valid+0xef/0x1a0 [ 2.275239] ? __mincore_unmapped_range+0x14f/0x190 [ 2.275242] kasan_report+0xce/0x100 [ 2.275245] ? __mincore_unmapped_range+0x14f/0x190 [ 2.275248] __mincore_unmapped_range+0x14f/0x190 [ 2.275252] mincore_unmapped_range+0x45/0x70 [ 2.275254] walk_pgd_range+0xafc/0xfc0 [ 2.275261] ? __pfx_walk_pgd_range+0x10/0x10 [ 2.275264] ? __update_load_avg_se+0x3d1/0x670 [ 2.275275] __walk_page_range+0xc0/0x310 [ 2.275278] ? __pfx_find_vma+0x10/0x10 [ 2.275281] ? finish_task_switch.isra.0+0x16d/0x4f0 [ 2.275290] walk_page_range_mm_unsafe+0x26f/0x3a0 [ 2.275293] ? __pfx_mtree_load+0x10/0x10 [ 2.275298] ? __pfx_walk_page_range_mm_unsafe+0x10/0x10 [ 2.275302] ? __free_frozen_pages+0x54d/0x7e0 [ 2.275308] __do_sys_mincore+0x132/0x380 [ 2.275311] do_syscall_64+0xf9/0x540 [ 2.275316] entry_SYSCALL_64_after_hwframe+0x77/0x7f [ 2.275322] RIP: 0033:0x422ccd [ 2.275326] Code: b3 66 2e 0f 1f 84 00 00 00 00 00 66 90 f3 0f 1e fa 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 b8 ff ff ff f7 d8 64 89 01 48 [ 2.275329] RSP: 002b:00007fffffffec18 EFLAGS: 00000287 ORIG_RAX: 000000000000001b [ 2.275337] RAX: ffffffffffffffda RBX: 0000000000000066 RCX: 0000000000422ccd [ 2.275339] RDX: 00000000004d0940 RSI: 0000000001000000 RDI: 00007ffff4000000 [ 2.275340] RBP: 00000000004d0940 R08: 0000000000000100 R09: 0000000000000100 [ 2.275342] R10: 0000000000000100 R11: 0000000000000287 R12: 20c49ba5e353f7cf [ 2.275343] R13: 00000000004990d3 R14: 0000000000000000 R15: 0000000000000001 [ 2.275346] </TASK> [ 2.275347] [ 2.296904] The buggy address belongs to the object at ffff888008d9b000 [ 2.296904] which belongs to the cache sigqueue of size 80 [ 2.298151] The buggy address is located 0 bytes inside of [ 2.298151] allocated 80-byte region [ffff888008d9b000, ffff888008d9b050) [ 2.299408] [ 2.299601] The buggy address belongs to the physical page: [ 2.300191] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x8d9b [ 2.301001] flags: 0x100000000000000(node=0|zone=1) [ 2.301535] page_type: f5(slab) [ 2.301884] raw: 0100000000000000 ffff888107e46780 dead000000000122 0000000000000000 [ 2.302687] raw: 0000000000000000 0000000800240024 00000000f5000000 0000000000000000 [ 2.303489] page dumped because: kasan: bad access detected [ 2.304092] [ 2.304276] Memory state around the buggy address: [ 2.304801] ffff888008d9af00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 2.305567] ffff888008d9af80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 2.306340] >ffff888008d9b000: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 2.307115] ^ [ 2.307474] ffff888008d9b080: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 2.308237] ffff888008d9b100: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 2.308997] ==================================================================
A specific example of this breaking things is mincore which walks an internal cursor data structure a byte at a time on assumption that page table entry callbacks are called only once for each entry.
Fix the problem by resetting walk->action to ACTION_SUBTREE prior to the none check.
The pattern also exists in walk_pud_range() so fix it there too.
This issue was found through AI-based fuzzing.
--- mm/pagewalk.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
mm/pagewalk.c +2 -4
@@ -127,6 +127,7 @@ static int walk_pmd_range(pud_t *pud, un pmd =pmd_offset (pud, addr); do { again: + walk->action = ACTION_SUBTREE; next = pmd_addr_end(addr, end); if (pmd_none(*pmd)) { if (has_install)
@@ -139,8 +140,6 @@ again:continue ; } - walk->action =ACTION_SUBTREE ; -/* * This implies that each ->pmd_entry() handler * needs to know about pmd_trans_huge() pmds
@@ -197,6 +196,7 @@ static int walk_pud_range(p4d_t *p4d, un pud =pud_offset (p4d, addr); do { again: + walk->action = ACTION_SUBTREE; next = pud_addr_end(addr, end); if (pud_none(*pud)) { if (has_install)
@@ -209,8 +209,6 @@ static int walk_pud_range(p4d_t *p4d, uncontinue ; } - walk->action =ACTION_SUBTREE ; -if (ops->pud_entry) err = ops->pud_entry (pud, addr, next, walk);if (err)
Greg Kroah-Hartman
maintainerPATCH 40/552 mm/vmscan: report RCU-tasks quiescent states in shrink_lruvec()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Breno Leitao <[email protected]>
commit 25f52e81216884a7444bf07a606691feb09a94e3 upstream.
I am seeing some rcu_tasks stalls in the Meta fleet during reclaim.
INFO: rcu_tasks detected stalls on tasks: 0000000088620d09: .. nvcsw: 6735/6735 holdout: 1 idle_cpu: -1/8 task:GlobalCPUThread state:R running task pid:2552016 tgid:2524552 Call Trace: shrink_lruvec mem_cgroup_iter shrink_node do_try_to_free_pages try_to_free_pages __alloc_frozen_pages_noprof alloc_pages_noprof pte_alloc_one __pte_alloc handle_mm_fault
Nothing promises direct reclaim returns in bounded time, and the scan loop in shrink_lruvec() only calls cond_resched(), which is a no-op on PREEMPTION kernels. Involuntary preemption is not a Tasks-RCU quiescent state, so the reclaiming task never reports one and becomes a holdout.
Upgrade it to cond_resched_tasks_rcu_qs(), which reports a quiescent state even when cond_resched() does nothing.
PS: This has been discussed in [1]
--- mm/vmscan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
mm/vmscan.c +1 -1
@@ -5864,7 +5864,7 @@ static void shrink_lruvec(struct lruvec } } -cond_resched (); +cond_resched_tasks_rcu_qs ();if (nr_reclaimed < nr_to_reclaim || proportional_reclaim)continue ;
Greg Kroah-Hartman
maintainerPATCH 41/552 mm/zswap: fix global shrinker when memory cgroup is disabled
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hao Jia <[email protected]>
commit dc8458f43fe964d8ade74c9b0fce54fe71d156de upstream.
Patch series "mm/zswap: Fixes and improves the zswap shrink", v4.
This series fixes and improves the zswap global shrinker (shrink_worker()): Patch 1: Fix missing global shrinker when memory cgroup is disabled. Patch 2: Extend shrink_memcg() to support batch writeback and thereby improving the writeback efficiency in the shrink_worker() and zswap_store() paths.
This patch (of 2):
Zswap writeback when the global pool limit is hit fails when memory cgroup is disabled. The pool remains full until it is organically drained by swapins or memory freeing, leading to zswap store failures and pages bypassing getting written directly to the backing swap device, causing LRU inversion (hotter pages with higher fault latency).
This happens because mem_cgroup_iter() always returns NULL when memory cgroups are disabled. As a result, the global shrinker shrink_worker() repeatedly takes empty walks. After MAX_RECLAIM_RETRIES failed attempts, the worker gives up without writing back any pages.
Therefore, when memory cgroup is disabled, fall through with the !memcg branch and shrink the root memcg directly.
With memcg disabled, shrink_memcg() only returns -ENOENT when the root LRU is empty, which means the total pages are already below thr. In the absence of heavy concurrent zswap stores, the loop then safely bails out via the zswap_total_pages() <= thr check; otherwise, it will resume shrinking the memcg after processing the reschedule check. For any other return value from shrink_memcg(), the loop is guaranteed to terminate, either after MAX_RECLAIM_RETRIES failures or once the threshold is met.
This is a potential performance regression for people using zswap without memcg that was introduced by the commit in "Fixes".
--- mm/zswap.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
mm/zswap.c +7 -6
@@ -1375,11 +1375,12 @@ static void shrink_worker(struct work_st }while (memcg && !mem_cgroup_tryget_online (memcg));spin_unlock (&zswap_shrink_lock); -if (!memcg) { -/* -* Continue shrinking without incrementing failures if -* we found candidate memcgs in the last tree walk. -*/ +/* +* A NULL memcg ends a full hierarchy pass (except when memcg is +* disabled, where it is always NULL: fall through to the root LRU). +* Count a failure only if the last pass found no candidates. +*/ +if (!memcg && !mem_cgroup_disabled ()) {if (!attempts && ++failures ==MAX_RECLAIM_RETRIES )break ;
@@ -1398,7 +1399,7 @@ static void shrink_worker(struct work_st* and failures. */ if (ret == -ENOENT ) -continue ; + goto resched; ++attempts;if (ret && ++failures ==MAX_RECLAIM_RETRIES )
Greg Kroah-Hartman
maintainerPATCH 42/552 mm: compaction: support non-movable compaction for pageblock requests
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Weiner <[email protected]>
commit 1b4b697a5743e624cc259d6c31a8d8716b796305 upstream.
While trying to fix a reclaim storm in defrag_mode, I noticed that non-movable direct compaction is extremely inefficient.
When searching for space to evacuate, compaction only allows blocks of the same type as the incoming request. This is to prevent migratetype pollution, where a small non-movable request frees space in a movable block and provokes the allocator to fall back and pollute it.
This protection is reasonable on one hand, but the downside is that it makes non-movable direct compaction nearly useless: if we get the type annotations right, by definition there aren't any movable pages inside the non-movable blocks it is allowed to scan.
With defrag_mode, the goal is the production of whole blocks, which are essentially type neutral: __rmqueue_claim() will convert them wholesale on alloc. This makes type mixing and pollution a non-issue.
Fix the pollution gates to take the requested order into account, and allow whole-block requests to scan blocks of other types.
The only exception is CMA blocks. That type is sticky and these blocks cannot be claimed to other types. Continue to be strict with them, and allow only explicit ALLOC_CMA requests and kcompactd to evacuate them.
--- mm/compaction.c | 46 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-)
mm/compaction.c +39 -7
@@ -1364,12 +1364,44 @@ static bool suitable_migration_source(stif (pageblock_skip_persistent (page))return false; -if ((cc->mode !=MIGRATE_ASYNC ) || !cc->direct_compaction) +/* +* Background compaction produces blocks for the zone at +* large, with no particular allocation context. Allow all +* block types, including CMA. +*/ +if (!cc->direct_compaction)return true; block_mt =get_pageblock_migratetype (page); -if (cc->migratetype ==MIGRATE_MOVABLE ) +/* +* CMA pages can only be taken by ALLOC_CMA requests. For anybody +* else, vacating a CMA block consumes free pages the caller +* could have used, and produces free pages it cannot. +*/ +if (is_migrate_cma (block_mt) && !(cc->alloc_flags &ALLOC_CMA )) +return false; + +/* +* Per default, scans are restricted to blocks compatible with +* the request, to prevent cross-contamination. Once +* compaction priority escalates to synchronous scans, though, +* scan all blocks to try to make forward progress. For +* movable request, this likely helps little: there shouldn't +* be many migratable pages inside non-movable blocks besides +* allocator fallbacks. For non-movable requests, this helps a +* lot, as they can finally scan movable blocks. +*/ +if (cc->mode !=MIGRATE_ASYNC ) +return true; + +/* +* Prevent <pageblock_order unmovable/reclaimable requests from +* polluting movable blocks through fallbacks. Whole-block production +* (directly requested, or defrag_mode) is exempt as the allocator +* claims and converts these. +*/ +if (cc->migratetype ==MIGRATE_MOVABLE || cc->order >= pageblock_order)return is_migrate_movable (block_mt);else return block_mt == cc->migratetype;
@@ -1957,12 +1989,12 @@ static unsigned long fast_find_migrateblreturn pfn;/* -* Only allow kcompactd and direct requests for movable pages to -* quickly clear out a MOVABLE pageblock for allocation. This -* reduces the risk that a large movable pageblock is freed for -* an unmovable/reclaimable small allocation. +* Prevent <pageblock_order unmovable/reclaimable requests from +* polluting movable blocks through fallbacks. Whole-block production +* is exempt as the allocator claims and converts these. */ -if (cc->direct_compaction && cc->migratetype !=MIGRATE_MOVABLE ) +if (cc->direct_compaction && cc->migratetype !=MIGRATE_MOVABLE && + cc->order < pageblock_order)return pfn;/*
Greg Kroah-Hartman
maintainerPATCH 43/552 mm: memcg-v1: fix wrong linux-mm list address in deprecation warnings
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guopeng Zhang <[email protected]>
commit 45b1ec4887bdcc58af885540d9fefa8b67d17d57 upstream.
The deprecation warnings for memory.oom_control and memory.pressure_level use [email protected] instead of the linux-mm mailing list address. Remove the extra hyphen.
--- mm/memcontrol-v1.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
mm/memcontrol-v1.c +3 -3
@@ -1139,13 +1139,13 @@ static ssize_t memcg_write_event_control event->unregister_event = mem_cgroup_usage_unregister_event; }else if (!strcmp (name,"memory.oom_control" )) {pr_warn_once ("oom_control is deprecated and will be removed. " -"Please report your usecase to [email protected]" +"Please report your usecase to [email protected]" " if you depend on this functionality.\n" ); event->register_event = mem_cgroup_oom_register_event; event->unregister_event = mem_cgroup_oom_unregister_event; }else if (!strcmp (name,"memory.pressure_level" )) {pr_warn_once ("pressure_level is deprecated and will be removed. " -"Please report your usecase to [email protected] " +"Please report your usecase to [email protected] " "if you depend on this functionality.\n" ); event->register_event = vmpressure_register_event; event->unregister_event = vmpressure_unregister_event;
@@ -1982,7 +1982,7 @@ static int mem_cgroup_oom_control_write(struct mem_cgroup *memcg =mem_cgroup_from_css (css);pr_warn_once ("oom_control is deprecated and will be removed. " -"Please report your usecase to [email protected] if you " +"Please report your usecase to [email protected] if you " "depend on this functionality.\n" );/* cannot set to root cgroup and only 0 and 1 are allowed */
Greg Kroah-Hartman
maintainerPATCH 44/552 mm: memcg-v1: fix memsw and TCP failcnt accounting
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guopeng Zhang <[email protected]>
commit 92192e9c5ee07efc657d3654bc264081fb0aa01b upstream.
Commit 0e2759afcaf9 ("page_counter: track failcnt only for legacy cgroups") made failcnt accounting conditional on track_failcnt. It enabled the flag for memcg->memory, but not for memcg->memsw or memcg->tcpmem.
Consequently, memory.memsw.failcnt remains zero when the memory+swap limit is hit. memory.kmem.tcp.limit_in_bytes still sets memcg->tcpmem.max, but TCP charge failures are not reflected in memory.kmem.tcp.failcnt.
Enable failcnt accounting for both v1 counters.
To reproduce memory.memsw.failcnt:
CG=/sys/fs/cgroup/memory/memsw-test
LIMIT=33554432
mkdir "$CG"
echo "$LIMIT" > "$CG/memory.limit_in_bytes"
echo "$LIMIT" > "$CG/memory.memsw.limit_in_bytes"Start a child process in the cgroup and make it allocate and touch 96 MiB of memory, causing a memcg OOM.
cat "$CG/memory.memsw.failcnt"
Without the patch, memory.memsw.failcnt is 0. With the patch, memory.memsw.failcnt is greater than 0.
To reproduce memory.kmem.tcp.failcnt:
CG=/sys/fs/cgroup/memory/tcpmem-test
LIMIT=65536
mkdir "$CG"
echo "$LIMIT" > "$CG/memory.kmem.tcp.limit_in_bytes"Start a child process in the cgroup, create a TCP socket, and reserve 1 MiB of socket memory with SO_RESERVE_MEM. The reservation fails with ENOMEM.
cat "$CG/memory.kmem.tcp.failcnt"
Without the patch, memory.kmem.tcp.failcnt is 0. With the patch, memory.kmem.tcp.failcnt is greater than 0.
--- mm/memcontrol.c | 2 ++ 1 file changed, 2 insertions(+)
mm/memcontrol.c +2 -0
@@ -3809,9 +3809,11 @@ mem_cgroup_css_alloc(struct cgroup_subsypage_counter_init (&memcg->swap, &parent->swap, false);#ifdef CONFIG_MEMCG_V1 memcg->memory.track_failcnt = !memcg_on_dfl; + memcg->memsw.track_failcnt = !memcg_on_dfl;WRITE_ONCE (memcg->oom_kill_disable,READ_ONCE (parent->oom_kill_disable));page_counter_init (&memcg->kmem, &parent->kmem, false);page_counter_init (&memcg->tcpmem, &parent->tcpmem, false); + memcg->tcpmem.track_failcnt = !memcg_on_dfl;#endif }else {init_memcg_stats ();
Greg Kroah-Hartman
maintainerPATCH 45/552 mm: memcg: stop reclaim when a limit update is superseded
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guopeng Zhang <[email protected]>
commit 9477820c63cbf4d97114238f3d1ff10dfd6bee3f upstream.
kernfs serializes file operations only per open file, so separate open files can update the same memory.high or memory.max file concurrently. Both handlers store the new limit before synchronous reclaim, but continue to use the writer's local target in the reclaim loop. If another writer raises or removes the limit, the first writer can continue reclaiming toward a stale target.
For memory.max, this can leave the writer looping indefinitely once reclaim retries are exhausted. The OOM path sees sufficient margin under the current limit and returns true without killing, while the writer still compares usage against its stale target and records another OOM event.
Check the current limit at the start of each reclaim iteration and stop if it no longer matches the writer's target.
Reproducer:
Populate a cgroup with anonymous memory and disable swapping. Lower memory.max from one open file, then restore it to "max" through another open file after the new limit becomes visible.
Without the patch, the first writer remains blocked and repeatedly increments the OOM event counter. With the patch, it returns normally.
This was not motivated by a reported production workload. We found it through automated randomized testing for our cgroup observability work and reduced it to the reproducer above.
--- mm/memcontrol.c | 6 ++++++ 1 file changed, 6 insertions(+)
mm/memcontrol.c +6 -0
@@ -4380,6 +4380,9 @@ static ssize_t memory_high_write(structunsigned long nr_pages =page_counter_read (&memcg->memory);unsigned long reclaimed; +if (high !=READ_ONCE (memcg->memory.high)) +break ; +if (nr_pages <= high)break ;
@@ -4431,6 +4434,9 @@ static ssize_t memory_max_write(struct kfor (;;) {unsigned long nr_pages =page_counter_read (&memcg->memory); +if (max !=READ_ONCE (memcg->memory.max)) +break ; +if (nr_pages <= max)break ;
Greg Kroah-Hartman
maintainerPATCH 46/552 mm: memcontrol: update state_local when flushing NMI stats
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guopeng Zhang <[email protected]>
commit 72f522bbf473f03a77e83547b677dc1505c5d41a upstream.
flush_nmi_stats() updates state[] for kmem and slab counters but leaves the corresponding state_local[] counters unchanged. Local kmem and slab statistics therefore miss updates collected through the NMI-safe atomic path.
Update state_local[] together with state[].
--- mm/memcontrol.c | 5 +++++ 1 file changed, 5 insertions(+)
mm/memcontrol.c +5 -0
@@ -4030,6 +4030,7 @@ static void flush_nmi_stats(struct mem_cint index =memcg_stats_index (MEMCG_KMEM ); memcg->vmstats->state[index] += kmem; + memcg->vmstats->state_local[index] += kmem;if (parent) parent->vmstats->state_pending[index] += kmem; }
@@ -4047,9 +4048,11 @@ static void flush_nmi_stats(struct mem_cint index =memcg_stats_index (NR_SLAB_RECLAIMABLE_B ); lstats->state[index] += slab; + lstats->state_local[index] += slab;if (plstats) plstats->state_pending[index] += slab; memcg->vmstats->state[index] += slab; + memcg->vmstats->state_local[index] += slab;if (parent) parent->vmstats->state_pending[index] += slab; }
@@ -4058,9 +4061,11 @@ static void flush_nmi_stats(struct mem_cint index =memcg_stats_index (NR_SLAB_UNRECLAIMABLE_B ); lstats->state[index] += slab; + lstats->state_local[index] += slab;if (plstats) plstats->state_pending[index] += slab; memcg->vmstats->state[index] += slab; + memcg->vmstats->state_local[index] += slab;if (parent) parent->vmstats->state_pending[index] += slab; }
Greg Kroah-Hartman
maintainerPATCH 47/552 mm: mempolicy: fix automatic numa balancing for shmem
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Weiner <[email protected]>
commit d230991493b521eeff39f32434fddcbcdb109eb0 upstream.
Neha reports that mapped shmem aren't considered for NUMA balancing, noting convergence problems and bandwidth bottlenecking for cachelib based workloads on tiered memory systems.
Looking at the code and going through the git history, this doesn't actually seem intentional:
Commit fc3147245d19 ("mm: numa: Limit NUMA scanning to migrate-on-fault VMAs") added a vma_policy_mof() gate to task_numa_work() so VMAs whose policy lacks MPOL_F_MOF are skipped from NUMA balancing scans. The motivation was a real usecase: Oracle was pinning shared segments with mbind(MPOL_BIND) so trapping faults was both expensive and pointless.
The handling of NULL from vm_ops->get_policy, however, treated "user explicitly opted out" the same as "user never specified anything." For VMAs whose shared policy is absent - the common case for shmem - the scan was disabled too.
This issue is old. It probably hurts less in conventional NUMA. But it's very noticeable on tiered systems, where entire tmpfs workingsets can get stuck on lower-bandwidth memory.
Fix this by having vma_policy_mof() use __get_vma_policy() directly, and thereby handle the fallback to task policy (-> preferred_node_policy() has MPOL_F_MOF per default). Every other consumer of vm_ops->get_policy already handles it this way, the scan-eligibility check was the outlier.
This preserves Mel's intended fix: don't scan stuff the user explicitly pinned. But allow default policy vmas to participate in balancing.
--- mm/mempolicy.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-)
mm/mempolicy.c +6 -15
@@ -1989,24 +1989,15 @@ struct mempolicy *get_vma_policy(structbool vma_policy_mof (struct vm_area_struct *vma) {struct mempolicy *pol; +pgoff_t ilx; +bool mof; -if (vma->vm_ops && vma->vm_ops->get_policy) { -bool ret = false; -pgoff_t ilx;/* ignored here */ - - pol = vma->vm_ops->get_policy (vma, vma->vm_start, &ilx); -if (pol && (pol->flags &MPOL_F_MOF )) - ret = true; -mpol_cond_put (pol); - -return ret; - } - - pol = vma->vm_policy; + pol =__get_vma_policy (vma, vma->vm_start, &ilx);if (!pol) pol =get_task_policy (current); - -return pol->flags &MPOL_F_MOF ; + mof = pol->flags &MPOL_F_MOF ; +mpol_cond_put (pol); +return mof; }bool apply_policy_zone (struct mempolicy *policy,enum zone_type zone)
Greg Kroah-Hartman
maintainerPATCH 48/552 mm: page_alloc: __GFP_FS lockdep annotation for direct compaction
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Weiner <[email protected]>
commit 37864d0bf5a4d60da6109b9078cc78ef3fc81216 upstream.
Patch series "mm: fix reclaim storms in defrag_mode", v2.
As we deployed vm.defrag_mode=1 in Meta production, some workloads regressed with recurring pressure spikes and swap storms (which in turn triggered userspace OOM rules on pressure and swap utilization levels).
Tracing pinned this to non-movable requests spinning and reclaiming unproductively when kswapd/kcompactd are overwhelmed. Direct reclaim predominantly frees up pages in movable blocks, but those requests cannot use that space under defrag_mode rules; and it is unlikely to free up whole blocks incidentally for __rmqueue_claim() to work.
This series fixes it by making non-movable requests participate in pageblock production in the allocator slowpath - meaning, they will invoke direct reclaim and direct compaction with pageblock_order.
That requires some small-ish adjustments up front in the allocator and the compaction code: three prep patches and the fix last.
The series has been in production against one of the affected workloads for several weeks and restores the OOM kill rate to !defrag_mode baseline.
This patch (of 4):
A subsequent patch will have some order-0 allocations participate in compaction under defrag_mode, to stave off extfrag events.
Since this is a sprawling expansion of entry points, and compaction can enter filesystem paths, add lockdep annotations that catches __GFP_FS passing errors.
Direct reclaim has had this annotation for a while, and since reclaim and compaction are usually used in conjunction, this is unlikely to unearth old bugs. It's more about future proofing and peace of mind.
--- mm/page_alloc.c | 2 ++ 1 file changed, 2 insertions(+)
mm/page_alloc.c +2 -0
@@ -4138,12 +4138,14 @@ __alloc_pages_direct_compact(gfp_t gfp_mpsi_memstall_enter (&pflags);delayacct_compact_start (); +fs_reclaim_acquire (gfp_mask); noreclaim_flag =memalloc_noreclaim_save (); *compact_result =try_to_compact_pages (gfp_mask, order, alloc_flags, ac, prio, &page);memalloc_noreclaim_restore (noreclaim_flag); +fs_reclaim_release (gfp_mask);psi_memstall_leave (&pflags);delayacct_compact_end ();
Greg Kroah-Hartman
maintainerPATCH 49/552 mm: page_alloc: move capture_control to the page allocator
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vlastimil Babka (SUSE) <[email protected]>
commit aee220f565cce38f0efcff940ae2b44bdc495408 upstream.
The compaction capturing code assumes the allocation request order and compaction target order are the same. That won't be true once defrag_mode promotes sub-block allocations to pageblock-order compaction: compaction targets the larger order, while capture should remain at the original allocation order.
Move the capture_control to the page allocator and give it its own copies of what the page freeing path matches against - zone, migratetype and the allocation order - rather than reaching into compaction's live compact_control. __alloc_pages_direct_compact() fills in migratetype and order, and installs and hides current->capture_control around the whole compaction call; try_to_compact_pages() aims capc->zone at each zone while it is being compacted. compact_zone_order() no longer deals with capture at all.
Pass the capture_control through try_to_compact_pages() / compact_zone_order() in place of the bare struct page **.
No functional change.
--- include/linux/compaction.h | 3 +- mm/compaction.c | 50 ++++++++++++--------------------------------- mm/internal.h | 4 ++- mm/page_alloc.c | 45 ++++++++++++++++++++++++++++++++++------ 4 files changed, 57 insertions(+), 45 deletions(-)
include/linux/compaction.h +2 -1
@@ -56,6 +56,7 @@ enum compact_result { };struct alloc_context ;/* in mm/internal.h */ +struct capture_control ;/* in mm/internal.h */ /* * Number of free order-0 pages that should be available above given watermark
@@ -92,7 +93,7 @@ extern int fragmentation_index(struct zoextern enum compact_result try_to_compact_pages (gfp_t gfp_mask,unsigned int order,unsigned int alloc_flags,const struct alloc_context *ac,enum compact_priority prio, -struct page **page); +struct capture_control *capc);extern void reset_isolation_suitable (pg_data_t *pgdat);extern bool compaction_suitable (struct zone *zone,int order,unsigned long watermark,int highest_zoneidx);
mm/compaction.c +14 -36
82 lines not on this page · raw message
mm/internal.h +3 -1
@@ -908,7 +908,9 @@ struct compact_control {* immediately when one is created during the free path. */ struct capture_control { -struct compact_control *cc; +struct zone *zone; +int migratetype; +int order;struct page *page; };
mm/page_alloc.c +38 -7
78 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 50/552 mm: page_alloc: fix non-movable reclaim storm in defrag_mode
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Weiner <[email protected]>
commit 7e8756d7ad22655b935c384f123071aa9de07a27 upstream.
As we deployed defrag_mode into Meta production, pressure spikes and excessive swapping were observed on some workloads. Tracing confirmed that this is unmovable/reclaimable requests spinning in the allocator and direct reclaim, causing excessive amounts of swap.
The initial plan for defrag_mode was to rely on kswapd/kcompactd to produce blocks, and if those are overwhelmed under high pressure, let the allocator fall back (__rmqueue_steal()) after its retry loops. However, that retrying results in more reclaim on some of these workloads than we'd hoped, sometimes excessively so, spurred on by the !costly order conditions in should_reclaim_retry().
The storms are dependent on the request type. Reclaim will inevitably make room in existing movable blocks, since that's where the LRU pages live. So if movable requests retry on reclaim, they make progress.
When non-movable requests spin in reclaim that isn't productive. They cannot use the individually freed pages, and the process is unlikely to accidentally free whole blocks to meet the ALLOC_NOFRAGMENT bar. They spin and overreclaim excessively, which tanks performance and triggers userspace guards like swap exhaustion or pressure based OOM.
To fix this, send non-movable requests, regardless of order, into pageblock reclaim/compaction. This way, they help move things along to meet the ALLOC_NOFRAGMENT bar. After this patch, the reclaim storms and excess OOM rates are no longer observed in production.
The longer-term plan is still to have all requests, including the movable ones, help make blocks to spread the cost of defragmenting more evenly and fairly; combined with proper watermarking to reduce allocation latencies in the common case. However, doing this naively unearths scaling and concurrency limitations in compaction that need to be addressed first. Promoting just non-movables for now is the minimally viable bug fix for the above issue.
--- mm/compaction.c | 2 +- mm/internal.h | 6 ++++++ mm/page_alloc.c | 31 ++++++++++++++++++++++++++----- 3 files changed, 33 insertions(+), 6 deletions(-)
mm/compaction.c +1 -1
@@ -2803,7 +2803,7 @@ static enum compact_result compact_zone_/** * try_to_compact_pages - Direct compact to satisfy a high-order allocation * @gfp_mask: The GFP mask of the current allocation -* @order: The order of the current allocation +* @order: The order to try to make available * @alloc_flags: The allocation flags of the current allocation * @ac: The context of current allocation * @prio: Determines how hard direct compaction should try to succeed
mm/internal.h +6 -0
@@ -910,6 +910,12 @@ struct compact_control {struct capture_control {struct zone *zone;int migratetype; +/* +* Allocation request order. May differ from the compaction +* order: defrag_mode promotes sub-block allocations to +* pageblock-order compaction; capture still matches at the +* original allocation order so prep_new_page() is consistent. +*/ int order;struct page *page; };
mm/page_alloc.c +26 -5
@@ -4138,8 +4138,24 @@ __alloc_pages_direct_compact(gfp_t gfp_m .order = order, .page = NULL, }; +int compact_order = order; -if (!order) +/* +* If fallbacks are not permitted (defrag_mode), we either +* need to reclaim space in a block of matching type, or clear +* out an entire block to allow __rmqueue_claim() to convert. +* +* Reclaim by itself is primarily freeing space in movable +* blocks, since that's where the LRU pages live. So this +* works for movable requests, but not for others. +* +* For those, promote the order to help make blocks, instead +* of spinning in reclaim alone unproductively. +*/ +if ((alloc_flags &ALLOC_NOFRAGMENT ) && ac->migratetype !=MIGRATE_MOVABLE ) + compact_order =max (order, pageblock_order); + +if (!compact_order)return NULL ;psi_memstall_enter (&pflags);
@@ -4155,8 +4171,8 @@ __alloc_pages_direct_compact(gfp_t gfp_mbarrier ();WRITE_ONCE (current->capture_control, &capc); - *compact_result =try_to_compact_pages (gfp_mask, order, alloc_flags, ac, - prio, &capc); + *compact_result =try_to_compact_pages (gfp_mask, compact_order, + alloc_flags, ac, prio, &capc);/* * Make sure we hide capture control first before we read the captured
@@ -4200,7 +4216,7 @@ __alloc_pages_direct_compact(gfp_t gfp_mstruct zone *zone =page_zone (page); zone->compact_blockskip_flush = false; -compaction_defer_reset (zone, order, true); +compaction_defer_reset (zone, compact_order, true);count_vm_event (COMPACTSUCCESS );return page; }
@@ -4437,9 +4453,14 @@ __alloc_pages_direct_reclaim(gfp_t gfp_mstruct page *page =NULL ;unsigned long pflags;bool drained = false; +int reclaim_order = order; + +/* Match the slowpath compaction promotion in __alloc_pages_direct_compact */ +if ((alloc_flags &ALLOC_NOFRAGMENT ) && ac->migratetype !=MIGRATE_MOVABLE ) + reclaim_order =max (order, pageblock_order);psi_memstall_enter (&pflags); - *did_some_progress =__perform_reclaim (gfp_mask, order, ac); + *did_some_progress =__perform_reclaim (gfp_mask, reclaim_order, ac);if (unlikely (!(*did_some_progress))) goto out;
Greg Kroah-Hartman
maintainerPATCH 51/552 mm: vmscan: fix node reclaim ignoring swappiness parameter
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ridong Chen <[email protected]>
commit 8a905195850d383c0465ab5bdd3c91d94269b242 upstream.
sc_swappiness() had two separate definitions depending on CONFIG_MEMCG. The !CONFIG_MEMCG variant simply returned vm_swappiness, ignoring the proactive_swappiness value passed through scan_control. This caused the swappiness parameter written to /sys/devices/system/node/nodeX/reclaim to have no effect when CONFIG_MEMCG is disabled.
Fix this by consolidating sc_swappiness() into a single definition that checks sc->proactive_swappiness first, then falls back to mem_cgroup_swappiness() which already handles both CONFIG_MEMCG and !CONFIG_MEMCG.
Before fix (swappiness=max ignored, mostly file pages reclaimed):
# cat /proc/sys/vm/swappiness
60
# cat /proc/vmstat | grep pgsteal
pgsteal_kswapd 0
pgsteal_direct 0
pgsteal_khugepaged 0
pgsteal_proactive 1840
pgsteal_anon 25
pgsteal_file 1815
# echo "64M swappiness=max" > /sys/devices/system/node/node0/reclaim
# cat /proc/vmstat | grep pgsteal
pgsteal_kswapd 0
pgsteal_direct 0
pgsteal_khugepaged 0
pgsteal_proactive 18013
pgsteal_anon 337
pgsteal_file 17676After fix (swappiness=max honored, anon pages reclaimed as expected):
# cat /proc/vmstat | grep pgsteal
pgsteal_kswapd 0
pgsteal_direct 0
pgsteal_khugepaged 0
pgsteal_proactive 0
pgsteal_anon 0
pgsteal_file 0
# echo "64M swappiness=max" > /sys/devices/system/node/node0/reclaim
# cat /proc/vmstat | grep pgsteal
pgsteal_kswapd 0
pgsteal_direct 0
pgsteal_khugepaged 0
pgsteal_proactive 16283
pgsteal_anon 16283
pgsteal_file 0--- mm/vmscan.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-)
mm/vmscan.c +7 -12
@@ -201,6 +201,13 @@ struct scan_control {*/ int vm_swappiness =60 ; +static int sc_swappiness (struct scan_control *sc,struct mem_cgroup *memcg) +{ +if (sc->proactive && sc->proactive_swappiness) +return *sc->proactive_swappiness; +return mem_cgroup_swappiness (memcg); +} +#ifdef CONFIG_MEMCG /* Returns true for reclaim through cgroup limits or cgroup interfaces. */
@@ -241,13 +248,6 @@ static bool writeback_throttling_sane(st#endif return false; } - -static int sc_swappiness (struct scan_control *sc,struct mem_cgroup *memcg) -{ -if (sc->proactive && sc->proactive_swappiness) -return *sc->proactive_swappiness; -return mem_cgroup_swappiness (memcg); -}#else static bool cgroup_reclaim (struct scan_control *sc) {
@@ -263,11 +263,6 @@ static bool writeback_throttling_sane(st {return true; } - -static int sc_swappiness (struct scan_control *sc,struct mem_cgroup *memcg) -{ -return READ_ONCE (vm_swappiness); -}#endif /* for_each_managed_zone_pgdat - helper macro to iterate over all managed zones in a pgdat up to
Greg Kroah-Hartman
maintainerPATCH 52/552 tools/compiler: match glibc 2.42 definition of __attribute_const__
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joy H.J. Lee <[email protected]>
commit 8700a4761beb219873956666cf91776a2c61e698 upstream.
glibc 2.42 added __attribute_const__ to sys/cdefs.h:
# define __attribute_const__ __attribute__ ((__const__))
GCC 15 warns when a macro is redefined to a different replacement list (-Wbuiltin-macro-redefined). Since host tool Makefiles (resolve_btfids, objtool) pass -Werror, this conflict becomes fatal.
The warning is suppressed on standard native builds because GCC treats /usr/include as a system header path (-isystem), and macro-redefinition warnings from system headers are silently suppressed by GCC. It fires when glibc headers are on a regular include path (-I) instead, which is the case in cross-compilation setups such as NixOS, where the sysroot's glibc is passed explicitly via -I rather than -isystem.
Per (C11 6.10.3), identical replacement lists are accepted silently. Match the glibc definition exactly, including the space before "((", so the redefinition is accepted without warning regardless of whether glibc headers are treated as system or non-system includes.
--- tools/include/linux/compiler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/include/linux/compiler.h +1 -1
@@ -119,7 +119,7 @@#define __read_mostly#ifndef __attribute_const__ -# define __attribute_const__ +# define __attribute_const__ __attribute__ ((__const__))#endif #ifndef __maybe_unused
Greg Kroah-Hartman
maintainerPATCH 53/552 x86/insn-eval: Move assign_register() out of KVM as insn_assign_reg()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kiryl Shutsemau (Meta) <[email protected]>
commit 1fe104b048d77d6cb25bd938e6a67450fb50e61d upstream.
KVM's instruction emulator has a small helper, assign_register(), that writes a value into a register following the x86 rules for writes to general-purpose registers: an 8- or 16-bit write leaves the rest of the register untouched, a 32-bit write zero-extends the result to 64 bits, and a 64-bit write replaces the whole register.
The TDX guest #VE handler needs the same logic for port I/O emulation to get 32-bit zero-extension right. Rather than add a third copy of the same switch, move the helper verbatim to <asm/insn-eval.h>, rename it to insn_assign_reg(), and route KVM's callers through it.
Add <asm/insn.h> to the header's includes so it builds standalone in callers that have not pulled it in transitively.
No functional change.
--- arch/x86/include/asm/insn-eval.h | 36 ++++++++++++++++++++++++++++++++++++ arch/x86/kvm/emulate.c | 26 ++++---------------------- 2 files changed, 40 insertions(+), 22 deletions(-)
arch/x86/include/asm/insn-eval.h +36 -0
@@ -9,6 +9,7 @@#include <linux/compiler.h> #include <linux/bug.h> #include <linux/err.h> +#include <asm/insn.h> #include <asm/ptrace.h> #define INSN_CODE_SEG_ADDR_SZ (params) ((params >> 4) & 0xf)
@@ -44,4 +45,39 @@ enum insn_mmio_type {enum insn_mmio_type insn_decode_mmio (struct insn *insn,int *bytes); +/* +* Write @val into *@reg following the x86 rules for writes to +* general-purpose registers (Intel SDM Vol. 1, "General-Purpose +* Registers in 64-Bit Mode"): an 8- or 16-bit write leaves the rest of +* the register untouched, a 32-bit write zero-extends the result into +* the upper 32 bits, and a 64-bit write replaces the whole register. +* +* @bytes is the width of the write, not a property of the instruction: +* an instruction that, say, sign-extends a 32-bit immediate into a +* 64-bit register does a 64-bit write here. +* +* @reg need not be 8-byte aligned: KVM's instruction emulator offsets +* the pointer by one byte to address the high-byte registers (AH, CH, +* DH, BH). Use narrow stores for the sub-word cases so the access +* width matches @bytes and the adjacent bytes are left alone. +*/ +static inline void insn_assign_reg (unsigned long *reg,u64 val,int bytes) +{ +switch (bytes) { +case 1 : + *(u8 *)reg = (u8 )val; +break ; +case 2 : + *(u16 *)reg = (u16 )val; +break ; +case 4 : +/* A 32-bit write zero-extends into the upper 32 bits. */ + *reg = (u32 )val; +break ; +case 8 : + *reg = val; +break ; + } +} +#endif /* _ASM_X86_INSN_EVAL_H */
arch/x86/kvm/emulate.c +4 -22
@@ -24,6 +24,7 @@#include "kvm_emulate.h" #include <linux/stringify.h> #include <asm/debugreg.h> +#include <asm/insn-eval.h> #include <asm/nospec-branch.h> #include <asm/ibt.h> #include <asm/text-patching.h>
@@ -436,25 +437,6 @@ static void assign_masked(ulong *dest, u *dest = (*dest & ~mask) | (src & mask); } -static void assign_register (unsigned long *reg,u64 val,int bytes) -{ -/* The 4-byte case *is* correct: in 64-bit mode we zero-extend. */ -switch (bytes) { -case 1 : - *(u8 *)reg = (u8 )val; -break ; -case 2 : - *(u16 *)reg = (u16 )val; -break ; -case 4 : - *reg = (u32 )val; -break ;/* 64b: zero-extend */ -case 8 : - *reg = val; -break ; - } -} -static inline unsigned long ad_mask (struct x86_emulate_ctxt *ctxt) {return (1UL << (ctxt->ad_bytes <<3 )) -1 ;
@@ -502,7 +484,7 @@ register_address_increment(struct x86_em {ulong *preg =reg_rmw (ctxt, reg); -assign_register (preg, *preg + inc, ctxt->ad_bytes); +insn_assign_reg (preg, *preg + inc, ctxt->ad_bytes); }static void rsp_increment (struct x86_emulate_ctxt *ctxt,int inc)
@@ -1756,7 +1738,7 @@ static int load_segment_descriptor(strucstatic void write_register_operand (struct operand *op) { -return assign_register (op->addr.reg, op->val, op->bytes); +return insn_assign_reg (op->addr.reg, op->val, op->bytes); }static int writeback (struct x86_emulate_ctxt *ctxt,struct operand *op)
@@ -1989,7 +1971,7 @@ static int em_popa(struct x86_emulate_ct rc =emulate_pop (ctxt, &val, ctxt->op_bytes);if (rc !=X86EMUL_CONTINUE )break ; -assign_register (reg_rmw (ctxt, reg), val, ctxt->op_bytes); +insn_assign_reg (reg_rmw (ctxt, reg), val, ctxt->op_bytes); --reg; }return rc;
Greg Kroah-Hartman
maintainerPATCH 54/552 x86/locking: Use sfence for wmb() if SSE is available
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yao Zi <[email protected]>
commit d824ed1307680dd482f607b0e707c575f70668c4 upstream.
When adding cc clobber to wmb()'s definition, the alternative() condition to use sfence was incorrectly raised from X86_FEATURE_XMM to X86_FEATURE_XMM2.
Restore the correct constraint for potential better performance on machines without SSE2.
--- arch/x86/include/asm/barrier.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/include/asm/barrier.h +1 -1
@@ -17,7 +17,7 @@#define rmb () asm volatile(ALTERNATIVE("lock addl $0,-4(%%esp)", "lfence", \ X86_FEATURE_XMM2) ::: "memory", "cc")#define wmb () asm volatile(ALTERNATIVE("lock addl $0,-4(%%esp)", "sfence", \ - X86_FEATURE_XMM2) ::: "memory", "cc") + X86_FEATURE_XMM) ::: "memory", "cc")#else #define __mb () asm volatile("mfence":::"memory")#define __rmb () asm volatile("lfence":::"memory")
Greg Kroah-Hartman
maintainerPATCH 55/552 x86/tdx: Fix off-by-one in port I/O handling
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kiryl Shutsemau (Meta) <[email protected]>
commit 0f63e656b1c679d32ac595de29d10c03efca6a25 upstream.
handle_in() and handle_out() in arch/x86/coco/tdx/tdx.c use:
u64 mask = GENMASK(BITS_PER_BYTE * size, 0);
GENMASK(h, l) includes bit h. For size=1 (INB), this produces GENMASK(8, 0) = 0x1FF (9 bits) instead of GENMASK(7, 0) = 0xFF (8 bits). The mask is one bit too wide for all I/O sizes.
Fix the mask calculation.
--- arch/x86/coco/tdx/tdx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/x86/coco/tdx/tdx.c +2 -2
@@ -693,7 +693,7 @@ static bool handle_in(struct pt_regs *re .r13 = PORT_READ, .r14 = port, }; -u64 mask =GENMASK (BITS_PER_BYTE * size,0 ); +u64 mask =GENMASK (BITS_PER_BYTE * size -1 ,0 );bool success;/*
@@ -713,7 +713,7 @@ static bool handle_in(struct pt_regs *restatic bool handle_out (struct pt_regs *regs,int size,int port) { -u64 mask =GENMASK (BITS_PER_BYTE * size,0 ); +u64 mask =GENMASK (BITS_PER_BYTE * size -1 ,0 );/* * Emulate the I/O write via hypercall. More info about ABI can be found
Greg Kroah-Hartman
maintainerPATCH 56/552 x86/tdx: Fix zero-extension for 32-bit port I/O
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kiryl Shutsemau (Meta) <[email protected]>
commit 941370fc93cc3474e26811f4d3b062903eefe2cf upstream.
According to x86 architecture rules, 32-bit operations zero-extend the result to 64 bits. The current implementation of handle_in() only masks the lower 32 bits, which preserves the upper 32 bits of RAX when a 32-bit port IN instruction is emulated.
Use insn_assign_reg() to write the result back into RAX with proper partial-register-write semantics: 1- and 2-byte forms leave the upper bits untouched, the 4-byte form zero-extends to the full register.
--- arch/x86/coco/tdx/tdx.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
arch/x86/coco/tdx/tdx.c +3 -5
@@ -693,8 +693,8 @@ static bool handle_in(struct pt_regs *re .r13 = PORT_READ, .r14 = port, }; -u64 mask =GENMASK (BITS_PER_BYTE * size -1 ,0 );bool success; +u64 val;/* * Emulate the I/O read via hypercall. More info about ABI can be found
@@ -702,11 +702,9 @@ static bool handle_in(struct pt_regs *re* "TDG.VP.VMCALL<Instruction.IO>". */ success = !__tdx_hypercall (&args); + val = success ? args.r11 :0 ; -/* Update part of the register affected by the emulated instruction */ - regs->ax &= ~mask; -if (success) - regs->ax |= args.r11 & mask; +insn_assign_reg (®s->ax, val, size);return success; }
Greg Kroah-Hartman
maintainerPATCH 57/552 hwtracing: hisi_ptt: Propagate DMA reset timeout in trace_start()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sanman Pradhan <[email protected]>
commit 75d42d990335322852ed5f7ce324b701c0949d79 upstream.
hisi_ptt_wait_dma_reset_done() discards the return value of readl_poll_timeout_atomic(). If the DMA engine does not complete its reset within the timeout, hisi_ptt_trace_start() proceeds to start tracing regardless.
Return a bool from hisi_ptt_wait_dma_reset_done(), consistent with the other wait helpers in this driver. On timeout, log an error, de-assert the reset bit, and return -ETIMEDOUT. Move ctrl->started to the successful path so a failed start does not leave the trace marked as active.
--- drivers/hwtracing/ptt/hisi_ptt.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-)
drivers/hwtracing/ptt/hisi_ptt.c +13 -7
@@ -171,13 +171,13 @@ static bool hisi_ptt_wait_trace_hw_idle( HISI_PTT_WAIT_TRACE_TIMEOUT_US); } -static void hisi_ptt_wait_dma_reset_done (struct hisi_ptt *hisi_ptt) +static bool hisi_ptt_wait_dma_reset_done (struct hisi_ptt *hisi_ptt) {u32 val; -readl_poll_timeout_atomic (hisi_ptt->iobase +HISI_PTT_TRACE_WR_STS , - val, !val,HISI_PTT_RESET_POLL_INTERVAL_US , -HISI_PTT_RESET_TIMEOUT_US ); +return !readl_poll_timeout_atomic (hisi_ptt->iobase +HISI_PTT_TRACE_WR_STS , + val, !val,HISI_PTT_RESET_POLL_INTERVAL_US , +HISI_PTT_RESET_TIMEOUT_US ); }static void hisi_ptt_trace_end (struct hisi_ptt *hisi_ptt)
@@ -202,14 +202,18 @@ static int hisi_ptt_trace_start(struct hreturn -EBUSY ; } - ctrl->started = true; -/* Reset the DMA before start tracing */ val =readl (hisi_ptt->iobase +HISI_PTT_TRACE_CTRL ); val |=HISI_PTT_TRACE_CTRL_RST ;writel (val, hisi_ptt->iobase +HISI_PTT_TRACE_CTRL ); -hisi_ptt_wait_dma_reset_done (hisi_ptt); +if (!hisi_ptt_wait_dma_reset_done (hisi_ptt)) { +pci_err (hisi_ptt->pdev,"timed out waiting for DMA reset\n" ); + val =readl (hisi_ptt->iobase +HISI_PTT_TRACE_CTRL ); + val &= ~HISI_PTT_TRACE_CTRL_RST ; +writel (val, hisi_ptt->iobase +HISI_PTT_TRACE_CTRL ); +return -ETIMEDOUT ; + } val =readl (hisi_ptt->iobase +HISI_PTT_TRACE_CTRL ); val &= ~HISI_PTT_TRACE_CTRL_RST ;
@@ -234,6 +238,8 @@ static int hisi_ptt_trace_start(struct hif (!hisi_ptt->trace_ctrl.is_port) val |=HISI_PTT_TRACE_CTRL_FILTER_MODE ; + ctrl->started = true; +/* Start the Trace */ val |=HISI_PTT_TRACE_CTRL_EN ;writel (val, hisi_ptt->iobase +HISI_PTT_TRACE_CTRL );
Greg Kroah-Hartman
maintainerPATCH 58/552 tracing/user_events: Clear copied tracing state before fork duplication
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jérémy Jean <[email protected]>
commit 390f6bd8583d177029d9df4bea6667509e55a765 upstream.
dup_task_struct() copies user_event_mm from the parent into the child, without grabbing a reference to it. user_event_mm_dup() should replace it, but it leaves that copied pointer unmodified if user_event_mm_alloc() fails.
When the child exits, user_event_mm_remove() decrements a reference the child never owned, which ultimately frees user_event_mm, while the parent still as a stale pointer to it. This creates a UAF, which KASAN reports as:
BUG: KASAN: slab-use-after-free in
current_user_event_mm+0x51/0x1d0 Write of size 4 at addr
ffff888005010d30 by task init/44
Call Trace:
<TASK>
kasan_report+0xce/0x100
kasan_check_range+0x10f/0x1e0
current_user_event_mm+0x51/0x1d0
user_events_ioctl+0x82e/0x15c0
__x64_sys_ioctl+0x139/0x1c0
do_syscall_64+0xce/0x450
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Allocated by task 44:
__kasan_kmalloc+0x8f/0xa0
__kmalloc_cache_noprof+0x180/0x3a0
user_event_mm_alloc+0x3c/0x1f0
current_user_event_mm+0x88/0x1d0
Freed by task 42:
__kasan_slab_free+0x43/0x70
kfree+0x13a/0x390
process_one_work+0x696/0xf90
worker_thread+0x420/0xba0The fix simply clears the copied pointer before any possible failure. In case of failure, the child then has nothing to free.
--- kernel/trace/trace_events_user.c | 3 +++ 1 file changed, 3 insertions(+)
kernel/trace/trace_events_user.c +3 -0
@@ -868,6 +868,9 @@ void user_event_mm_dup(struct task_strucstruct user_event_mm *mm =user_event_mm_alloc (t);struct user_event_enabler *enabler; +/* On failure, do not free parent's copy */ + t->user_event_mm =NULL ; +if (!mm)return ;
Greg Kroah-Hartman
maintainerPATCH 59/552 tracing: Fix crash passing ERR_PTR to kthread_stop()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hui Su <[email protected]>
commit 649bc7df3e5d7be6f7996a95084037dbf3cad1e5 upstream.
event_test_stuff() calls kthread_run() and unconditionally passes the returned task_struct pointer to kthread_stop(). kthread_run() returns an error pointer such as ERR_PTR(-ENOMEM) when kthread creation fails, for example under memory pressure during the boot-time event self-test. kthread_stop() then dereferences the invalid pointer, crashing the kernel.
Check the result of kthread_run() before passing it to kthread_stop(). Use WARN_ON() so that a failure to create the self-test thread does not go unnoticed, matching the ring-buffer self-test fix in commit 91542863abad ("ring-buffer: Fix crash passing ERR_PTR to kthread_stop()").
--- kernel/trace/trace_events.c | 2 ++ 1 file changed, 2 insertions(+)
kernel/trace/trace_events.c +2 -0
@@ -4729,6 +4729,8 @@ static __init void event_test_stuff(voidstruct task_struct *test_thread; test_thread =kthread_run (event_test_thread,NULL ,"test-events" ); +if (WARN_ON (IS_ERR (test_thread))) +return ;msleep (1 );kthread_stop (test_thread); }
Greg Kroah-Hartman
maintainerPATCH 60/552 tracing: Fix logged instance name on creation failure
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vincent Donnefort <[email protected]>
commit a9a01be2834a529cbd490ccbab02643f0c1735f2 upstream.
When boot instance creation fails, the kernel incorrectly logs "(null)" as the instance name because strsep() consumes curr_str entirely during parsing.
Print the properly parsed name variable instead. And while at it log the error code.
--- kernel/trace/trace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/trace/trace.c +2 -1
@@ -11172,7 +11172,8 @@ __init static void enable_instances(void tr =trace_array_create_systems (name,NULL , addr, size);if (IS_ERR (tr)) { -pr_warn ("Tracing: Failed to create instance buffer %s\n" , curr_str); +pr_warn ("Tracing: Failed to create instance buffer '%s' (%ld)\n" , name, +PTR_ERR (tr));continue ; }
Greg Kroah-Hartman
maintainerPATCH 61/552 tracing: Fix use-after-free in trace_pipe read on sub-buffer order change
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Deepanshu Kartikey <[email protected]>
commit 372f8534244d632ad5118e8a87a11291b01712d3 upstream.
Writing to buffer_subbuf_size_kb calls ring_buffer_subbuf_order_set(), which frees every sub-buffer of the ring buffer, including the reader page, and replaces them with newly allocated ones.
Readers of trace_pipe hold pointers into those pages. ring_buffer_peek() looks up an event under cpu_buffer->reader_lock but returns the event pointer after dropping the lock, and peek_next_entry() then calls ring_buffer_event_length() and ring_buffer_event_data() on it. If the sub-buffer order is changed in that window, the reader dereferences freed memory:
BUG: KASAN: use-after-free in ring_buffer_peek+0x3e0/0x430 Read of size 1 at addr ffff88802a4cf010 by task syz-executor989/6002
Freed by:
free_buffer_page kernel/trace/ring_buffer.c:398 [inline] ring_buffer_subbuf_order_set+0x1325/0x18e0 kernel/trace/ring_buffer.c:7444 buffer_subbuf_size_write+0x182/0x280 kernel/trace/trace.c:8221
Take trace_access_lock(RING_BUFFER_ALL_CPUS) around the order change. This is the lock trace_pipe readers already hold across their entire peek-and-print loop, so the swap can no longer race with a reader that is dereferencing a peeked event.
--- kernel/trace/trace.c | 3 +++ 1 file changed, 3 insertions(+)
kernel/trace/trace.c +3 -0
@@ -9699,6 +9699,8 @@ buffer_subbuf_size_write(struct file *fi/* Do not allow tracing while changing the order of the ring buffer */ tracing_stop_tr (tr); +trace_access_lock (RING_BUFFER_ALL_CPUS ); + old_order =ring_buffer_subbuf_order_get (tr->array_buffer.buffer);if (old_order == order) goto out;
@@ -9738,6 +9740,7 @@ buffer_subbuf_size_write(struct file *fi#endif (*ppos)++; out: +trace_access_unlock (RING_BUFFER_ALL_CPUS );if (ret) cnt = ret;tracing_start_tr (tr);
Greg Kroah-Hartman
maintainerPATCH 62/552 tracing: Fix use-after-free with same-name named triggers
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hui Su <[email protected]>
commit a7318172aa332a161fb9618286e64454c827f8fd upstream.
When two hist triggers on different events are registered with the same name=, the second one reuses the first as named_data. Both are added to tr->hist_vars by save_hist_vars() during event_hist_trigger_parse(), because save_hist_vars() is called before event_trigger_register() while the named reuse is only detected later, in hist_register_trigger().
In the named-data branch hist_register_trigger() then frees the second histogram's hist_data via destroy_hist_data(), but never removes its tr->hist_vars list entry, leaving a dangling pointer and leaking the trace_array reference it holds.
A later hist trigger that references a variable makes find_var_file() walk tr->hist_vars and dereference the freed hist_data. The bug is reproducible from userspace by writing three hist triggers to tracefs:
cd /sys/kernel/tracing
echo 'hist:keys=common_pid:x=common_pid:name=mh' > events/sched/sched_switch/trigger echo 'hist:keys=common_pid:x=common_pid:name=mh' > events/sched/sched_process_fork/trigger echo 'hist:keys=common_pid:vals=$x' > events/sched/sched_process_exit/trigger
The third write panics the kernel:
BUG: KASAN: slab-use-after-free in find_var_file.part.0+0x272/0x290
Read of size 8 at addr ffff888001f8a0e0 by task sh/1
CPU: 1 UID: 0 PID: 1 Comm: sh Tainted: G D N
Call Trace:
find_var_file.part.0
find_event_var
parse_atom
parse_expr
__create_val_field
event_hist_trigger_parse
trigger_process_regex
event_trigger_write
vfs_write
ksys_write
do_syscall_64
entry_SYSCALL_64_after_hwframe
Allocated by task 1:
event_hist_trigger_parse
Freed by task 1:
hist_register_trigger+0x618/0xa30
event_hist_trigger_parse
The buggy address belongs to freed 2048-byte region
Oops: general protection fault ... RIP: find_var_file.part.0
Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000bFix by removing the hist_data from tr->hist_vars and releasing the trace_array reference in the named-data branch of hist_register_trigger() before freeing the hist_data.
--- kernel/trace/trace_events_hist.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
kernel/trace/trace_events_hist.c +3 -1
@@ -6613,8 +6613,10 @@ static int hist_register_trigger(char *gtracing_set_filter_buffering (file->tr, true); } -if (named_data) +if (named_data) { +remove_hist_vars (hist_data);destroy_hist_data (hist_data); + } out:return ret; }
Greg Kroah-Hartman
maintainerPATCH 63/552 cdx: Fix double free when sysfs file creation fails
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Prasanna Kumar T S M <[email protected]>
commit 6f4acc3a3c300e174e3f586b97b04ed8f5948c36 upstream.
In cdx_create_res_attr(), if sysfs_create_bin_file() fails, the code frees res_attr but doesn't set cdx_dev->res_attr[num] to NULL. This leaves a dangling pointer in the array. Then cdx_destroy_res_attr() frees the already-freed memory. Fix the double free by initializing cdx_dev->res_attr[num] after sysfs_create_bin_file() completes.
--- drivers/cdx/cdx.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/cdx/cdx.c +5 -2
@@ -745,7 +745,6 @@ static int cdx_create_res_attr(struct cdsysfs_bin_attr_init (res_attr); - cdx_dev->res_attr[num] = res_attr;sprintf (res_attr_name,"resource%d" , num); res_attr->mmap = cdx_mmap_resource;
@@ -754,8 +753,12 @@ static int cdx_create_res_attr(struct cd res_attr->size =cdx_resource_len (cdx_dev, num); res_attr->private = (void *)(unsigned long )num; ret =sysfs_create_bin_file (&cdx_dev->dev.kobj, res_attr); -if (ret) +if (ret) {kfree (res_attr); +return ret; + } + + cdx_dev->res_attr[num] = res_attr;return ret; }
Greg Kroah-Hartman
maintainerPATCH 64/552 device property: fix infinite loop in fwnode_for_each_child_node()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xu Yang <[email protected]>
commit 1900692555826753adab8799a1a8d50bb1ee200c upstream.
When iterate over children of a fwnode that has a secondary fwnode, fwnode_get_next_child_node() can enter an infinite loop if the secondary fwnode has more than one child.
Parent Child
(Primary fwnode) FWa: {FWa1, FWa2, FWa3}
(Secondary fwnode) FWb: {FWb1, FWb2}In this case:
┌─> fwnode_get_next_child_node(FWa, FWa1) │ - fwnode_call_ptr_op(FWa, get_next_child_node, FWa1) returns FWa2 │ │ ... │ │ fwnode_get_next_child_node(FWa, FWa3) │ - fwnode_call_ptr_op(FWa, get_next_child_node, FWa3) returns NULL │ - fwnode_call_ptr_op(FWb, get_next_child_node, FWa3) returns FWb1 │ │ fwnode_get_next_child_node(FWa, FWb1) │ - fwnode_call_ptr_op(FWa, get_next_child_node, FWb1) returns FWa1 └────┘
This cause fwnode_for_each_child_node() to loop indefinitely, reapeatedly output {FWa1, FWa2, FWa3, FWb1, FWa1, ...}.
The root cause is that when the current child (FWb1) belongs to the secondary fwnode, calling get_next_child_node() on the parimary fwnode incorrectly returns the first child (FWa1) again instead of NULL.
Fix this by dynamically checking the parent fwnode of the current child before calling get_next_child_node(). This approach follows the pattern established in commit b5b41ab6b0c1 ("device property: Check fwnode->secondary in fwnode_graph_get_next_endpoint()").
--- drivers/base/property.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-)
drivers/base/property.c +16 -3
@@ -797,18 +797,31 @@ struct fwnode_handle * fwnode_get_next_child_node(const struct fwnode_handle *fwnode, struct fwnode_handle *child) { + const struct fwnode_handle *parent; + struct fwnode_handle *child_parent __free(fwnode_handle) = NULL;struct fwnode_handle *next; -if (IS_ERR_OR_NULL (fwnode)) +/* +* If this function is in a loop and the previous iteration returned +* an child from fwnode->secondary, then we need to use the secondary +* as parent rather than @fwnode. +*/ +if (child) { + child_parent =fwnode_get_parent (child); + parent = child_parent; + }else { + parent = fwnode; + } +if (IS_ERR_OR_NULL (parent))return NULL ;/* Try to find a child in primary fwnode */ - next =fwnode_call_ptr_op (fwnode, get_next_child_node, child); + next =fwnode_call_ptr_op (parent, get_next_child_node, child);if (next)return next;/* When no more children in primary, continue with secondary */ -return fwnode_call_ptr_op (fwnode->secondary, get_next_child_node, child); +return fwnode_get_next_child_node (parent->secondary,NULL ); }EXPORT_SYMBOL_GPL (fwnode_get_next_child_node);
Greg Kroah-Hartman
maintainerPATCH 65/552 misc: nsm: bound the device-reported response length
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <[email protected]>
commit 808e530654a5354e6df78863a5d61e4d44e67235 upstream.
nsm_sendrecv_msg_locked() stores the virtqueue used-ring length reported by the NSM device into msg->resp.len without bounding it to the response buffer. A malicious or buggy backend can report a length larger than the response buffer; parse_resp_raw() then copies that many bytes out of the fixed buffer to user space, disclosing adjacent kernel heap (an out-of-bounds read). The request path already floors its length in fill_req_raw(); the response path lacks the symmetric check.
Clamp the stored length to the size of the response buffer. Well-behaved devices report no more than the posted buffer size, so conforming traffic is unaffected.
--- drivers/misc/nsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/misc/nsm.c +1 -1
@@ -243,7 +243,7 @@ static int nsm_sendrecv_msg_locked(struc goto cleanup; } - msg->resp.len = len; + msg->resp.len = min_t(unsigned int, len, sizeof(msg->resp.data)); rc =0 ;
Greg Kroah-Hartman
maintainerPATCH 66/552 powerpc/powermac: fix OF node refcount
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bartosz Golaszewski <[email protected]>
commit bd0abfe6b013aeb2a1aebc5fbc7ceeb50355bda3 upstream.
Platform devices created with platform_device_alloc() call platform_device_release() when the last reference to the device's kobject is dropped. This function calls of_node_put() unconditionally. This works fine for devices created with platform_device_register_full() but users of the split approach (platform_device_alloc() + platform_device_add()) must bump the reference of the of_node they assign manually. Add the missing call to of_node_get().
--- arch/powerpc/platforms/powermac/low_i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/platforms/powermac/low_i2c.c +1 -1
@@ -1505,7 +1505,7 @@ static int __init pmac_i2c_create_platfoif (bus->platform_dev ==NULL )return -ENOMEM ; bus->platform_dev->dev.platform_data = bus; - bus->platform_dev->dev.of_node = bus->busnode; + bus->platform_dev->dev.of_node =of_node_get (bus->busnode);platform_device_add (bus->platform_dev); }
Greg Kroah-Hartman
maintainerPATCH 67/552 rapidio: mport_cdev: fix use-after-free in dma_req_free()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: James Kim <[email protected]>
commit 5cbef379a94b161726c5f504598bf4791d45cedc upstream.
dma_req_free() acquires buf_mutex through req->map, drops the mapping reference with kref_put(), and then dereferences req->map again to unlock the mutex.
If kref_put() drops the last reference, mport_release_mapping() frees the mapping, and the subsequent mutex_unlock() dereferences a freed object. This is a use-after-free.
Fix this by caching map and md before kref_put(), clearing req->map while holding buf_mutex, and using the cached md for mutex unlocking.
The bug is reachable from userspace via the RapidIO mport character device interface.
--- drivers/rapidio/devices/rio_mport_cdev.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
drivers/rapidio/devices/rio_mport_cdev.c +7 -3
@@ -564,9 +564,13 @@ static void dma_req_free(struct kref *re }if (req->map) { -mutex_lock (&req->map->md->buf_mutex); -kref_put (&req->map->ref, mport_release_mapping); -mutex_unlock (&req->map->md->buf_mutex); +struct rio_mport_mapping *map = req->map; +struct mport_dev *md = map->md; + +mutex_lock (&md->buf_mutex); + req->map =NULL ; +kref_put (&map->ref, mport_release_mapping); +mutex_unlock (&md->buf_mutex); }kref_put (&priv->dma_ref, mport_release_dma);
Greg Kroah-Hartman
maintainerPATCH 68/552 Revert "media: v4l2-dev: fix error handling in __video_register_device()"
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hans Verkuil <[email protected]>
commit e7600f5cee5de14065f950807931d6e6d40fb2d7 upstream.
This reverts commit 2a934fdb01db6458288fc9386d3d8ceba6dd551a.
The intentions of that patch were good, but it doesn't work.
The idea is that if device_register fails, you have to do a put_device to let the ref counter release resources.
However, the V4L2 API says that if video_register_device() fails, then you have to call video_device_release(), which kfree()s the video_device struct.
But the put_device() will already have freed the struct, so you end up in a double-free scenario.
There is not really a good way of fixing this without breaking video_register_device() into two parts, one that initializes everything, and one that does the actual device_register, and then converting all V4L2 drivers to this new model.
That is a massive job, and it is very unlikely that device_register will fail.
So rather than ending up in a double-free scenario, just revert this patch, and in that case we'll have a small memory leak. Which is a lot more robust.
--- drivers/media/v4l2-core/v4l2-dev.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
drivers/media/v4l2-core/v4l2-dev.c +7 -7
@@ -1066,25 +1066,25 @@ int __video_register_device(struct video vdev->dev.class = &video_class; vdev->dev.devt =MKDEV (VIDEO_MAJOR , vdev->minor); vdev->dev.parent = vdev->dev_parent; - vdev->dev.release = v4l2_device_release;dev_set_name (&vdev->dev,"%s%d" , name_base, vdev->num); - -/* Increase v4l2_device refcount */ -v4l2_device_get (vdev->v4l2_dev); -mutex_lock (&videodev_lock); ret =device_register (&vdev->dev);if (ret <0 ) {mutex_unlock (&videodev_lock);pr_err ("%s: device_register failed\n" , __func__); -put_device (&vdev->dev); -return ret; + goto cleanup; } +/* Register the release callback that will be called when the last +reference to the device goes away. */ + vdev->dev.release = v4l2_device_release;if (nr !=-1 && nr != vdev->num && warn_if_nr_in_use)pr_warn ("%s: requested %s%d, got %s\n" , __func__, name_base, nr,video_device_node_name (vdev)); +/* Increase v4l2_device refcount */ +v4l2_device_get (vdev->v4l2_dev); +/* Part 5: Register the entity. */ ret =video_register_media_controller (vdev);
Greg Kroah-Hartman
maintainerPATCH 69/552 serial: imx: serialize imx_uart_ports[] lifetime
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Karl Mehltretter <[email protected]>
commit 8b0b29fdcb47907ae0296b8fe829e918e05e300f upstream.
imx_uart_probe() publishes its devm-allocated port in imx_uart_ports[] before uart_add_one_port() because console setup uses the table. The entry is not cleared when adding the port fails or after removal, leaving a dangling pointer.
A sibling probe can register the shared console through that stale entry. This was reproduced under KASAN on QEMU mcimx6ul-evk by unbinding a sibling UART, unbinding the console UART and rebinding the sibling.
Keep the entry valid through uart_remove_one_port(), then clear it. Protect port addition and removal together with their table updates so sibling operations cannot interleave. Reject an occupied slot rather than clobbering an active port during a duplicate-line probe.
--- drivers/tty/serial/imx.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-)
drivers/tty/serial/imx.c +17 -3
@@ -22,6 +22,7 @@#include <linux/clk.h> #include <linux/delay.h> #include <linux/ktime.h> +#include <linux/mutex.h> #include <linux/pinctrl/consumer.h> #include <linux/rational.h> #include <linux/slab.h>
@@ -2079,6 +2080,9 @@ static const struct uart_ops imx_uart_postatic struct imx_port *imx_uart_ports[UART_NR ]; +/* Held across uart_add/remove_one_port(); console callbacks must not take it. */ +static DEFINE_MUTEX (imx_uart_ports_lock); +#if IS_ENABLED (CONFIG_SERIAL_IMX_CONSOLE )static void imx_uart_console_putchar (struct uart_port *port,unsigned char ch) {
@@ -2631,11 +2635,19 @@ static int imx_uart_probe(struct platfor } } - imx_uart_ports[sport->port.line] = sport; -platform_set_drvdata (pdev, sport); - ret =uart_add_one_port (&imx_uart_uart_driver, &sport->port); + scoped_guard(mutex, &imx_uart_ports_lock) { +if (imx_uart_ports[sport->port.line]) { + ret = -EBUSY ; + }else { + imx_uart_ports[sport->port.line] = sport; + ret =uart_add_one_port (&imx_uart_uart_driver, + &sport->port); +if (ret) + imx_uart_ports[sport->port.line] =NULL ; + } + } err_clk:clk_disable_unprepare (sport->clk_ipg);
@@ -2647,7 +2659,9 @@ static void imx_uart_remove(struct platf {struct imx_port *sport =platform_get_drvdata (pdev); +guard (mutex)(&imx_uart_ports_lock);uart_remove_one_port (&imx_uart_uart_driver, &sport->port); + imx_uart_ports[sport->port.line] =NULL ; }static void imx_uart_restore_context (struct imx_port *sport)
Greg Kroah-Hartman
maintainerPATCH 70/552 staging: greybus: hid: fix SET_REPORT return value
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hao-Qun Huang <[email protected]>
commit 6d45195a9626d8aaaaed212c55638829a9c624a3 upstream.
__gb_hid_output_raw_report() stores the result of gb_hid_set_report() in ret and even adjusts it to account for the report ID byte, but then always returns 0.
This hides Greybus transport errors from HID_REQ_SET_REPORT callers, and makes hidraw report zero bytes written to user space on success, although hid_hw_raw_request() is expected to return the number of bytes transferred or a negative errno. The sibling GET_REPORT path, __gb_hid_get_raw_report(), already follows this convention.
Return ret like the other HID transport drivers do.
--- drivers/staging/greybus/hid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/greybus/hid.c +1 -1
@@ -256,7 +256,7 @@ static int __gb_hid_output_raw_report(stif (report_id && ret >=0 ) ret++;/* add report_id to the number of transferred bytes */ -return 0 ; +return ret; } static int gb_hid_raw_request(struct hid_device *hid, unsigned char reportnum,
Greg Kroah-Hartman
maintainerPATCH 71/552 usb: dwc2: gadget: Exit partial power down state when changing USB pull-up
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Francesco Lavra <[email protected]>
commit bf1e90189a98ca4a824fd64b4f3c6043d13c98ea upstream.
When a USB host suspends a connected device, the DWC2 USB device controller enters a partial power down state where controller registers are not accessible. If the USB gadget is then disconnected or deactivated (e.g. when a gadget function is unbound from the controller), the pullup callback in struct usb_gadget_ops is invoked; if the controller is kept in partial power down, the register write in dwc2_hsotg_core_disconnect() does not take effect; as a result, the USB host keeps seeing the device as connected, even though the device is disabled.
Properly exit partial power down state in the pullup callback, so that the USB host detects a device disconnection as intended.
--- drivers/usb/dwc2/gadget.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
drivers/usb/dwc2/gadget.c +10 -1
@@ -4680,6 +4680,7 @@ static int dwc2_hsotg_pullup(struct usb_ {struct dwc2_hsotg *hsotg =to_hsotg (gadget);unsigned long flags; +int ret =0 ;dev_dbg (hsotg->dev,"%s: is_on: %d op_state: %d\n" , __func__, is_on, hsotg->op_state);
@@ -4691,6 +4692,13 @@ static int dwc2_hsotg_pullup(struct usb_ }spin_lock_irqsave (&hsotg->lock, flags); +if (hsotg->in_ppd) { + ret =dwc2_exit_partial_power_down (hsotg,0 , true); +if (ret) { +dev_err (hsotg->dev,"exit partial_power_down failed\n" ); + goto exit; + } + }if (is_on) { hsotg->enabled =1 ;dwc2_hsotg_core_init_disconnected (hsotg, false);
@@ -4704,9 +4712,10 @@ static int dwc2_hsotg_pullup(struct usb_ } hsotg->gadget.speed =USB_SPEED_UNKNOWN ; +exit:spin_unlock_irqrestore (&hsotg->lock, flags); -return 0 ; +return ret; }static int dwc2_hsotg_vbus_session (struct usb_gadget *gadget,int is_active)
Greg Kroah-Hartman
maintainerPATCH 72/552 usb: dwc3: gadget: Fix use-after-free in dwc3_gadget_free_endpoints due to race condition
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pei Xiao <[email protected]>
commit 9c855832790cd488d87de1885974f4c37cfe7358 upstream.
In dwc3_gadget_init_endpoint, &dep->nostream_work is bound with dwc3_nostream_work, and dwc3_gadget_endpoint_stream_event can queue this delayed work on system_percpu_wq when a DEPEVT_STREAM_NOSTREAM event is received.
If we remove the gadget, dwc3_gadget_free_endpoints makes cleanup and the memory allocated for dep with kzalloc() is released by kfree(dep), while the delayed work mentioned above may still be pending or running. The sequence of operations that may lead to a UAF bug is as follows:
CPU0 CPU1
| dwc3_thread_interrupt
| dwc3_endpoint_interrupt
| dwc3_gadget_endpoint_stream_event
| queue_delayed_work(system_percpu_wq,
| &dep->nostream_work)
dwc3_gadget_free_endpoints |
dwc3_free_trb_pool(dep) |
list_del(&dep->endpoint.ep_list) |
dwc3_debugfs_remove_endpoint_dir(dep) |
kfree(dep) |
// dep is freed |
| dwc3_nostream_work
| // use dep (use-after-free)Fix it by canceling the delayed work before kfree(dep) in dwc3_gadget_free_endpoints.
--- drivers/usb/dwc3/gadget.c | 1 + 1 file changed, 1 insertion(+)
drivers/usb/dwc3/gadget.c +1 -0
@@ -3497,6 +3497,7 @@ static void dwc3_gadget_free_endpoints(s }dwc3_debugfs_remove_endpoint_dir (dep); +cancel_delayed_work_sync (&dep->nostream_work);kfree (dep); } }
Greg Kroah-Hartman
maintainerPATCH 73/552 usb: gadget: at91_udc: drain polled-VBUS timer/work before udc is freed
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fan Wu <[email protected]>
commit c27d13ce4bab80fbdf6523928071b6c24b37606c upstream.
In polled-VBUS mode (board.vbus_pin && board.vbus_polled), probe arms a self-restarting cycle: at91_vbus_timer() schedules vbus_timer_work, and at91_vbus_timer_work() calls at91_vbus_update() and re-arms the timer via mod_timer(). Both recover the same udc through container_of and dereference it on every iteration.
Neither teardown path cancels this cycle. udc is devm-allocated, so it is freed after at91udc_remove() returns, and is likewise freed when probe fails and devres runs. A timer callback or work item that is pending or running at either point dereferences the freed udc.
Add at91_udc_shutdown_vbus_timer() and call it from at91udc_remove() and from the usb_add_gadget_udc() failure path in probe; the remaining probe error paths fail before the timer is armed. timer_shutdown_sync() waits for a running callback and clears timer->function, which makes the work handler's mod_timer() a permanent no-op; cancel_work_sync() then drains any pending or running work whose re-arm attempt now does nothing. The timer must be shut down first, since cancelling the work alone would let the timer re-queue it. The guard mirrors probe: in IRQ mode the timer and work_struct are never initialized.
This does not require a fault; a normal driver unbind can interleave with an already queued work item.
This issue was found by an in-house static analysis tool.
--- drivers/usb/gadget/udc/at91_udc.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)
drivers/usb/gadget/udc/at91_udc.c +19 -1
@@ -1794,6 +1794,19 @@ static void at91udc_of_init(struct at91_ udc->caps = match->data; } +/* +* The work handler re-arms this timer, so shut the timer down before +* draining the work; otherwise it restarts the polling cycle. +*/ +static void at91_udc_shutdown_vbus_timer (struct at91_udc *udc) +{ +if (!(udc->board.vbus_pin && udc->board.vbus_polled)) +return ; + +timer_shutdown_sync (&udc->vbus_timer); +cancel_work_sync (&udc->vbus_timer_work); +} +static int at91udc_probe (struct platform_device *pdev) {struct device *dev = &pdev->dev;
@@ -1907,7 +1920,7 @@ static int at91udc_probe(struct platform } retval =usb_add_gadget_udc (dev, &udc->gadget);if (retval) - goto err_unprepare_iclk; + goto err_shutdown_vbus;dev_set_drvdata (dev, udc);device_init_wakeup (dev,1 );create_debug_file (udc);
@@ -1915,6 +1928,8 @@ static int at91udc_probe(struct platformINFO ("%s version %s\n" , driver_name,DRIVER_VERSION );return 0 ; +err_shutdown_vbus: +at91_udc_shutdown_vbus_timer (udc); err_unprepare_iclk:clk_unprepare (udc->iclk); err_unprepare_fclk:
@@ -1933,6 +1948,9 @@ static void at91udc_remove(struct platfoDBG ("remove\n" );usb_del_gadget_udc (&udc->gadget); + +at91_udc_shutdown_vbus_timer (udc); +if (udc->driver) {dev_err (&pdev->dev,"Driver still in use but removing anyhow\n" );
Greg Kroah-Hartman
maintainerPATCH 74/552 USB: phy: fsl-usb: fix missing static keywords
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 80574c40598aedbc1751c528e414d7e224bc6313 upstream.
A recent change enabling compile testing of a Freescale dual-role controller indirectly enabled a USB PHY driver to be built. That driver in turn is missing a bunch of static keywords which results in warnings like:
drivers/usb/phy/phy-fsl-usb.c:105:5: error: no previous prototype for 'write_ulpi' [-Werror=missing-prototypes]
105 | int write_ulpi(u8 addr, u8 data)
| ^~~~~~~~~~
which consequently breaks -Werror builds.
Add the missing static keywords.
--- drivers/usb/phy/phy-fsl-usb.c | 52 +++++++++++++++++++++--------------------- drivers/usb/phy/phy-fsl-usb.h | 6 ++-- 2 files changed, 29 insertions(+), 29 deletions(-)
drivers/usb/phy/phy-fsl-usb.c +26 -26
@@ -46,7 +46,7 @@static const char driver_name[] ="fsl-usb2-otg" ; -const pm_message_t otg_suspend_state = { +static const pm_message_t otg_suspend_state = { .event =1 , };
@@ -57,11 +57,11 @@ static struct fsl_otg *fsl_otg_dev;static int srp_wait_done;/* FSM timers */ -struct fsl_otg_timer *a_wait_vrise_tmr, *a_wait_bcon_tmr, *a_aidl_bdis_tmr, +static struct fsl_otg_timer *a_wait_vrise_tmr, *a_wait_bcon_tmr, *a_aidl_bdis_tmr, *b_ase0_brst_tmr, *b_se0_srp_tmr;/* Driver specific timers */ -struct fsl_otg_timer *b_data_pulse_tmr, *b_vbus_pulse_tmr, *b_srp_fail_tmr, +static struct fsl_otg_timer *b_data_pulse_tmr, *b_vbus_pulse_tmr, *b_srp_fail_tmr, *b_srp_wait_tmr, *a_wait_enum_tmr;static struct list_head active_timers;
@@ -102,7 +102,7 @@ static void (*_fsl_writel)(u32 v, unsign#define fsl_writel (val, addr) writel(val, addr)#endif /* CONFIG_PPC32 */ -int write_ulpi (u8 addr,u8 data) +static int write_ulpi (u8 addr,u8 data) {u32 temp;
@@ -115,7 +115,7 @@ int write_ulpi(u8 addr, u8 data)/* Operations that will be called from OTG Finite State Machine */ /* Charge vbus for vbus pulsing in SRP */ -void fsl_otg_chrg_vbus (struct otg_fsm *fsm,int on) +static void fsl_otg_chrg_vbus (struct otg_fsm *fsm,int on) {u32 tmp;
@@ -133,7 +133,7 @@ void fsl_otg_chrg_vbus(struct otg_fsm *f }/* Discharge vbus through a resistor to ground */ -void fsl_otg_dischrg_vbus (int on) +static void fsl_otg_dischrg_vbus (int on) {u32 tmp;
@@ -151,7 +151,7 @@ void fsl_otg_dischrg_vbus(int on) }/* A-device driver vbus, controlled through PP bit in PORTSC */ -void fsl_otg_drv_vbus (struct otg_fsm *fsm,int on) +static void fsl_otg_drv_vbus (struct otg_fsm *fsm,int on) {u32 tmp;
@@ -169,7 +169,7 @@ void fsl_otg_drv_vbus(struct otg_fsm *fs* Pull-up D+, signalling connect by periperal. Also used in * data-line pulsing in SRP */ -void fsl_otg_loc_conn (struct otg_fsm *fsm,int on) +static void fsl_otg_loc_conn (struct otg_fsm *fsm,int on) {u32 tmp;
@@ -188,7 +188,7 @@ void fsl_otg_loc_conn(struct otg_fsm *fs* port. In host mode, controller will automatically send SOF. * Suspend will block the data on the port. */ -void fsl_otg_loc_sof (struct otg_fsm *fsm,int on) +static void fsl_otg_loc_sof (struct otg_fsm *fsm,int on) {u32 tmp;
@@ -203,7 +203,7 @@ void fsl_otg_loc_sof(struct otg_fsm *fsm }/* Start SRP pulsing by data-line pulsing, followed with v-bus pulsing. */ -void fsl_otg_start_pulse (struct otg_fsm *fsm) +static void fsl_otg_start_pulse (struct otg_fsm *fsm) {u32 tmp;
@@ -219,7 +219,7 @@ void fsl_otg_start_pulse(struct otg_fsmfsl_otg_add_timer (fsm, b_data_pulse_tmr); } -void b_data_pulse_end (unsigned long foo) +static void b_data_pulse_end (unsigned long foo) {#ifdef HA_DATA_PULSE #else
@@ -230,7 +230,7 @@ void b_data_pulse_end(unsigned long foo)fsl_otg_pulse_vbus (); } -void fsl_otg_pulse_vbus (void ) +static void fsl_otg_pulse_vbus (void ) { srp_wait_done =0 ;fsl_otg_chrg_vbus (&fsl_otg_dev->fsm,1 );
@@ -238,7 +238,7 @@ void fsl_otg_pulse_vbus(void)fsl_otg_add_timer (&fsl_otg_dev->fsm, b_vbus_pulse_tmr); } -void b_vbus_pulse_end (unsigned long foo) +static void b_vbus_pulse_end (unsigned long foo) {fsl_otg_chrg_vbus (&fsl_otg_dev->fsm,0 );
@@ -251,7 +251,7 @@ void b_vbus_pulse_end(unsigned long foo)fsl_otg_add_timer (&fsl_otg_dev->fsm, b_srp_wait_tmr); } -void b_srp_end (unsigned long foo) +static void b_srp_end (unsigned long foo) {fsl_otg_dischrg_vbus (0 ); srp_wait_done =1 ;
@@ -266,7 +266,7 @@ void b_srp_end(unsigned long foo)* a_host will start by SRP. It needs to set b_hnp_enable before * actually suspending to start HNP */ -void a_wait_enum (unsigned long foo) +static void a_wait_enum (unsigned long foo) {VDBG ("a_wait_enum timeout\n" );if (!fsl_otg_dev->phy.otg->host->b_hnp_enable)
@@ -276,13 +276,13 @@ void a_wait_enum(unsigned long foo) }/* The timeout callback function to set time out bit */ -void set_tmout (unsigned long indicator) +static void set_tmout (unsigned long indicator) { *(int *)indicator =1 ; }/* Initialize timers */ -int fsl_otg_init_timers (struct otg_fsm *fsm) +static int fsl_otg_init_timers (struct otg_fsm *fsm) {/* FSM used timers */ a_wait_vrise_tmr = otg_timer_initializer(&set_tmout, TA_WAIT_VRISE,
@@ -339,7 +339,7 @@ int fsl_otg_init_timers(struct otg_fsm * }/* Uninitialize timers */ -void fsl_otg_uninit_timers (void ) +static void fsl_otg_uninit_timers (void ) {/* FSM used timers */ kfree (a_wait_vrise_tmr);
@@ -391,7 +391,7 @@ static struct fsl_otg_timer *fsl_otg_get }/* Add timer to timer list */ -void fsl_otg_add_timer (struct otg_fsm *fsm,void *gtimer) +static void fsl_otg_add_timer (struct otg_fsm *fsm,void *gtimer) {struct fsl_otg_timer *timer = gtimer;struct fsl_otg_timer *tmp_timer;
@@ -421,7 +421,7 @@ static void fsl_otg_fsm_add_timer(struct }/* Remove timer from the timer list; clear timeout status */ -void fsl_otg_del_timer (struct otg_fsm *fsm,void *gtimer) +static void fsl_otg_del_timer (struct otg_fsm *fsm,void *gtimer) {struct fsl_otg_timer *timer = gtimer;struct fsl_otg_timer *tmp_timer, *del_tmp;
@@ -443,7 +443,7 @@ static void fsl_otg_fsm_del_timer(struct }/* Reset controller, not reset the bus */ -void otg_reset_controller (void ) +static void otg_reset_controller (void ) {u32 command;
@@ -455,7 +455,7 @@ void otg_reset_controller(void) }/* Call suspend/resume routines in host driver */ -int fsl_otg_start_host (struct otg_fsm *fsm,int on) +static int fsl_otg_start_host (struct otg_fsm *fsm,int on) {struct usb_otg *otg = fsm->otg;struct device *dev;
@@ -522,7 +522,7 @@ end:* Call suspend and resume function in udc driver * to stop and start udc driver. */ -int fsl_otg_start_gadget (struct otg_fsm *fsm,int on) +static int fsl_otg_start_gadget (struct otg_fsm *fsm,int on) {struct usb_otg *otg = fsm->otg;struct device *dev;
@@ -704,7 +704,7 @@ static int fsl_otg_start_hnp(struct usb_* intact. It needs to have knowledge of some USB interrupts * such as port change. */ -irqreturn_t fsl_otg_isr (int irq,void *dev_id) +static irqreturn_t fsl_otg_isr (int irq,void *dev_id) {struct otg_fsm *fsm = &((struct fsl_otg *)dev_id)->fsm;struct usb_otg *otg = ((struct fsl_otg *)dev_id)->phy.otg;
@@ -830,7 +830,7 @@ err: }/* OTG Initialization */ -int usb_otg_start (struct platform_device *pdev) +static int usb_otg_start (struct platform_device *pdev) {struct fsl_otg *p_otg;struct usb_phy *otg_trans =usb_get_phy (USB_PHY_TYPE_USB2 );
@@ -1002,7 +1002,7 @@ static void fsl_otg_remove(struct platfo pdata->exit (pdev); } -struct platform_driver fsl_otg_driver = { +static struct platform_driver fsl_otg_driver = { .probe = fsl_otg_probe, .remove = fsl_otg_remove, .driver = {
drivers/usb/phy/phy-fsl-usb.h +3 -3
@@ -373,6 +373,6 @@ struct fsl_otg_config {#define FSL_OTG_NAME "fsl-usb2-otg" -void fsl_otg_add_timer (struct otg_fsm *fsm,void *timer); -void fsl_otg_del_timer (struct otg_fsm *fsm,void *timer); -void fsl_otg_pulse_vbus (void ); +static void fsl_otg_add_timer (struct otg_fsm *fsm,void *timer); +static void fsl_otg_del_timer (struct otg_fsm *fsm,void *timer); +static void fsl_otg_pulse_vbus (void );
Greg Kroah-Hartman
maintainerPATCH 75/552 usb: typec: tcpci: pass correct rx_type to tcpm_pd_receive()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xu Yang <[email protected]>
commit b691a07c5f644080374ddd24de6a0e05f5d28744 upstream.
Previously, tcpci_irq() always passed TCPC_TX_SOP as the receive type to tcpm_pd_receive(), ignoring the actual frame type reported by the TCPC_RX_BUF_FRAME_TYPE register.
Cache the TCPC_RX_DETECT register value in rx_type_mask variable. When a PD messageis received, read TCPC_RX_BUF_FRAME_TYPE register and handle the message only if its frame type is enabled in mask.
The TCPC_RX_BUF_FRAME_TYPE register records the received message type, which has a 1:1 mapping to enum tcpm_transmit_type.
--- drivers/usb/typec/tcpm/tcpci.c | 12 +++++++++++- include/linux/usb/tcpci.h | 1 + 2 files changed, 12 insertions(+), 1 deletion(-)
drivers/usb/typec/tcpm/tcpci.c +11 -1
@@ -37,6 +37,7 @@ struct tcpci {struct regmap *regmap;unsigned int alert_mask; +unsigned int rx_type_mask;bool controls_vbus;
@@ -485,6 +486,8 @@ static int tcpci_set_pd_rx(struct tcpc_dif (tcpci->data->cable_comm_capable) reg |=TCPC_RX_DETECT_SOP1 ; } + + tcpci->rx_type_mask = reg; ret =regmap_write (tcpci->regmap,TCPC_RX_DETECT , reg);if (ret <0 )return ret;
@@ -746,6 +749,7 @@ process_status:if (status &TCPC_ALERT_RX_STATUS ) {struct pd_message msg;unsigned int cnt, payload_cnt; +enum tcpm_transmit_type rx_type;u16 header;regmap_read (tcpci->regmap,TCPC_RX_BYTE_CNT , &cnt);
@@ -770,10 +774,16 @@ process_status:regmap_raw_read (tcpci->regmap,TCPC_RX_DATA , &msg.payload, payload_cnt); + ret =regmap_read (tcpci->regmap,TCPC_RX_BUF_FRAME_TYPE , &rx_type); +if (ret) +return ret; +/* Read complete, clear RX status alert bit */ tcpci_write16 (tcpci,TCPC_ALERT ,TCPC_ALERT_RX_STATUS ); -tcpm_pd_receive (tcpci->port, &msg,TCPC_TX_SOP ); + rx_type &=TCPC_RX_BUF_FRAME_TYPE_MASK ; +if (tcpci->rx_type_mask &BIT (rx_type)) +tcpm_pd_receive (tcpci->port, &msg, rx_type); }if (tcpci->data->vbus_vsafe0v && (status &TCPC_ALERT_EXTENDED_STATUS )) {
include/linux/usb/tcpci.h +1 -0
@@ -144,6 +144,7 @@#define TCPC_RX_BUF_FRAME_TYPE 0x31#define TCPC_RX_BUF_FRAME_TYPE_SOP 0#define TCPC_RX_BUF_FRAME_TYPE_SOP1 1 +#define TCPC_RX_BUF_FRAME_TYPE_MASK GENMASK(2, 0)#define TCPC_RX_HDR 0x32#define TCPC_RX_DATA 0x34/* through 0x4f */
Greg Kroah-Hartman
maintainerPATCH 76/552 usb: typec: thunderbolt: Disable work before freeing tbt on remove
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fan Wu <[email protected]>
commit 92090f6ff2acc81e9dd99881dcfb4f8c1bdaabd3 upstream.
tbt_altmode_remove() drops the plug and cable references without draining tbt->work. The work function dereferences those references, and can also requeue itself in its error path. The VDM callbacks can queue the same work item.
Disable and drain tbt->work before dropping the references. This waits for an existing invocation and prevents subsequent schedule_work() calls from queueing it during teardown.
This issue was found by an in-house static analysis tool and confirmed by manual code review.
--- drivers/usb/typec/altmodes/thunderbolt.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/usb/typec/altmodes/thunderbolt.c +2 -0
@@ -303,6 +303,8 @@ static void tbt_altmode_remove(struct ty {struct tbt_altmode *tbt =typec_altmode_get_drvdata (alt); +disable_work_sync (&tbt->work); +for (int i =TYPEC_PLUG_SOP_PP ; i >=0 ; --i) {if (tbt->plug[i])typec_altmode_put_plug (tbt->plug[i]);
Greg Kroah-Hartman
maintainerPATCH 77/552 usb: typec: ucsi: use UCSI_TIMEOUT_MS for sync command completion
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Huang Wei <[email protected]>
commit eb4573cf2fd860b20adfae050c3f6ec6ddc3abdb upstream.
The synchronous command completion path in ucsi_sync_control_common() hardcodes a 5 second (5 * HZ) timeout when waiting for the PPM to signal command completion via ACPI notification. This value matched UCSI_TIMEOUT_MS when it was still 5000 ms, but it was not updated when that macro was later raised to 10000 ms to fix PPM reset timeouts.
As a result, the two PPM communication paths are now inconsistent: the polling path in ucsi_reset_ppm() respects the 10 second timeout, while the event-driven completion path still uses 5 seconds. On machines where the firmware is slow to respond during boot (e.g. some Lenovo ThinkPad models such as the E14 Gen 7), commands sent after the PPM reset, such as SET_NOTIFICATION_ENABLE and GET_CAPABILITY, can exceed 5 seconds and cause UCSI initialization to fail with:
ucsi_acpi USBC000:00: error -ETIMEDOUT: PPM init failed
Once UCSI init aborts, USB-C PD negotiation never completes, which in turn blocks USB-C dock enumeration since the dock depends on a successful PD contract.
Replace the hardcoded 5 * HZ with msecs_to_jiffies(UCSI_TIMEOUT_MS) so that both communication paths share a single, consistent timeout value, and future adjustments to UCSI_TIMEOUT_MS are picked up automatically.
--- drivers/usb/typec/ucsi/ucsi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/usb/typec/ucsi/ucsi.c +2 -1
@@ -78,7 +78,8 @@ int ucsi_sync_control_common(struct ucsiif (ret) goto out_clear_bit; -if (!wait_for_completion_timeout (&ucsi->complete,5 *HZ )) +if (!wait_for_completion_timeout (&ucsi->complete, +msecs_to_jiffies (UCSI_TIMEOUT_MS ))) ret = -ETIMEDOUT ; out_clear_bit:
Greg Kroah-Hartman
maintainerPATCH 78/552 usb: gadget: u_audio: Fix use-after-free on sound card disconnect
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sonali Pradhan <[email protected]>
commit 858965947081d10d41d9a1010a540d3d5eea958b upstream.
g_audio_cleanup() invokes snd_card_free_when_closed() to initiate sound card teardown and immediately frees the underlying struct snd_uac_chip context. However, snd_card_free_when_closed() returns asynchronously while ALSA control elements (kctls) remain open in userspace.
When userspace control applications access or close these open file descriptors, kctl callbacks attempt to dereference kctl->private_data pointing to &uac->c_prm or &uac->p_prm within the freed uac structure, resulting in a use-after-free (UAF) memory corruption.
Fix this issue by deferring the destruction of struct snd_uac_chip until all references to the ALSA sound card are released. Register a custom card->private_free callback (u_audio_card_free) during g_audio_setup() that frees uac and its associated playback/capture request and ring buffers only when the sound card reference count drops to zero.
--- drivers/usb/gadget/function/u_audio.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-)
drivers/usb/gadget/function/u_audio.c +18 -6
@@ -1177,6 +1177,20 @@ static struct snd_kcontrol_new u_audio_c }, }; +static void u_audio_card_free (struct snd_card *card) +{ +struct snd_uac_chip *uac = card->private_data; + +if (!uac) +return ; + +kfree (uac->p_prm.reqs); +kfree (uac->c_prm.reqs); +kfree (uac->p_prm.rbuf); +kfree (uac->c_prm.rbuf); +kfree (uac); +} +int g_audio_setup (struct g_audio *g_audio,const char *pcm_name,const char *card_name) {
@@ -1258,6 +1272,8 @@ int g_audio_setup(struct g_audio *g_audi goto fail; uac->card = card; + card->private_data = uac; + card->private_free = u_audio_card_free;/* * Create first PCM device
@@ -1426,6 +1442,8 @@ int g_audio_setup(struct g_audio *g_audi snd_fail:snd_card_free (card); +return err; + fail:kfree (uac->p_prm.reqs);kfree (uac->c_prm.reqs);
@@ -1451,12 +1469,6 @@ void g_audio_cleanup(struct g_audio *g_a card = uac->card;if (card)snd_card_free_when_closed (card); - -kfree (uac->p_prm.reqs); -kfree (uac->c_prm.reqs); -kfree (uac->p_prm.rbuf); -kfree (uac->c_prm.rbuf); -kfree (uac); }EXPORT_SYMBOL_GPL (g_audio_cleanup);
Greg Kroah-Hartman
maintainerPATCH 79/552 usb: gadget: snps_udc_plat: clean up PHY on probe deferral
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Myeonghun Pak <[email protected]>
commit 886338ea7d40e4ba5123c58204d7f7e53d825825 upstream.
When the referenced extcon device has not registered yet, extcon_get_edev_by_phandle() returns -EPROBE_DEFER after the driver has initialized and powered on the PHY. The direct return bypasses the common cleanup path and leaves both operations unbalanced.
Store the lookup error first and route deferred probing through exit_phy, while retaining the existing behavior of suppressing the error message for deferral.
This issue was identified during our ongoing static-analysis research while reviewing kernel code.
--- drivers/usb/gadget/udc/snps_udc_plat.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/usb/gadget/udc/snps_udc_plat.c +2 -3
@@ -159,10 +159,9 @@ static int udc_plat_probe(struct platforif (of_property_present (dev->of_node,"extcon" )) { udc->edev =extcon_get_edev_by_phandle (dev,0 );if (IS_ERR (udc->edev)) { -if (PTR_ERR (udc->edev) == -EPROBE_DEFER ) -return -EPROBE_DEFER ; -dev_err (dev,"Invalid or missing extcon\n" ); ret =PTR_ERR (udc->edev); +if (ret != -EPROBE_DEFER ) +dev_err (dev,"Invalid or missing extcon\n" ); goto exit_phy; }
Greg Kroah-Hartman
maintainerPATCH 80/552 usb: gadget: midi2: remove default configfs groups on teardown
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joshua Crofts <[email protected]>
commit 0f6bffb5008f0cba9cad5ded2caccc64466a6e54 upstream.
f_midi2_alloc_inst() creates default configfs child groups for the default endpoint and default block using configfs_add_default_group(), setting their internal refcount to 1.
However, during function teardown in f_midi2_free_inst() or EP cleanup in f_midi2_ep_opts_release(), configfs_remove_default_groups() is never called, therefore never dropping the refcount and leaking struct f_midi2_ep_opts and f_midi2_block_opts.
Add the missing configfs_remove_default_groups() in the afformentioned functions to free the structs properly.
--- drivers/usb/gadget/function/f_midi2.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/usb/gadget/function/f_midi2.c +2 -0
@@ -2474,6 +2474,7 @@ static void f_midi2_ep_opts_release(stru {struct f_midi2_ep_opts *opts =to_f_midi2_ep_opts (item); +configfs_remove_default_groups (&opts->group);kfree (opts->info.ep_name);kfree (opts->info.product_id);kfree (opts);
@@ -2640,6 +2641,7 @@ static void f_midi2_free_inst(struct usb opts = container_of(f, struct f_midi2_opts, func_inst); +configfs_remove_default_groups (&opts->func_inst.group);kfree (opts->info.iface_name);kfree (opts); }
Greg Kroah-Hartman
maintainerPATCH 81/552 usb: gadget: f_tcm: fix deadlock in usbg_make_tpg()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yun Zhou <[email protected]>
commit 9dbf74f4022f80f7669d2b3c22c5deb46c1b5674 upstream.
usbg_make_tpg() held dep_lock while calling configfs_depend_item_unlocked(), which acquires the configfs root inode lock when operating across subsystems. This creates a circular lock dependency with configfs_rmdir():
dep_lock -> configfs root inode lock -> su_mutex -> dep_lock
In usbg_make_tpg(), dep_lock only serialized the read of opts->ready, which is a monotonic flag that transitions from false to true exactly once (in tcm_set_name()) and never reverts. Remove dep_lock from usbg_make_tpg() entirely and use READ_ONCE/WRITE_ONCE to access opts->ready locklessly instead.
--- drivers/usb/gadget/function/f_tcm.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-)
drivers/usb/gadget/function/f_tcm.c +12 -11
@@ -1674,19 +1674,25 @@ static struct se_portal_group *usbg_make opts = container_of(tpg_instances[i].func_inst, struct f_tcm_opts, func_inst); -mutex_lock (&opts->dep_lock); -if (!opts->ready) - goto unlock_dep; +if (!READ_ONCE (opts->ready)) + goto unlock_inst;if (opts->has_dep) {if (!try_module_get (opts->dependent)) - goto unlock_dep; + goto unlock_inst; }else { +/* +* configfs_depend_item_unlocked() may acquire the configfs +* root inode lock when the target belongs to a different +* subsystem. Calling it under dep_lock would create a +* circular dependency: +* dep_lock -> configfs inode lock -> su_mutex -> dep_lock +*/ ret =configfs_depend_item_unlocked ( wwn->wwn_group.cg_subsys, &opts->func_inst.group.cg_item);if (ret) - goto unlock_dep; + goto unlock_inst; } tpg =kzalloc (sizeof (struct usbg_tpg ),GFP_KERNEL );
@@ -1713,7 +1719,6 @@ static struct se_portal_group *usbg_make tpg_instances[i].tpg = tpg; tpg->fi = tpg_instances[i].func_inst; -mutex_unlock (&opts->dep_lock);mutex_unlock (&tpg_instances_lock);return &tpg->se_tpg;
@@ -1726,8 +1731,6 @@ unref_dep:module_put (opts->dependent); else configfs_undepend_item_unlocked(&opts->func_inst.group.cg_item); -unlock_dep: -mutex_unlock (&opts->dep_lock); unlock_inst:mutex_unlock (&tpg_instances_lock);
@@ -2664,9 +2667,7 @@ static int tcm_set_name(struct usb_functpr_debug ("tcm: Activating %s\n" , name); -mutex_lock (&opts->dep_lock); - opts->ready = true; -mutex_unlock (&opts->dep_lock); +WRITE_ONCE (opts->ready, true);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 82/552 usb: gadget: uvc: Fix null pointer dereference in uvcg_video_init()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeffin Philip <[email protected]>
commit 5b1da38592efdc1a263d4c0353298cba19e9d6fc upstream.
In uvcg_video_init(), if kthread_run_worker() fails, the error logged uses uvcg_err(), however, the pointer it uses:video->uvc is not assigned at this point, triggering a null pointer dereference. Fix this by directly using uvc->func which is assigned already.
--- drivers/usb/gadget/function/uvc_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/gadget/function/uvc_video.c +1 -1
@@ -821,7 +821,7 @@ int uvcg_video_init(struct uvc_video *vi/* Allocate a kthread for asynchronous hw submit handler. */ video->kworker =kthread_run_worker (0 ,"UVCG" );if (IS_ERR (video->kworker)) { -uvcg_err (&video->uvc->func,"failed to create UVCG kworker\n" ); +uvcg_err (&uvc->func,"failed to create UVCG kworker\n" );return PTR_ERR (video->kworker); }
Greg Kroah-Hartman
maintainerPATCH 83/552 usb: gadget: uvc: fix dangling pointers in uvc_function_bind() and uvc_function_unbind()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeffin Philip <[email protected]>
commit bdab5605259ba5d6ff927c1a85cc83eb3ecfdacc upstream.
In uvc_function_bind() error path, we use usb_ep_free_request which uses uvc->control_req but does not set it to NULL afterwards. Thus, uvc->control_req is a dangling pointer causing a UAF. Also we do not set the uvc->control_buf pointer to NULL after freeing it, which is another dangling pointer. Fix it by setting uvc->control_req to NULL after we run usb_ep_free_request() and uvc->control_buf to NULL after kfree. Do the same for uvc_function_unbind().
--- drivers/usb/gadget/function/f_uvc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/usb/gadget/function/f_uvc.c +6 -1
@@ -889,9 +889,12 @@ error_unlock: v4l2_error:v4l2_device_unregister (&uvc->v4l2_dev); error: -if (uvc->control_req) +if (uvc->control_req) {usb_ep_free_request (cdev->gadget->ep0, uvc->control_req); + uvc->control_req =NULL ; + }kfree (uvc->control_buf); + uvc->control_buf =NULL ;usb_free_all_descriptors (f);return ret;
@@ -1075,7 +1078,9 @@ static void uvc_function_unbind(struct u uvc->vdev_release_done =NULL ;usb_ep_free_request (cdev->gadget->ep0, uvc->control_req); + uvc->control_req =NULL ;kfree (uvc->control_buf); + uvc->control_buf =NULL ;usb_free_all_descriptors (f); }
Greg Kroah-Hartman
maintainerPATCH 84/552 usb: gadget: f_fs: Prevent deadlock during ep0 read loop
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Neill Kapron <[email protected]>
commit 569dd7e5dcffe1e1c6b26ca2cd3be57eb433e082 upstream.
Currently, ffs_ep0_read() holds ffs->mutex when it prepares to go to sleep waiting for an event. When no setup events are pending, it calls wait_event_interruptible_exclusive_locked_irq() with the mutex still held. The wait macro deliberately drops the waitqueue spinlock before sleeping but does not drop the mutex.
If a userspace daemon is polling ep0 via read() and the gadget is asynchronously torn down via configfs (e.g., echo "" > UDC), a deadlock can occur:
1. The configfs teardown calls functionfs_unbind(), which queues a FUNCTIONFS_UNBIND event.
2. The daemon wakes up, consumes the event, and drops the mutex.
3. However, if the daemon loops and immediately issues another read() before exiting, it reacquires ffs->mutex and again goes into an interruptible sleep.
4. Meanwhile, functionfs_unbind() continues execution and attempts to acquire ffs->mutex to tear down ep0req.
5. The kernel deadlocks because the configfs thread is stuck in an uninterruptible sleep waiting for the mutex, while the userspace daemon is in an interruptible sleep holding the mutex forever because no more events will arrive.
To fix this, we drop both the waitqueue spinlock and ffs->mutex before going to sleep, and use wait_event_interruptible_exclusive() instead. Upon waking up, we jump back to the retry label to safely reacquire the mutex and re-evaluate the state machine. By not sleeping with ffs->mutex held, we natively decouple gadget teardowns (which require the mutex) from userspace polling.
--- drivers/usb/gadget/function/f_fs.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
drivers/usb/gadget/function/f_fs.c +10 -4
@@ -549,6 +549,7 @@ static ssize_t ffs_ep0_read(struct fileif (ffs_setup_state_clear_cancelled (ffs) ==FFS_SETUP_CANCELLED )return -EIDRM ; +retry:/* Acquire mutex */ ret =ffs_mutex_lock (&ffs->mutex, file->f_flags &O_NONBLOCK );if (ret <0 )
@@ -583,10 +584,15 @@ static ssize_t ffs_ep0_read(struct filebreak ; } -if (wait_event_interruptible_exclusive_locked_irq (ffs->ev.waitq, - ffs->ev.count)) { - ret = -EINTR ; -break ; +if (!ffs->ev.count) { +spin_unlock_irq (&ffs->ev.waitq.lock); +mutex_unlock (&ffs->mutex); + +if (wait_event_interruptible_exclusive (ffs->ev.waitq, + ffs->ev.count)) +return -EINTR ; + + goto retry; }/* unlocks spinlock */
Greg Kroah-Hartman
maintainerPATCH 85/552 fpga: altera-cvp: Avoid out-of-bounds read in trailing byte write
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daisuke Matsuda <[email protected]>
commit 9da70a43b5fea60d758137f7f0ccfe19356cb5bb upstream.
The trailing byte path in altera_cvp_send_block() dereferences a u32 pointer even when only 1-3 bytes remain in the input buffer. If the buffer ends at a page or scatterlist boundary, this can read past the valid image data and fault.
Copy the remaining bytes into a zero-initialized u32 before writing the final word so only valid bytes are read from the input buffer.
--- drivers/fpga/altera-cvp.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/fpga/altera-cvp.c +6 -4
@@ -16,6 +16,7 @@#include <linux/module.h> #include <linux/pci.h> #include <linux/sizes.h> +#include <linux/string.h> #define CVP_BAR 0/* BAR used for data transfer in memory mode */ #define CVP_DUMMY_WR 244/* dummy writes to clear CvP state machine */
@@ -264,7 +265,7 @@ static int altera_cvp_v2_wait_for_creditstatic int altera_cvp_send_block (struct altera_cvp_conf *conf,const u32 *data,size_t len) { -u32 mask, words = len /sizeof (u32); +u32 words = len /sizeof (u32);int i, remainder;for (i =0 ; i < words; i++)
@@ -273,9 +274,10 @@ static int altera_cvp_send_block(struct/* write up to 3 trailing bytes, if any */ remainder = len %sizeof (u32);if (remainder) { - mask =BIT (remainder *8 ) -1 ; -if (mask) - conf->write_data (conf, *data & mask); +u32 word =0 ; + +memcpy (&word, data, remainder); + conf->write_data (conf, word); }return 0 ;
Greg Kroah-Hartman
maintainerPATCH 86/552 HID: sensor-hub: Fix out-of-bounds write in sensor_hub_get_feature
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xingrui Li <[email protected]>
commit c92693f3ed099401d0383ef35ca1fe1e6ba033de upstream.
sensor_hub_get_feature() clamps its return value to the caller's buffer size, but the copy loop still copies field->report_size / 8 bytes for each report value. A malicious HID descriptor can advertise a large feature field size while an IIO caller supplies a small stack buffer, such as a single s32, causing an out-of-bounds write.
HID core stores parsed report values in __s32 slots and clamps extracted values to 32 bits. Reject feature fields that require more than one slot per value, guard the total byte count calculation, and clamp each per-value copy to the remaining caller buffer.
--- drivers/hid/hid-sensor-hub.c | 44 +++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-)
drivers/hid/hid-sensor-hub.c +26 -18
@@ -239,12 +239,17 @@ int sensor_hub_get_feature(struct hid_se u32 field_index, int buffer_size, void *buffer) { struct hid_report *report; +struct hid_field *field;struct sensor_hub_data *data =hid_get_drvdata (hsdev->hdev); -int report_size; +size_t field_size; +size_t report_size; +size_t copied =0 ; +size_t to_copy;int ret =0 ; -u8 *val_ptr; -int buffer_index =0 ; -int i; +unsigned int i; + +if (!buffer || buffer_size <=0 ) +return -EINVAL ;memset (buffer,0 , buffer_size);
@@ -258,26 +263,29 @@ int sensor_hub_get_feature(struct hid_sehid_hw_request (hsdev->hdev, report,HID_REQ_GET_REPORT );hid_hw_wait (hsdev->hdev); + field = report->field[field_index]; +/* calculate number of bytes required to read this field */ - report_size =DIV_ROUND_UP (report->field[field_index]->report_size, -8 ) * - report->field[field_index]->report_count; -if (!report_size) { + field_size =DIV_ROUND_UP (field->report_size,8 ); +/* HID core stores each parsed report value in a __s32 slot. */ +if (!field_size || field_size >sizeof (field->value[0 ])) { + ret = -EINVAL ; + goto done_proc; + } +if (field->report_count >SIZE_MAX / field_size) { ret = -EINVAL ; goto done_proc; } - ret =min (report_size, buffer_size); - val_ptr = (u8 *)report->field[field_index]->value; -for (i =0 ; i < report->field[field_index]->report_count; ++i) { -if (buffer_index >= ret) -break ; - -memcpy (&((u8 *)buffer)[buffer_index], val_ptr, - report->field[field_index]->report_size /8 ); - val_ptr +=sizeof (__s32); - buffer_index += (report->field[field_index]->report_size /8 ); + report_size = field_size * field->report_count; + report_size =min_t (size_t, report_size, buffer_size); + +for (i =0 ; i < field->report_count && copied < report_size; ++i) { + to_copy =min (field_size, report_size - copied); +memcpy (&((u8 *)buffer)[copied], &field->value[i], to_copy); + copied += to_copy; } + ret = copied; done_proc:mutex_unlock (&data->mutex);
Greg Kroah-Hartman
maintainerPATCH 87/552 lib/ucs2_string.c: fix out-of-bounds read in ucs2_strnlen()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vincent Mailhol <[email protected]>
commit cec0d03fe785380540dc1b4d07c80f67ae2ffc78 upstream.
Patch series "lib/ucs2_string.c: fix out-of-bounds read in ucs2_strnlen()", v2.
This series fixes an off-by-one out-of-bounds read in ucs2_strnlen().
The first patch is the real fix, the second patch comes as a bonus and fixes the code indentation.
This patch (of 2):
ucs2_strnlen() checks the current character before checking whether the caller-provided maximum length has been reached. If the input is not NUL-terminated within that bound, the loop can read one ucs2_char_t past the limit.
Test the length before dereferencing to prevent an off-by-one out-of-bounds read.
--- lib/ucs2_string.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
lib/ucs2_string.c +1 -1
@@ -8,7 +8,7 @@ ucs2_strnlen(const ucs2_char_t *s, size_ {unsigned long length =0 ; -while (*s++ !=0 && length < maxlength) +while (length < maxlength && *s++ !=0 ) length++;return length; }
Greg Kroah-Hartman
maintainerPATCH 88/552 media: cec: stm32: prevent out-of-bounds write on RX overflow
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weigang He <[email protected]>
commit fb9dda38d4b9e90db07ed9a0ee2d35bf85494035 upstream.
stm32_rx_done() appends each received CEC byte to rx_msg.msg[] using rx_msg.len as the write index, incrementing it on every RXBR (receive-byte-ready) interrupt without checking it against the buffer size:
cec->rx_msg.msg[cec->rx_msg.len++] = val & 0xFF;
rx_msg.msg[] is a fixed CEC_MAX_MSG_SIZE (16) byte array in struct cec_msg, and rx_msg.len is only reset on RXACKE/RXOVR or after a completed message (RXEND). The number of bytes received before RXEND is decided by the remote CEC device (it sets EOM), not by the driver. A peer that keeps sending bytes without ending the message drives RXBR repeatedly, pushing rx_msg.len past 16 and writing peer-controlled bytes out of bounds into the surrounding memory. This is reachable in normal operation once the driver has probed and receiving is enabled, from the IRQ thread, without any local privilege.
The length check in the CEC core runs on the consumer side, after the byte has been stored, so it does not prevent the overflow. Bound the index in the driver before the store, as the other platform CEC drivers already do (e.g. tegra_cec), dropping the excess bytes of an overlong frame.
Found by static analysis tool CodeQL.
--- drivers/media/cec/platform/stm32/stm32-cec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/media/cec/platform/stm32/stm32-cec.c +2 -1
@@ -132,7 +132,8 @@ static void stm32_rx_done(struct stm32_cu32 val;regmap_read (cec->regmap,CEC_RXDR , &val); - cec->rx_msg.msg[cec->rx_msg.len++] = val &0xFF ; +if (cec->rx_msg.len <CEC_MAX_MSG_SIZE ) + cec->rx_msg.msg[cec->rx_msg.len++] = val &0xFF ; }if (cec->irq_status &RXEND ) {
Greg Kroah-Hartman
maintainerPATCH 89/552 media: vicodec: fix out-of-bounds write in FWHT encoder
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Junrui Luo <[email protected]>
commit cf4500ebf6fb57bf4ab83c3dd349a40257dbe2a9 upstream.
vidioc_s_fmt_vid_out() sizes the encoder CAPTURE buffer from the compressed descriptor pixfmt_fwht, whose sizeimage_mult is 3:coded_w * coded_h * 3 + sizeof(struct fwht_cframe_hdr). fwht_encode_frame() encodes one plane per component, and an incompressible plane takes the FWHT_FRAME_UNENCODED path in encode_plane(), copying the plane verbatim.
For a 4-component pixel format all four planes are full resolution (width_div == height_div == 1), so a frame that forces every plane through the unencoded fallback writessizeof(struct fwht_cframe_hdr) + 4 * coded_w * coded_h bytes, overrunning the plane by coded_w * coded_h, which can result in corruption of adjacent kernel heap memory.
Bump pixfmt_fwht.sizeimage_mult from 3 to 4, matching the largest components_num among the supported raw formats, so the capture buffer is always large enough for the unencoded fallback.
--- drivers/media/test-drivers/vicodec/vicodec-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/media/test-drivers/vicodec/vicodec-core.c +2 -2
@@ -63,11 +63,11 @@ struct pixfmt_info { };static const struct v4l2_fwht_pixfmt_info pixfmt_fwht = { -V4L2_PIX_FMT_FWHT ,0 ,3 ,1 ,1 ,1 ,1 ,1 ,0 ,1 +V4L2_PIX_FMT_FWHT ,0 ,4 ,1 ,1 ,1 ,1 ,1 ,0 ,1 };static const struct v4l2_fwht_pixfmt_info pixfmt_stateless_fwht = { -V4L2_PIX_FMT_FWHT_STATELESS ,0 ,3 ,1 ,1 ,1 ,1 ,1 ,0 ,1 +V4L2_PIX_FMT_FWHT_STATELESS ,0 ,4 ,1 ,1 ,1 ,1 ,1 ,0 ,1 };static void vicodec_dev_release (struct device *dev)
Greg Kroah-Hartman
maintainerPATCH 90/552 nilfs2: fix slab-out-of-bounds in nilfs_direct_propagate after truncation
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryusuke Konishi <[email protected]>
commit 45662dedb8f272ef7f16e69f13424c4bd0399240 upstream.
Shuangpeng Bai reported that KASAN detected a slab-out-of-bounds error in nilfs_direct_propagate() during testing.
Analysis revealed that after truncating a file, a node block immediately below the B-tree root was not deleted. Instead, it remained in the B-tree node cache in a dirty state. The log writer subsequently detected this block and incorrectly invoked nilfs_direct_propagate() on it, which is designed to handle only data blocks in direct mapping.
B-tree nodes in the cache are managed by virtual block numbers, and their logical keys typically exceed the range expected by direct mapping. Consequently, processing such a node as a direct mapping entry triggers a slab-out-of-bounds access.
The root cause is that when a B-tree mapping collapses into a direct mapping during truncation, an intermediate node block pointed to by the root node is left behind as garbage instead of being explicitly deleted.
This resolves the issue by adding a nilfs_btree_discard() operation to delete the remaining intermediate node block during the conversion. A 'deform' flag is added to the bop_delete interface to explicitly signal that the deletion is part of a mapping transformation. This allows the B-tree mapping implementation to perform the necessary cleanup and discarding of the residual node structure that would be otherwise be left orphaned after the transition.
--- fs/nilfs2/bmap.c | 2 +- fs/nilfs2/bmap.h | 2 +- fs/nilfs2/btree.c | 39 ++++++++++++++++++++++++++++++++------- fs/nilfs2/direct.c | 4 ++-- 4 files changed, 36 insertions(+), 11 deletions(-)
fs/nilfs2/bmap.c +1 -1
@@ -175,7 +175,7 @@ static int nilfs_bmap_do_delete(struct nreturn ret; } -return bmap->b_ops->bop_delete (bmap, key); +return bmap->b_ops->bop_delete (bmap, key, false); }/**
fs/nilfs2/bmap.h +1 -1
@@ -63,7 +63,7 @@ struct nilfs_bmap_operations {int (*bop_lookup_contig)(const struct nilfs_bmap *,__u64 ,__u64 *,unsigned int );int (*bop_insert)(struct nilfs_bmap *,__u64 ,__u64 ); -int (*bop_delete)(struct nilfs_bmap *,__u64 ); +int (*bop_delete)(struct nilfs_bmap *bmap,__u64 key,bool deform);void (*bop_clear)(struct nilfs_bmap *);int (*bop_propagate)(struct nilfs_bmap *,struct buffer_head *);
fs/nilfs2/btree.c +32 -7
@@ -1425,6 +1425,28 @@ static void nilfs_btree_shrink(struct ni path[level].bp_bh =NULL ; } +/** +* nilfs_btree_discard - discard the last node for the mapping transformation +* @btree: bmap struct of btree +* @path: array of nilfs_btree_path struct +* @level: level of the B-tree node being operated on +* @keyp: argument for passing a key (unused) +* @ptrp: argument for passing a pointer (unused) +*/ +static void nilfs_btree_discard (struct nilfs_bmap *btree, +struct nilfs_btree_path *path,int level, +__u64 *keyp,__u64 *ptrp) +{ +struct nilfs_btree_node *root =nilfs_btree_get_root (btree); + +nilfs_btree_node_delete (root,0 ,NULL ,NULL , +NILFS_BTREE_ROOT_NCHILDREN_MAX ); +nilfs_btree_node_set_level (root, level); + +nilfs_btnode_delete (path[level].bp_bh); + path[level].bp_bh =NULL ; +} +static void nilfs_btree_nop (struct nilfs_bmap *btree,struct nilfs_btree_path *path,int level,__u64 *keyp,__u64 *ptrp)
@@ -1435,7 +1457,7 @@ static int nilfs_btree_prepare_delete(ststruct nilfs_btree_path *path, int *levelp, struct nilfs_bmap_stats *stats, - struct inode *dat) + struct inode *dat, bool deform) { struct buffer_head *bh;struct nilfs_btree_node *node, *parent, *sib;
@@ -1522,15 +1544,17 @@ static int nilfs_btree_prepare_delete(stif (nilfs_btree_node_get_nchildren (node) -1 <=NILFS_BTREE_ROOT_NCHILDREN_MAX ) { path[level].bp_op = nilfs_btree_shrink; - stats->bs_nblocks +=2 ; - level++; - path[level].bp_op = nilfs_btree_nop; - goto shrink_root_child; + }else if (deform) { + path[level].bp_op = nilfs_btree_discard; }else { path[level].bp_op = nilfs_btree_do_delete; stats->bs_nblocks++; goto out; } + stats->bs_nblocks +=2 ; + level++; + path[level].bp_op = nilfs_btree_nop; + goto shrink_root_child; } }
@@ -1581,7 +1605,7 @@ static void nilfs_btree_commit_delete(stnilfs_bmap_set_dirty (btree); } -static int nilfs_btree_delete (struct nilfs_bmap *btree,__u64 key) +static int nilfs_btree_delete (struct nilfs_bmap *btree,__u64 key,bool deform) {struct nilfs_btree_path *path;
@@ -1601,7 +1625,8 @@ static int nilfs_btree_delete(struct nil dat =NILFS_BMAP_USE_VBN (btree) ?nilfs_bmap_get_dat (btree) :NULL ; - ret =nilfs_btree_prepare_delete (btree, path, &level, &stats, dat); + ret =nilfs_btree_prepare_delete (btree, path, &level, &stats, dat, + deform);if (ret <0 ) goto out;nilfs_btree_commit_delete (btree, path, level, dat);
fs/nilfs2/direct.c +2 -2
@@ -144,7 +144,7 @@ static int nilfs_direct_insert(struct nireturn ret; } -static int nilfs_direct_delete (struct nilfs_bmap *bmap,__u64 key) +static int nilfs_direct_delete (struct nilfs_bmap *bmap,__u64 key,bool deform) {union nilfs_bmap_ptr_req req;struct inode *dat;
@@ -234,7 +234,7 @@ int nilfs_direct_delete_and_convert(stru/* no need to allocate any resource for conversion */ /* delete */ - ret = bmap->b_ops->bop_delete (bmap, key); + ret = bmap->b_ops->bop_delete (bmap, key, true);if (ret <0 )return ret;
Greg Kroah-Hartman
maintainerPATCH 91/552 of: fix out-of-bounds read in of_alias_scan() stem parser
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdurrahman Hussain <[email protected]>
commit 5bb01c657ff9fc807c2c592ca18af34c4fc3bc6f upstream.
The stem parser tests isdigit(*(end - 1)) before checking end > start and so reads one byte before the property name when the name is empty or all digits. Check the bound first.
--- drivers/of/base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/of/base.c +1 -1
@@ -1891,7 +1891,7 @@ void of_alias_scan(void * (*dt_alloc)(u6/* walk the alias backwards to extract the id and work out * the 'stem' string */ -while (isdigit (*(end-1 )) && end > start) +while (end > start &&isdigit (*(end -1 ))) end--; len = end - start;
Greg Kroah-Hartman
maintainerPATCH 92/552 PCI/sysfs: Fix out-of-bounds read in pci_write_legacy_io()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Wilczyński <[email protected]>
commit dc76258d0132df1d831a5a29758bd448ca9c566e upstream.
pci_write_legacy_io() loads 4 bytes from the kernfs write buffer regardless of how many bytes userspace wrote:
if (count != 1 && count != 2 && count != 4)
return -EINVAL;
return pci_legacy_write(bus, off, *(u32 *)buf, count);kernfs_fop_write_iter() allocates the buffer with kmalloc(len + 1), so a 1-byte write to the legacy_io sysfs file allocates 2 bytes and the unconditional u32 load reads up to 2 bytes past the end of the allocation, which KASAN reports as a slab-out-of-bounds read. Similarly, a 2-byte write overreads by 1 byte.
Thus, read only the number of bytes requested using get_unaligned_le16() and get_unaligned_le32() for the 2 and 4 byte cases, interpreting the buffer as little-endian to match the byte ordering of PCI I/O port space.
The PowerPC implementation previously compensated for the generic code's native-endian 32-bit load by shifting the value into place for the 1 and 2 byte cases. The shifts were only correct on big-endian kernels.
On little-endian PowerPC (POWER8 and later), they extracted the wrong bytes, so a 1-byte write wrote an out-of-bounds byte instead of the requested value. On big-endian, the native load also caused out_le16() and out_le32() to reverse the user's bytes on the wire for 2 and 4 byte writes. The little-endian helpers resolve both issues, so the shifts are removed.
No changes are needed for the Alpha platform.
The legacy_io file is root-only and exists only on Alpha and PowerPC, the two architectures that define HAVE_PCI_LEGACY.
--- arch/powerpc/kernel/pci-common.c | 9 ++------- drivers/pci/pci-sysfs.c | 18 +++++++++++++++--- 2 files changed, 17 insertions(+), 10 deletions(-)
arch/powerpc/kernel/pci-common.c +2 -7
@@ -626,19 +626,14 @@ int pci_legacy_write(struct pci_bus *busreturn -ENXIO ; addr = hose->io_base_virt + port; -/* WARNING: The generic code is idiotic. It gets passed a pointer -* to what can be a 1, 2 or 4 byte quantity and always reads that -* as a u32, which means that we have to correct the location of -* the data read within those 32 bits for size 1 and 2 -*/ switch (size) {case 1 : -out_8 (addr, val >>24 ); +out_8 (addr, val);return 1 ;case 2 :if (port &1 )return -EINVAL ; -out_le16 (addr, val >>16 ); +out_le16 (addr, val);return 2 ;case 4 :if (port &3 )
drivers/pci/pci-sysfs.c +15 -3
@@ -931,12 +931,24 @@ static ssize_t pci_write_legacy_io(struc char *buf, loff_t off, size_t count) {struct pci_bus *bus =to_pci_bus (kobj_to_dev (kobj)); +u32 val; -/* Only support 1, 2 or 4 byte accesses */ -if (count !=1 && count !=2 && count !=4 ) +/* Only support 1, 2 or 4 byte accesses. */ +switch (count) { +case 1 : + val = *(u8 *)buf; +break ; +case 2 : + val =get_unaligned_le16 (buf); +break ; +case 4 : + val =get_unaligned_le32 (buf); +break ; +default :return -EINVAL ; + } -return pci_legacy_write (bus, off, *(u32 *)buf, count); +return pci_legacy_write (bus, off, val, count); }/**
Greg Kroah-Hartman
maintainerPATCH 93/552 phy: rockchip-samsung-dcphy: fix out-of-range max_register
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Yang <[email protected]>
commit 4486e75ba647bd8b98fc1f053101b40caceeed4b upstream.
The PHY register block is 64KB, so with a register stride of 4 the last accessible register sits at offset 0xfffc. max_register names 0x10000, one register past the end of the mapping: dumping the registers through the regmap debugfs interface reads beyond the ioremapped region and oopses on the unmapped page. The oops fires with the regmap lock held, so later PHY operations deadlock.
--- drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c +1 -1
@@ -1525,7 +1525,7 @@ static const struct regmap_config samsun .reg_bits = 32, .val_bits = 32, .reg_stride = 4, - .max_register = 0x10000, + .max_register = 0xfffc, }; static struct phy *samsung_mipi_dcphy_xlate(struct device *dev,
Greg Kroah-Hartman
maintainerPATCH 94/552 ubifs: fix out-of-bounds read in signature length check
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ibrahim Hashimov <[email protected]>
commit 95d27c1708bb6e8823c8e7c623f9abc2a91bf4bf upstream.
ubifs_sb_verify_signature() bounds the on-disk ubifs_sig_node->len field before handing the signature payload to verify_pkcs7_signature(), but the check has the wrong sign:
if (le32_to_cpu(signode->len) > snod->len + sizeof(struct ubifs_sig_node))
The signature bytes start sizeof(struct ubifs_sig_node) (UBIFS_SIG_NODE_SZ, 64 bytes) into the node, so the payload is at most
snod->len - sizeof(struct ubifs_sig_node)
bytes long. Adding the header size instead of subtracting it accepts a declared length up to 2 * UBIFS_SIG_NODE_SZ larger than the node actually holds -- past the end of c->sbuf, which is vmalloc(c->leb_size). verify_pkcs7_signature() -> pkcs7_parse_message() -> asn1_ber_decoder() is then handed that inflated length and reads beyond the allocation while walking the DER headers. The node length comes straight from the mounted image, so a crafted signed UBIFS image reaches this via ubifs_read_superblock() before the signature is cryptographically checked.
snod->len is guaranteed to be >= UBIFS_SIG_NODE_SZ by the node scanner (c->ranges[UBIFS_SIG_NODE].min_len == UBIFS_SIG_NODE_SZ), so the corrected subtraction cannot underflow. Legitimately signed images are unaffected: a correct superblock never declares a signature longer than the node it is embedded in.
--- fs/ubifs/auth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ubifs/auth.c +1 -1
@@ -217,7 +217,7 @@ int ubifs_sb_verify_signature(struct ubi signode = snod->node; -if (le32_to_cpu (signode->len) > snod->len +sizeof (struct ubifs_sig_node )) { +if (le32_to_cpu (signode->len) > snod->len -sizeof (struct ubifs_sig_node )) {ubifs_err (c,"invalid signature len %d" ,le32_to_cpu (signode->len)); err = -EINVAL ; goto out_destroy;
Greg Kroah-Hartman
maintainerPATCH 95/552 zram: validate deflate params
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sergey Senozhatsky <[email protected]>
commit ec7607ac4717ff521c9c1e9d8271c26293345513 upstream.
We must validate user-supplied deflate winbits before we pass it to zlib_deflate_workspacesize(), which triggers BUG_ON() if winbits value is outside of valid ranges.
--- drivers/block/zram/backend_deflate.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
drivers/block/zram/backend_deflate.c +9 -1
@@ -24,8 +24,16 @@ static int deflate_setup_params(struct z {if (params->level ==ZCOMP_PARAM_NOT_SET ) params->level =Z_DEFAULT_COMPRESSION ; -if (params->deflate.winbits ==ZCOMP_PARAM_NOT_SET ) +if (params->deflate.winbits ==ZCOMP_PARAM_NOT_SET ) { params->deflate.winbits =DEFLATE_DEF_WINBITS ; + }else { +s32 wb = params->deflate.winbits; + +if ((wb <-15 || wb >-9 ) && (wb <9 || wb >15 )) { +pr_err ("invalid deflate winbits: %d\n" , wb); +return -EINVAL ; + } + }return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 96/552 zsmalloc: account for handle size in class lookup
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Longlong Xia <[email protected]>
commit f7bf5cd5b5f2b13fe2361860880c4e214c08b440 upstream.
zs_lookup_class_index() lets zram recompression decide whether a newly compressed object would use a smaller size class. It currently classifies the payload size directly, while zs_malloc() adds ZS_HANDLE_SIZE before selecting the class.
This makes lookup disagree with allocation near size-class boundaries. With 4 KiB pages, CONFIG_ZSMALLOC_CHAIN_SIZE=8, and 64-bit handles, a 1025-to-1024-byte recompression appears to move from class 64 to class 62 although both allocations use class 64. Conversely, a 1049-to-1025-byte recompression appears to stay in class 64 although the allocations move from class 65 to class 64.
As a result, zram can accept replacements with no allocation benefit or reject ones that would save memory, potentially marking the object incompressible.
Factor size-class selection into lookup_size_class(), account for the handle there, and use the helper for both lookup and allocation.
--- mm/zsmalloc.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
mm/zsmalloc.c +7 -4
@@ -508,6 +508,11 @@ static int get_size_class_index(int sizereturn min_t (int,ZS_SIZE_CLASSES -1 , idx); } +static struct size_class *lookup_size_class (struct zs_pool *pool,size_t size) +{ +return pool->size_class[get_size_class_index (size +ZS_HANDLE_SIZE )]; +} +static inline void class_stat_add (struct size_class *class,int type,unsigned long cnt) {
@@ -1052,7 +1057,7 @@ unsigned int zs_lookup_class_index(struc {struct size_class *class; - class = pool->size_class[get_size_class_index (size)]; + class =lookup_size_class (pool, size);return class->index; }
@@ -1279,9 +1284,7 @@ unsigned long zs_malloc(struct zs_pool *if (!handle)return (unsigned long )ERR_PTR (-ENOMEM ); -/* extra space in chunk to keep the handle */ - size +=ZS_HANDLE_SIZE ; - class = pool->size_class[get_size_class_index (size)]; + class =lookup_size_class (pool, size);/* class->lock effectively protects the zpage migration */ spin_lock (&class->lock);
Greg Kroah-Hartman
maintainerPATCH 97/552 NFS/localio: fix ref leak on nfs_uuid_add_file failure
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chris Mason <[email protected]>
commit ca018c19e0ba38975e5ddc3ef8117d5b734313aa upstream.
When nfs_uuid_add_file() races with nfs_uuid_put() tearing down uuid->net, it returns -ENXIO without publishing nfl->nfs_uuid via rcu_assign_pointer(). nfs_open_local_fh() then enters its error branch and only releases the slot's file ref and its paired net ref plus its own entry-time net ref, while the close path is a no-op:
nfs_close_local_fh()
nfs_uuid = rcu_dereference(nfl->nfs_uuid);
if (!nfs_uuid) { rcu_read_unlock(); return; } /* always */nfsd_open_local_fh() returns localio holding a caller-owned +1 nfsd_file reference (from nfsd_file_get() after nfsd_file_acquire_local()) and an entry-time nfsd_net reference (from its first nfsd_net_try_get()) embedded as nf->nf_net. Both are leaked on the failure path, pinning one nfsd_file (and the underlying struct file, dentry, inode) and one nfsd_net_ref per occurrence, which blocks nfsd_net and netns teardown.
Fix by releasing the caller-owned file ref and its net ref through the existing helper, using a stack-local RCU pointer so the helper can xchg it out, then returning -ENXIO so callers do not dereference a localio whose slot has been cleared:
struct nfsd_file __rcu *tmp = RCU_INITIALIZER(localio);
nfs_to_nfsd_file_put_local(pnf);
nfs_to_nfsd_file_put_local(&tmp);
localio = ERR_PTR(-ENXIO);The trailing nfs_to_nfsd_net_put(net) continues to release the outer net ref, so all three nfsd_net_try_get() increments are balanced on the error branch.
--- fs/nfs_common/nfslocalio.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
fs/nfs_common/nfslocalio.c +15 -1
@@ -292,8 +292,22 @@ struct nfsd_file *nfs_open_local_fh(nfs_ localio = nfs_to->nfsd_open_local_fh (net, uuid->dom, rpc_clnt, cred, nfs_fh, pnf, fmode);if (!IS_ERR (localio) &&nfs_uuid_add_file (uuid, nfl) <0 ) { -/* Delete the cached file when racing with nfs_uuid_put() */ +/* +* Delete the cached file when racing with nfs_uuid_put(). +* Since nfl->nfs_uuid was never published via +* rcu_assign_pointer(), nfs_close_local_fh() will early-return +* and cannot clean up after us. Drop the slot's file ref and +* its paired net ref, then drop the caller-owned nfsd_file ref +* (+1) and the entry-time nfsd_net ref carried via nf->nf_net, +* and return -ENXIO so the caller never dereferences the +* now-cleared localio. +*/ +struct nfsd_file __rcu *tmp = + (struct nfsd_file __force __rcu *)localio; +nfs_to_nfsd_file_put_local (pnf); +nfs_to_nfsd_file_put_local (&tmp); + localio =ERR_PTR (-ENXIO ); }nfs_to_nfsd_net_put (net);
Greg Kroah-Hartman
maintainerPATCH 98/552 NFS: fix delegation_hash_table leak when nfs4_server_common_setup() fails
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nate Prodromou <[email protected]>
commit 2092f5b38f88be306140c77aeeeb43fc1adacacc upstream.
nfs4_server_common_setup() allocates server->delegation_hash_table first, but server->destroy - the only path that frees the table via nfs4_destroy_server() - is not assigned until the very end of the function. If any intermediate step fails (the is_ds_only_client() check, nfs4_init_session(), nfs4_get_rootfh(), or nfs_probe_server()), the function returns with server->destroy still NULL, so the caller's nfs_free_server() skips the destroy callback and the hash table is leaked (4 KiB per attempt with the default delegation watermark).
This is trivially reachable from userspace: every failed NFSv4 mount leaks one allocation. A client that persistently retries a mount that cannot succeed leaks kernel memory without bound. Observed in production where a Longhorn backup poller retried mount.nfs4 against an NFSv3-only server roughly 10 times per second, leaking ~3.4 GiB of unreclaimable slab (kmalloc-rnd-13-4k) per day; the node accumulated 12 GiB of leaked slab before the source was identified via the kmem:kmalloc tracepoint (call_site=nfs4_delegation_hash_alloc).
Reproducer:
# server exports NFSv3 only (or export path absent for v4) while :; do mount -t nfs4 <server>:/missing /mnt; done # watch SUnreclaim in /proc/meminfo grow 4 KiB per iteration
Free the table on the error paths between the allocation and the assignment of server->destroy.
--- fs/nfs/nfs4client.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
fs/nfs/nfs4client.c +12 -5
@@ -1095,20 +1095,22 @@ static int nfs4_server_common_setup(strureturn error;/* data servers support only a subset of NFSv4.1 */ -if (is_ds_only_client (server->nfs_client)) -return -EPROTONOSUPPORT ; +if (is_ds_only_client (server->nfs_client)) { + error = -EPROTONOSUPPORT ; + goto out_free_delegation_hash; + }/* We must ensure the session is initialised first */ error =nfs4_init_session (server->nfs_client);if (error <0 ) -return error; + goto out_free_delegation_hash;nfs_server_set_init_caps (server);/* Probe the root fh to retrieve its FSID and filehandle */ error =nfs4_get_rootfh (server, mntfh, auth_probe);if (error <0 ) -return error; + goto out_free_delegation_hash; dprintk("Server FSID: %llx:%llx\n", (unsigned long long) server->fsid.major,
@@ -1117,7 +1119,7 @@ static int nfs4_server_common_setup(stru error =nfs_probe_server (server, mntfh);if (error <0 ) -return error; + goto out_free_delegation_hash;nfs4_session_limit_rwsize (server);nfs4_session_limit_xasize (server);
@@ -1129,6 +1131,11 @@ static int nfs4_server_common_setup(stru server->mount_time = jiffies; server->destroy = nfs4_destroy_server;return 0 ; + +out_free_delegation_hash: +kfree (server->delegation_hash_table); + server->delegation_hash_table =NULL ; +return error; }/*
Greg Kroah-Hartman
maintainerPATCH 99/552 NFSD: check truncate permission under inode lock
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
commit b778e0e0a16759f22a70579c3cf8d254a40d4a7f upstream.
nfsd_setattr() checks whether a size update needs NFSD_MAY_TRUNC before it takes inode_lock(). The comparison uses the file size sampled by that unlocked read, but the actual ATTR_SIZE update is applied later under inode_lock() by notify_change().
This leaves a TOCTOU window for append-only files. If a client sends a SETATTR that does not shrink the file at the time of the unlocked sample, a concurrent append can extend the file before nfsd_setattr() takes inode_lock(). notify_change() then applies a real truncation without the NFSD_MAY_TRUNC check that rejects IS_APPEND(inode). The VFS truncate syscall paths perform their own append-only checks before calling notify_change(), so NFSD must make this decision against the locked size it is about to change.
Split the write-count acquisition from the truncation permission check. Keep get_write_access() before the locked setattr work, then recheck whether the requested size is below i_size_read(inode) after inode_lock() has been acquired and before notify_change(ATTR_SIZE). This also avoids the plain unlocked inode->i_size load.
--- fs/nfsd/vfs.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-)
fs/nfsd/vfs.c +18 -12
@@ -418,21 +418,22 @@ nfsd_sanitize_attrs(struct inode *inode, }static __be32 -nfsd_get_write_access (struct svc_rqst *rqstp,struct svc_fh *fhp, -struct iattr *iap) +nfsd_may_truncate (struct svc_rqst *rqstp,struct svc_fh *fhp, +struct iattr *iap) {struct inode *inode =d_inode (fhp->fh_dentry); -if (iap->ia_size < inode->i_size) { -__be32 err; +if (iap->ia_size >=i_size_read (inode)) +return nfs_ok; - err =nfsd_permission (&rqstp->rq_cred, - fhp->fh_export, fhp->fh_dentry, -NFSD_MAY_TRUNC |NFSD_MAY_OWNER_OVERRIDE ); -if (err) -return err; - } -return nfserrno (get_write_access (inode)); +return nfsd_permission (&rqstp->rq_cred, fhp->fh_export, fhp->fh_dentry, +NFSD_MAY_TRUNC |NFSD_MAY_OWNER_OVERRIDE ); +} + +static __be32 +nfsd_get_write_access (struct svc_fh *fhp) +{ +return nfserrno (get_write_access (d_inode (fhp->fh_dentry))); }static int __nfsd_setattr (struct dentry *dentry,struct iattr *iap)
@@ -559,12 +560,17 @@ nfsd_setattr(struct svc_rqst *rqstp, str* setattr call. */ if (size_change) { - err =nfsd_get_write_access (rqstp, fhp, iap); + err =nfsd_get_write_access (fhp);if (err)return err; }inode_lock (inode); +if (size_change) { + err =nfsd_may_truncate (rqstp, fhp, iap); +if (err) + goto out_unlock; + } err =fh_fill_pre_attrs (fhp);if (err) goto out_unlock;
Greg Kroah-Hartman
maintainerPATCH 100/552 NFSD: Encode only the status in NFS-ACL v2 GETACL error replies
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
commit ed4edddad19babf76b56882ad9600f5646b167a0 upstream.
The NFSv2 ACL GETACL reply is a union that carries file attributes and ACL data only when the status is NFS_OK. All error cases are void results. However, currently the NFSv2 ACL GETACL result encoder decides whether to append the "OK" body by testing only whether the file handle resolved to a positive dentry, not the actual reply status.
A GETACL request that resolves its file handle but then fails for another reason (an unsupported mask value, a getattr failure, or an ACL retrieval error) therefore appends file attributes and ACL data after the error status on the wire. Worse, when the mask is rejected, fh_getattr() hasn't been called at all, so those attributes are serialized from a zero-filled kstat and are junk.
The logic before the xdr_stream conversion used the reply status. Revert to that approach (but keep the xdr_stream conversion in place).
--- fs/nfsd/nfs2acl.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-)
fs/nfsd/nfs2acl.c +15 -16
@@ -248,22 +248,21 @@ nfsaclsvc_encode_getaclres(struct svc_rqif (!svcxdr_encode_stat (xdr, resp->status))return false; - -if (dentry ==NULL ||d_really_is_negative (dentry)) -return true; - inode =d_inode (dentry); - -if (!svcxdr_encode_fattr (rqstp, xdr, &resp->fh, &resp->stat)) -return false; -if (xdr_stream_encode_u32 (xdr, resp->mask) <0 ) -return false; - -if (!nfs_stream_encode_acl (xdr, inode, resp->acl_access, - resp->mask &NFS_ACL ,0 )) -return false; -if (!nfs_stream_encode_acl (xdr, inode, resp->acl_default, - resp->mask &NFS_DFACL ,NFS_ACL_DEFAULT )) -return false; +switch (resp->status) { +case nfs_ok: + inode =d_inode (dentry); +if (!svcxdr_encode_fattr (rqstp, xdr, &resp->fh, &resp->stat)) +return false; +if (xdr_stream_encode_u32 (xdr, resp->mask) <0 ) +return false; +if (!nfs_stream_encode_acl (xdr, inode, resp->acl_access, + resp->mask &NFS_ACL ,0 )) +return false; +if (!nfs_stream_encode_acl (xdr, inode, resp->acl_default, + resp->mask &NFS_DFACL ,NFS_ACL_DEFAULT )) +return false; +break ; + }return true; }
Greg Kroah-Hartman
maintainerPATCH 101/552 NFSD: Fix off-by-one in DRC bucket pruning limit
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
commit d0728723c80dcb3432effd67c7e919b596004b1d upstream.
nfsd_prune_bucket_locked() evicts an entry before checking the freed count against @max. The check uses "++freed > max", which does not break until freed exceeds max, resulting in max + 1 evictions. Use ">=" so the limit stated in the function comment is honored.
--- fs/nfsd/nfscache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nfsd/nfscache.c +1 -1
@@ -275,7 +275,7 @@ nfsd_prune_bucket_locked(struct nfsd_netnfsd_cacherep_unlink_locked (nn, b, rp);list_add (&rp->c_lru, dispose); -if (max && ++freed > max) +if (max && ++freed >= max)break ; } }
Greg Kroah-Hartman
maintainerPATCH 102/552 NFSD: restart ssc_expire_umount walk after dropping nfsd_ssc_lock
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit 036c1b182f4da65363e79ec0ac276edc6b7296e5 upstream.
nfsd4_ssc_expire_umount() walks nn->nfsd_ssc_mount_list with list_for_each_entry_safe(ni, tmp, ...). For each expired entry it sets nsui_busy = true, drops nfsd_ssc_lock to run mntput() on the source vfsmount, then reacquires the lock to list_del + kfree the entry and continue iterating via the macro's saved tmp pointer.
The nsui_busy flag protects the current ni from concurrent nfsd4_ssc_setup_dul() finders during the lock-drop window, but it does not pin tmp. Another nfsd RPC thread that fails its source- server mount and reaches nfsd4_ssc_cancel_dul() will, during that same window, take nfsd_ssc_lock, list_del + kfree its own ssc_umount item, and release the lock. If that item is the saved tmp of the expire walk, the next iteration dereferences a freed nfsd4_ssc_umount_item.
Restart the walk from the head after the mntput() unlock window so no saved next pointer survives the lock-drop. The list is bounded by the number of active inter-server source mounts (typically small) and the expire delayed-work runs periodically rather than per-IO, so the restart is cheap.
--- fs/nfsd/nfs4state.c | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-)
fs/nfsd/nfs4state.c +25 -19
@@ -6738,30 +6738,36 @@ static void nfsd4_ssc_shutdown_umount(ststatic void nfsd4_ssc_expire_umount (struct nfsd_net *nn) {bool do_wakeup = false; -struct nfsd4_ssc_umount_item *ni =NULL ; -struct nfsd4_ssc_umount_item *tmp; +struct nfsd4_ssc_umount_item *ni; +restart:spin_lock (&nn->nfsd_ssc_lock); -list_for_each_entry_safe (ni, tmp, &nn->nfsd_ssc_mount_list, nsui_list) { -if (time_after (jiffies, ni->nsui_expire)) { -if (refcount_read (&ni->nsui_refcnt) >1 ) -continue ; +list_for_each_entry (ni, &nn->nfsd_ssc_mount_list, nsui_list) { +if (!time_after (jiffies, ni->nsui_expire)) +break ; +if (refcount_read (&ni->nsui_refcnt) >1 ) +continue ; -/* mark being unmount */ - ni->nsui_busy = true; -spin_unlock (&nn->nfsd_ssc_lock); -mntput (ni->nsui_vfsmount); -spin_lock (&nn->nfsd_ssc_lock); +/* Prevent concurrent setup during unmount */ + ni->nsui_busy = true; +spin_unlock (&nn->nfsd_ssc_lock); +mntput (ni->nsui_vfsmount); +spin_lock (&nn->nfsd_ssc_lock); -/* waiters need to start from begin of list */ -list_del (&ni->nsui_list); -kfree (ni); +/* Force concurrent scanners to restart */ +list_del (&ni->nsui_list); +kfree (ni); -/* wakeup ssc_connect waiters */ - do_wakeup = true; -continue ; - } -break ; +/* wakeup ssc_connect waiters */ + do_wakeup = true; +/* +* Concurrent nfsd4_ssc_cancel_dul() can free any item +* on the list under nfsd_ssc_lock while mntput() runs +* above. Restart from the head; the list is short and +* the expire worker is periodic, so this is cheap. +*/ +spin_unlock (&nn->nfsd_ssc_lock); + goto restart; }if (do_wakeup)wake_up_all (&nn->nfsd_ssc_waitq);
Greg Kroah-Hartman
maintainerPATCH 103/552 NFSD: remove flawed WARN_ON_ONCE from nfsd_mode_check
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mike Snitzer <[email protected]>
commit aa0cf48a448c5a9fe1a1e880899ecd589ce39e6e upstream.
The header for commit e75b23f9e323 ("nfsd: check d_can_lookup in fh_verify of directories") details the assumption that justified adding the WARN_ON_ONCE to nfsd_mode_check(), that assumption is invalid (in the case of NFS reexport).
When NFSD exports an NFS filesystem it is very possible for nfsd_mode_check() to encounter a @dentry that doesn't have i_op->lookup (see nfs_fhget()'s NFS_ATTR_FATTR_MOUNTPOINT and NFS_ATTR_FATTR_V4_REFERRAL handling, and d_flags_for_inode()).
So remove nfsd_mode_check()'s WARN_ON_ONCE(). The nfserr_notdir return on that branch must stay. It guards the subsequent lookup_one_unlocked() -> __lookup_slow() path, which calls inode->i_op->lookup() with no NULL check, so returning nfserr_notdir is what keeps a client LOOKUP into such a @dentry from dereferencing a NULL method pointer.
--- fs/nfsd/nfsfh.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
fs/nfsd/nfsfh.c +1 -3
@@ -69,10 +69,8 @@ nfsd_mode_check(struct dentry *dentry, uif (requested ==0 )/* the caller doesn't care */ return nfs_ok;if (mode == requested) { -if (mode ==S_IFDIR && !d_can_lookup (dentry)) { -WARN_ON_ONCE (1 ); +if (mode ==S_IFDIR && !d_can_lookup (dentry))return nfserr_notdir; - }return nfs_ok; }if (mode ==S_IFLNK ) {
Greg Kroah-Hartman
maintainerPATCH 104/552 nfsd: guard nfsd_serv deref in nfsd_file_net_dispose
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chris Mason <[email protected]>
commit 9f1ddfc8cb9076592401a611eb3a44d36186d014 upstream.
nfsd_file_net_dispose() is the consumer side of l->freeme: the nfsd service thread loop calls it to drain entries that the filecache garbage collector and shrinker append via nfsd_file_dispose_list_delayed(). During per-net teardown, nn->nfsd_serv is cleared before the filecache laundrette is shut down, so the service thread can still run a dispose pass that finds more than eight entries on l->freeme and dereferences a NULL svc_serv:
nfsd service thread loop
nfsd_file_net_dispose(nn)
if (!list_empty(&l->freeme)) {
...
svc_wake_up(nn->nfsd_serv); /* nn->nfsd_serv == NULL */
}The sibling helper nfsd_file_dispose_list_delayed() already documents this ordering and caches nn->nfsd_serv into a local before testing it for NULL. nfsd_file_net_dispose() was introduced with the same raw svc_wake_up(nn->nfsd_serv) call and never picked up the guard.
Fix by loading nn->nfsd_serv into a local svc_serv pointer and only calling svc_wake_up() when it is non-NULL, matching the pattern in nfsd_file_dispose_list_delayed().
--- fs/nfsd/filecache.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
fs/nfsd/filecache.c +12 -3
@@ -471,11 +471,20 @@ void nfsd_file_net_dispose(struct nfsd_nfor (i =0 ; i <8 && !list_empty (&l->freeme); i++)list_move (l->freeme.next, &dispose);spin_unlock (&l->lock); -if (!list_empty (&l->freeme)) -/* Wake up another thread to share the work +if (!list_empty (&l->freeme)) { +/* +* Wake up another thread to share the work * *before* doing any actual disposing. +* +* The filecache laundrette is shut down after +* the nn->nfsd_serv pointer is cleared, but +* before the svc_serv is freed. */ -svc_wake_up (nn->nfsd_serv); +struct svc_serv *serv = nn->nfsd_serv; + +if (serv) +svc_wake_up (serv); + }nfsd_file_dispose_list (&dispose); } }
Greg Kroah-Hartman
maintainerPATCH 105/552 NFSv4.1: fix layout segment leak on the pnfs_layout_process() forget path
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Junrui Luo <[email protected]>
commit ee5a386cfe60f3f8286de16a9db8e1a08f0bc124 upstream.
When the server returns a new layout stateid while a valid one is still held, pnfs_layout_process() calls pnfs_mark_matching_lsegs_return() on the on-stack free_me list and jumps to out_forget. Segments whose reference count drops to zero are unlinked from lo->plh_segs and moved to free_me by mark_lseg_invalid(); for an idle cached segment the layout header holds the only reference, so this happens on the first decrement.
out_forget never drains free_me -- only the success path calls pnfs_free_lseg_list().
Commit 814b84971388 ("pNFS/NFSv4: Fix a layout segment leak in pnfs_layout_process()") added the drain; commit 08bd8dbe8882 ("pNFS/NFSv4: Try to return invalid layout in pnfs_layout_process()") removed it while switching the destination to lo->plh_return_segs, which is drained elsewhere. Commit fb700ef02676 ("NFSv4.1: Simplify layout return in pnfs_layout_process()") switched the destination back to free_me without restoring the drain.
Restore the pnfs_free_lseg_list() call.
--- fs/nfs/pnfs.c | 1 + 1 file changed, 1 insertion(+)
fs/nfs/pnfs.c +1 -0
@@ -2631,6 +2631,7 @@ out_forget:spin_unlock (&ino->i_lock); lseg->pls_layout = lo;NFS_SERVER (ino)->pnfs_curr_ld->free_lseg (lseg); +pnfs_free_lseg_list (&free_me);return ERR_PTR (-EAGAIN ); }
Greg Kroah-Hartman
maintainerPATCH 106/552 pNFS: Fix EBUSY check in pnfs_layout_need_return
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tim Menninger <[email protected]>
commit 20358201777496fd0bb7b4336fcb4d3fc13cad28 upstream.
Commit 41d0a8ead9720 ("NFSv4/pnfs: Add support for the PNFS_LAYOUT_FILE_BULK_RETURN flag") replaced pnfs_layout_segments_returnable() in pnfs_layout_need_return() with a direct call to pnfs_mark_layout_stateid_return().
The old helper checked the return value against -EBUSY, but the replacement compares against EBUSY. Since pnfs_mark_layout_stateid_return() returns negative errno values, the -EBUSY case is never detected.
Fix the comparison in pnfs_layout_need_return() to check against -EBUSY.
--- fs/nfs/pnfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nfs/pnfs.c +1 -1
@@ -1389,7 +1389,7 @@ pnfs_layout_need_return(struct pnfs_layoreturn false;return pnfs_mark_layout_stateid_return (lo, &lo->plh_return_segs, lo->plh_return_iomode, - lo->plh_return_seq) !=EBUSY ; + lo->plh_return_seq) != -EBUSY ; }static void pnfs_layoutreturn_before_put_layout_hdr (struct pnfs_layout_hdr *lo)
Greg Kroah-Hartman
maintainerPATCH 107/552 nfsd: RCU-protect cl_cb_session to fix use-after-free on session teardown
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Layton <[email protected]>
commit 01c5d5f58a5db9b0ee5afba2e49d3157788687b2 upstream.
After a DESTROY_SESSION the per-session teardown path can free a session while rpciod still holds an inflight callback rpc_task that dereferences clp->cl_cb_session. nfsd4_probe_callback_sync() flushes cl_callback_wq, but once nfsd4_run_cb_work() has called rpc_call_async() the rpc_task lives on rpciod; flushing the workqueue does not wait for it. rpc_shutdown_client() does drain rpciod tasks, but uses a 1-second wait_event_timeout — tasks stuck in rpc_delay() (e.g. 2-second NFS4ERR_DELAY retries) can outlive the drain.
destroy path rpciod
------------ ------
unhash_session(ses)
nfsd4_probe_callback_sync(clp)
flush_workqueue(cl_callback_wq)
/* returns; rpc_task still live */
nfsd4_put_session_locked(ses)
free_session(ses) -> kfree(ses)
nfsd4_cb_sequence_done()
reads cb_clp->cl_cb_session
/* freed slab */A second window exists in nfsd4_process_cb_update(). When __nfsd4_find_backchannel() returns NULL because unhash_session() has already removed the destroyed session from cl_sessions, setup_callback_client() takes the v4.1 early return so clp->cl_cb_session = ses never fires and the field retains a pointer to the about-to-be-freed session.
Fix both by converting cl_cb_session to an RCU-protected pointer:
- Move the cl_cb_session = ses assignment in setup_callback_client() to after rpc_create() succeeds, so it is only published when a working backchannel exists. Clear cl_cb_session on the error return in nfsd4_process_cb_update(). Both stores use rcu_assign_pointer().
- Annotate cl_cb_session with __rcu. All rpciod-side readers use rcu_read_lock()/rcu_dereference() and check for NULL, bailing to the appropriate error or requeue path:
encode_cb_sequence4args(), decode_cb_sequence4resok(), nfsd41_cb_get_slot(), nfsd41_cb_release_slot(), nfsd4_cb_prepare(), and nfsd4_cb_sequence_done().
- Switch __free_session() from kfree() to kfree_rcu() so the session slab is not reclaimed until after an RCU grace period, guaranteeing that rpciod readers inside rcu_read_lock() never dereference freed memory.
- Pass the session pointer to the nfsd_cb_seq_status and nfsd_cb_free_slot tracepoints instead of having them re-read cl_cb_session.
- nfsd4_cb_prepare() calls rpc_exit() when the session is NULL, routing through the done/release path to requeue the callback.
--- fs/nfsd/nfs4callback.c | 109 ++++++++++++++++++++++++++++++++++++++++--------- fs/nfsd/nfs4state.c | 4 - fs/nfsd/state.h | 3 - fs/nfsd/trace.h | 14 ++---- 4 files changed, 100 insertions(+), 30 deletions(-)
fs/nfsd/nfs4callback.c +90 -19
@@ -456,13 +456,20 @@ static void encode_cb_sequence4args(struconst struct nfsd4_callback *cb, struct nfs4_cb_compound_hdr *hdr) { - struct nfsd4_session *session = cb->cb_clp->cl_cb_session; + struct nfsd4_session *session;struct nfsd4_referring_call_list *rcl;__be32 *p;if (hdr->minorversion ==0 )return ; +rcu_read_lock (); + session =rcu_dereference (cb->cb_clp->cl_cb_session); +if (!session) { +rcu_read_unlock (); +return ; + } +encode_nfs_cb_opnum4 (xdr,OP_CB_SEQUENCE );encode_sessionid4 (xdr, session);
@@ -478,6 +485,7 @@ static void encode_cb_sequence4args(struencode_referring_call_list4 (xdr, rcl); hdr->nops++; +rcu_read_unlock (); }static void update_cb_slot_table (struct nfsd4_session *ses,u32 target)
@@ -529,21 +537,32 @@ static void update_cb_slot_table(structstatic int decode_cb_sequence4resok (struct xdr_stream *xdr,struct nfsd4_callback *cb) { -struct nfsd4_session *session = cb->cb_clp->cl_cb_session; +struct nfsd4_session *session;int status = -ESERVERFAULT ;__be32 *p;u32 seqid, slotid, target; +rcu_read_lock (); + session =rcu_dereference (cb->cb_clp->cl_cb_session); +if (!session) { +rcu_read_unlock (); + cb->cb_seq_status = -NFS4ERR_BADSESSION ; +return -NFS4ERR_BADSESSION ; + } +/* * If the server returns different values for sessionID, slotID or * sequence number, the server is looney tunes. */ p =xdr_inline_decode (xdr,NFS4_MAX_SESSIONID_LEN +4 +4 +4 +4 ); -if (unlikely (p ==NULL )) +if (unlikely (p ==NULL )) { +rcu_read_unlock (); goto out_overflow; + }if (memcmp (p, session->se_sessionid.data,NFS4_MAX_SESSIONID_LEN )) {dprintk ("NFS: %s Invalid session id\n" , __func__); +rcu_read_unlock (); goto out; } p +=XDR_QUADLEN (NFS4_MAX_SESSIONID_LEN );
@@ -551,12 +570,14 @@ static int decode_cb_sequence4resok(stru seqid =be32_to_cpup (p++);if (seqid != session->se_cb_seq_nr[cb->cb_held_slot]) {dprintk ("NFS: %s Invalid sequence number\n" , __func__); +rcu_read_unlock (); goto out; } slotid =be32_to_cpup (p++);if (slotid != cb->cb_held_slot) {dprintk ("NFS: %s Invalid slotid\n" , __func__); +rcu_read_unlock (); goto out; }
@@ -564,6 +585,7 @@ static int decode_cb_sequence4resok(stru target =be32_to_cpup (p++);update_cb_slot_table (session, target); +rcu_read_unlock (); status =0 ; out: cb->cb_seq_status = status;
@@ -1174,9 +1196,8 @@ static int setup_callback_client(struct }else {if (!conn->cb_xprt || !ses)return -EINVAL ; - clp->cl_cb_session = ses; args.bc_xprt = conn->cb_xprt; - args.prognumber = clp->cl_cb_session->se_cb_prog; + args.prognumber = ses->se_cb_prog; args.protocol = conn->cb_xprt->xpt_class->xcl_ident |XPRT_TRANSPORT_BC ; args.authflavor = ses->se_cb_sec.flavor;
@@ -1194,8 +1215,10 @@ static int setup_callback_client(structreturn -ENOMEM ; } -if (clp->cl_minorversion !=0 ) +if (clp->cl_minorversion !=0 ) { clp->cl_cb_conn.cb_xprt = conn->cb_xprt; +rcu_assign_pointer (clp->cl_cb_session, ses); + } clp->cl_cb_client = client; clp->cl_cb_cred = cred;rcu_read_lock ();
@@ -1302,18 +1325,33 @@ static int grab_slot(struct nfsd4_sessiostatic bool nfsd41_cb_get_slot (struct nfsd4_callback *cb,struct rpc_task *task) {struct nfs4_client *clp = cb->cb_clp; -struct nfsd4_session *ses = clp->cl_cb_session; +struct nfsd4_session *ses;if (cb->cb_held_slot >=0 )return true; + +rcu_read_lock (); + ses =rcu_dereference (clp->cl_cb_session); +if (!ses) { +rcu_read_unlock (); +rpc_sleep_on (&clp->cl_cb_waitq, task,NULL ); +return false; + } cb->cb_held_slot =grab_slot (ses);if (cb->cb_held_slot <0 ) { +rcu_read_unlock ();rpc_sleep_on (&clp->cl_cb_waitq, task,NULL );/* Race breaker */ - cb->cb_held_slot =grab_slot (ses); +rcu_read_lock (); + ses =rcu_dereference (clp->cl_cb_session); +if (ses) + cb->cb_held_slot =grab_slot (ses); +rcu_read_unlock ();if (cb->cb_held_slot <0 )return false;rpc_wake_up_queued_task (&clp->cl_cb_waitq, task); + }else { +rcu_read_unlock (); }return true; }
@@ -1321,12 +1359,17 @@ static bool nfsd41_cb_get_slot(struct nfstatic void nfsd41_cb_release_slot (struct nfsd4_callback *cb) {struct nfs4_client *clp = cb->cb_clp; -struct nfsd4_session *ses = clp->cl_cb_session; +struct nfsd4_session *ses;if (cb->cb_held_slot >=0 ) { -spin_lock (&ses->se_lock); - ses->se_cb_slot_avail |=BIT (cb->cb_held_slot); -spin_unlock (&ses->se_lock); +rcu_read_lock (); + ses =rcu_dereference (clp->cl_cb_session); +if (ses) { +spin_lock (&ses->se_lock); + ses->se_cb_slot_avail |=BIT (cb->cb_held_slot); +spin_unlock (&ses->se_lock); + } +rcu_read_unlock (); cb->cb_held_slot =-1 ;rpc_wake_up_next (&clp->cl_cb_waitq); }
@@ -1458,22 +1501,35 @@ static void nfsd4_cb_prepare(struct rpc_trace_nfsd_cb_rpc_prepare (clp); cb->cb_seq_status =1 ; cb->cb_status =0 ; -if (minorversion && !nfsd41_cb_get_slot (cb, task)) -return ; +if (minorversion) { +if (!rcu_access_pointer (clp->cl_cb_session)) { +rpc_exit (task, -EIO ); +return ; + } +if (!nfsd41_cb_get_slot (cb, task)) +return ; + }rpc_call_start (task); }/* Returns true if CB_COMPOUND processing should continue */ static bool nfsd4_cb_sequence_done (struct rpc_task *task,struct nfsd4_callback *cb) { -struct nfsd4_session *session = cb->cb_clp->cl_cb_session; +struct nfsd4_session *session;bool ret = false;if (cb->cb_held_slot <0 ) goto requeue; +rcu_read_lock (); + session =rcu_dereference (cb->cb_clp->cl_cb_session); +if (!session) { +rcu_read_unlock (); + goto requeue; + } +/* This is the operation status code for CB_SEQUENCE */ -trace_nfsd_cb_seq_status (task, cb); +trace_nfsd_cb_seq_status (task, cb, session);switch (cb->cb_seq_status) {case 0 :/*
@@ -1505,12 +1561,16 @@ static bool nfsd4_cb_sequence_done(struc fallthrough;case -NFS4ERR_BADSESSION :nfsd4_mark_cb_fault (cb->cb_clp); +rcu_read_unlock (); goto requeue;case -NFS4ERR_DELAY : cb->cb_seq_status =1 ; -if (RPC_SIGNALLED (task) || !rpc_restart_call (task)) +if (RPC_SIGNALLED (task) || !rpc_restart_call (task)) { +rcu_read_unlock (); goto requeue; + }rpc_delay (task,2 *HZ ); +rcu_read_unlock ();return false;case -NFS4ERR_SEQ_MISORDERED :case -NFS4ERR_BADSLOT :
@@ -1522,11 +1582,13 @@ static bool nfsd4_cb_sequence_done(struc*/ nfsd4_mark_cb_fault (cb->cb_clp); cb->cb_held_slot =-1 ; +rcu_read_unlock (); goto retry_nowait;default :nfsd4_mark_cb_fault (cb->cb_clp); } -trace_nfsd_cb_free_slot (task, cb); +trace_nfsd_cb_free_slot (task, cb, session); +rcu_read_unlock ();nfsd41_cb_release_slot (cb);return ret; retry_nowait:
@@ -1648,7 +1710,15 @@ static struct nfsd4_conn * __nfsd4_find_* Note there isn't a lot of locking in this code; instead we depend on * the fact that it is run from clp->cl_callback_wq, which won't run two * work items at once. So, for example, clp->cl_callback_wq handles all -* access of cl_cb_client and all calls to rpc_create or rpc_shutdown_client. +* access of cl_cb_client, and all calls to rpc_create or +* rpc_shutdown_client. +* +* cl_cb_session is written only from cl_callback_wq (via +* rcu_assign_pointer) and read from rpciod under rcu_read_lock (via +* rcu_dereference) by encode_cb_sequence4args(), decode_cb_sequence4resok(), +* nfsd4_cb_sequence_done(), and the cb-slot helpers. Sessions are freed +* with kfree_rcu() so that rpciod readers in an RCU read-side critical +* section never dereference a freed session. */ static void nfsd4_process_cb_update (struct nfsd4_callback *cb) {
@@ -1700,6 +1770,7 @@ static void nfsd4_process_cb_update(strunfsd4_mark_cb_down (clp);if (c)svc_xprt_put (c->cn_xprt); +rcu_assign_pointer (clp->cl_cb_session, ses);return ; } }
fs/nfsd/nfs4state.c +2 -2
@@ -2185,7 +2185,7 @@ static void __free_session(struct nfsd4_ {free_session_slots (ses,0 );xa_destroy (&ses->se_slots); -kfree (ses); +kfree_rcu (ses, rcu_head); }static void free_session (struct nfsd4_session *ses)
@@ -3292,7 +3292,7 @@ static struct nfs4_client *create_client clp->cl_time =ktime_get_boottime_seconds ();copy_verf (clp, verf);memcpy (&clp->cl_addr, sa,sizeof (struct sockaddr_storage )); - clp->cl_cb_session =NULL ; +RCU_INIT_POINTER (clp->cl_cb_session,NULL ); clp->net = net; clp->cl_nfsd_dentry = nfsd_client_mkdir( nn, &clp->cl_nfsdfs,
fs/nfsd/state.h +2 -1
@@ -383,6 +383,7 @@ struct nfsd4_session {u16 se_slot_gen;bool se_dead;u32 se_target_maxslots; +struct rcu_head rcu_head; };/* formatted contents of nfs4_sessionid */
@@ -494,7 +495,7 @@ struct nfs4_client {#define NFSD4_CB_FAULT 3int cl_cb_state;struct nfsd4_callback cl_cb_null; -struct nfsd4_session *cl_cb_session; +struct nfsd4_session __rcu *cl_cb_session;/* for all client information that callback code might need: */ spinlock_t cl_lock;
fs/nfsd/trace.h +6 -8
@@ -1688,9 +1688,10 @@ DEFINE_NFSD_CB_LIFETIME_EVENT(bc_shutdow TRACE_EVENT(nfsd_cb_seq_status, TP_PROTO( const struct rpc_task *task, - const struct nfsd4_callback *cb + const struct nfsd4_callback *cb, + const struct nfsd4_session *session ), - TP_ARGS(task, cb), + TP_ARGS(task, cb, session), TP_STRUCT__entry( __field(unsigned int, task_id) __field(unsigned int, client_id)
@@ -1702,8 +1703,6 @@ TRACE_EVENT(nfsd_cb_seq_status,__field (int, seq_status) ),TP_fast_assign ( - const struct nfs4_client *clp = cb->cb_clp; -const struct nfsd4_session *session = clp->cl_cb_session; const struct nfsd4_sessionid *sid = (struct nfsd4_sessionid *)&session->se_sessionid;
@@ -1729,9 +1728,10 @@ TRACE_EVENT(nfsd_cb_seq_status, TRACE_EVENT(nfsd_cb_free_slot, TP_PROTO( const struct rpc_task *task, - const struct nfsd4_callback *cb + const struct nfsd4_callback *cb, + const struct nfsd4_session *session ), - TP_ARGS(task, cb), + TP_ARGS(task, cb, session), TP_STRUCT__entry( __field(unsigned int, task_id) __field(unsigned int, client_id)
@@ -1742,8 +1742,6 @@ TRACE_EVENT(nfsd_cb_free_slot,__field (u32, slot_seqno) ),TP_fast_assign ( - const struct nfs4_client *clp = cb->cb_clp; -const struct nfsd4_session *session = clp->cl_cb_session; const struct nfsd4_sessionid *sid = (struct nfsd4_sessionid *)&session->se_sessionid;
Greg Kroah-Hartman
maintainerPATCH 108/552 nfsd: release path refs on follow_down() error
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chris Mason <[email protected]>
commit 6cba08dc1922140d260cfeb30bbda4ee1bf869d8 upstream.
nfsd_cross_mnt() initializes a local struct path with mntget() and dget() before calling follow_down(). On a negative return the error arm jumps to out without releasing those references:
err = follow_down(&path, follow_flags);
if (err < 0)
goto out;follow_down() never drops the caller's entry-time refs on any error sub-case; for example a pre-cross d_manage() failure leaves path untouched, so the mntget()/dget() taken on entry survive the call.
Every other early-exit arm in nfsd_cross_mnt() (other-namespace return, IS_ERR(exp2), and the success tail after the swap) already calls path_put(&path); the err < 0 arm is the lone omission. The leak inflates mnt_count and d_count on each failed cross-mount, blocking umount and pinning dentries against the shrinker, and is reachable by any authenticated NFS client through nfsd_lookup_dentry or the NFSv4 READDIR encode path.
Fix by calling path_put(&path) before the goto out in the err < 0 arm so the entry-time refs are released on all follow_down() error returns.
--- fs/nfsd/vfs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
fs/nfsd/vfs.c +3 -1
@@ -136,8 +136,10 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, s follow_flags =LOOKUP_AUTOMOUNT ; err =follow_down (&path, follow_flags); -if (err <0 ) +if (err <0 ) { +path_put (&path); goto out; + }if (path.mnt == exp->ex_path.mnt && path.dentry == dentry &&nfsd_mountpoint (dentry, exp) ==2 ) {/* This is only a mountpoint in some other namespace */
Greg Kroah-Hartman
maintainerPATCH 109/552 nfsd: Reset write verifier when async COPY writeback fails
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
commit f5cb2276954cb80987a93ef9f9dfbfdbfc0f10b9 upstream.
Async COPY captures nn->writeverf at request time and reports it to the client via CB_OFFLOAD after the worker kthread completes. When the post-copy vfs_fsync_range() or filemap_check_wb_err() in _nfsd_copy_file_range() reports an error, the worker correctly leaves NFSD4_COPY_F_COMMITTED clear so that CB_OFFLOAD encodes wr_stable_how as NFS_UNSTABLE, but the server's write verifier is not rotated.
A client that receives NFS_UNSTABLE in CB_OFFLOAD follows up with COMMIT to make the copied data durable. With the verifier unchanged, COMMIT returns the same value the client just received via CB_OFFLOAD, and the client concludes the copy is durable -- silently dropping the data whose writeback in fact failed. This violates the UNSTABLE+COMMIT durability contract (RFC 7862 section 15.1, RFC 8881 section 18.32) and matches the bug just fixed in nfsd_vfs_write() and nfsd_commit().
Rotate nn->writeverf at the writeback-failure site. The async COPY worker has no svc_rqst, so commit_reset_write_verifier() is not available here; calling nfsd_reset_write_verifier() directly mirrors the trace-less reset already used by nfsd_file_check_write_error() for the same purpose. Filter out -EAGAIN and -ESTALE, matching commit_reset_write_verifier(), since neither indicates a durable-storage failure.
--- fs/nfsd/nfs4proc.c | 2 ++ 1 file changed, 2 insertions(+)
fs/nfsd/nfs4proc.c +2 -0
@@ -1827,6 +1827,8 @@ static ssize_t _nfsd_copy_file_range(str status =filemap_check_wb_err (dst->f_mapping, since);if (!status)set_bit (NFSD4_COPY_F_COMMITTED , ©->cp_flags); +else if (status != -EAGAIN && status != -ESTALE ) +nfsd_reset_write_verifier (copy->cp_nn); }return bytes_copied; }
Greg Kroah-Hartman
maintainerPATCH 110/552 nfsd: return NFS4ERR_NOTSUPP for unsupported netloc4 types
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Layton <[email protected]>
commit 45b06a75086f331f52cbb81223a59421d43f8809 upstream.
nfsd4_decode_nl4_server() handled only NL4_NETADDR and returned nfserr_bad_xdr for NL4_NAME and NL4_URL. Those forms are well-formed XDR, so BADXDR is misleading -- the request is unsupported, not malformed.
Decode and discard the utf8str_cis for NL4_NAME and NL4_URL to keep the stream consistent, and return nfserr_notsupp. nfsd4_proc_compound() honors a decode-time op->status, so the op fails without executing.
--- fs/nfsd/nfs4xdr.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
fs/nfsd/nfs4xdr.c +13 -0
@@ -1969,6 +1969,7 @@ static __be32 nfsd4_decode_nl4_server(st {struct nfs42_netaddr *naddr;__be32 *p; +u32 str_len;if (xdr_stream_decode_u32 (argp->xdr, &ns->nl4_type) <0 )return nfserr_bad_xdr;
@@ -1998,6 +1999,18 @@ static __be32 nfsd4_decode_nl4_server(streturn nfserr_bad_xdr;memcpy (naddr->addr, p, naddr->addr_len);break ; +case NL4_NAME : +case NL4_URL : +/* +* Well-formed XDR, but only NL4_NETADDR is supported. Consume +* the utf8str_cis to keep the stream aligned, then return +* NFS4ERR_NOTSUPP rather than the misleading NFS4ERR_BADXDR. +*/ +if (xdr_stream_decode_u32 (argp->xdr, &str_len) <0 ) +return nfserr_bad_xdr; +if (!xdr_inline_decode (argp->xdr, str_len)) +return nfserr_bad_xdr; +return nfserr_notsupp;default :return nfserr_bad_xdr; }
Greg Kroah-Hartman
maintainerPATCH 111/552 nfsd: sample writeback error cursor before async COPY loop
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
commit 20a67a7d18221af736f124770c2c5e859b479046 upstream.
_nfsd_copy_file_range() samples dst->f_wb_err into "since" after the copy loop, then uses it to detect writeback errors via filemap_check_wb_err() once vfs_fsync_range() returns. Because the nfsd_file cache reuses a single struct file across requests targeting the same inode, a concurrent COMMIT or stable WRITE on dst advances dst->f_wb_err to the current mapping->wb_err via file_check_and_advance_wb_err() during its own vfs_fsync_range(). If that advancement lands between the writeback error appearing in mapping->wb_err and the COPY worker sampling "since", the worker captures the already-advanced cursor, errseq_check() sees cur == since and returns zero, and NFSD4_COPY_F_COMMITTED is set even though writeback failed. CB_OFFLOAD then encodes wr_stable_how = FILE_SYNC4, the client treats the copied data as durable, and the failure becomes silent data loss.
Sample since once at the start of the function. The cursor then reflects state in effect before this COPY issues any writes, and filemap_check_wb_err() detects any error that occurs during the copy regardless of which thread first observes it. This matches the pattern used by nfsd_vfs_write() and nfsd4_clone_file_range().
--- fs/nfsd/nfs4proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nfsd/nfs4proc.c +1 -1
@@ -1805,6 +1805,7 @@ static ssize_t _nfsd_copy_file_range(str/* See RFC 7862 p.67: */ if (bytes_total ==0 ) bytes_total =ULLONG_MAX ; + since =READ_ONCE (dst->f_wb_err); do { /* Only async copies can be stopped here */ if (kthread_should_stop())
@@ -1820,7 +1821,6 @@ static ssize_t _nfsd_copy_file_range(str }while (bytes_total >0 &&nfsd4_copy_is_async (copy));/* for a non-zero asynchronous copy do a commit of data */ if (nfsd4_copy_is_async (copy) && copy->cp_res.wr_bytes_written >0 ) { - since =READ_ONCE (dst->f_wb_err); end = copy->cp_dst_pos + copy->cp_res.wr_bytes_written -1 ; status =vfs_fsync_range (dst, copy->cp_dst_pos, end,0 );if (!status)
Greg Kroah-Hartman
maintainerPATCH 112/552 nfsd: set SC_STATUS_FREED in nfsd4_drop_revoked_stid for delegations
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhenghang Xiao <[email protected]>
commit 650d370cfbc66a96dd14d517bd704689b5bda4e5 upstream.
nfsd4_drop_revoked_stid() handles FREE_STATEID for admin-revoked delegations but does not set SC_STATUS_FREED before releasing cl_lock. revoke_delegation() uses this flag to detect whether FREE_STATEID has already processed the delegation -- without it, the freed delegation is added to cl_revoked via list_add(), producing a use-after-free when cl_revoked is later traversed in __destroy_client().
The SC_STATUS_REVOKED path in nfsd4_free_stateid() (line 7983) already sets SC_STATUS_FREED correctly. Apply the same pattern to the SC_STATUS_ADMIN_REVOKED path in nfsd4_drop_revoked_stid().
--- fs/nfsd/nfs4state.c | 1 + 1 file changed, 1 insertion(+)
fs/nfsd/nfs4state.c +1 -0
@@ -5072,6 +5072,7 @@ static void nfsd4_drop_revoked_stid(strucase SC_TYPE_DELEG : dp =delegstateid (s);list_del_init (&dp->dl_recall_lru); + s->sc_status |=SC_STATUS_FREED ;spin_unlock (&cl->cl_lock);nfs4_put_stid (s);break ;
Greg Kroah-Hartman
maintainerPATCH 113/552 nfsd: size fh_verify server sockaddr slot by xpt_locallen
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chris Mason <[email protected]>
commit 71d068490098b1d23c63b2345e40675d3a1ca763 upstream.
The nfsd_fh_verify and nfsd_fh_verify_err tracepoints declare the server sockaddr slot sized by xpt_remotelen but fill it from xpt_local using xpt_locallen:
TP_STRUCT__entry(
...
__sockaddr(server, rqstp->rq_xprt->xpt_remotelen)
...
)
TP_fast_assign(
...
__assign_sockaddr(server, &rqstp->rq_xprt->xpt_local,
rqstp->rq_xprt->xpt_locallen);
...
)When xpt_locallen exceeds xpt_remotelen, __assign_sockaddr's memcpy writes past the reserved ring-buffer slot. In the reverse direction (xpt_locallen < xpt_remotelen) the slot is oversized and the unwritten tail leaks prior ring-buffer contents to trace consumers.
The write-past-end case is reachable on NFS/UDP. svc_xprt_set_remote() is only called from svc_tcp_accept() (net/sunrpc/svcsock.c) and from the RDMA connect path; svc_create_socket() for UDP calls only svc_xprt_set_local(), so xpt_remotelen stays 0 for the xprt's lifetime. Every fh_verify trace for an NFSv2/v3-over-UDP request then copies 16 or 28 bytes from xpt_local into a zero-byte slot.
The other NFSD tracepoints that record the server address (NFSD_TRACE_PROC_CALL_FIELDS, NFSD_TRACE_PROC_RES_FIELDS, SVC_RQST_ENDPOINT_FIELDS) already size the server slot by xpt_locallen; nfsd_fh_verify and nfsd_fh_verify_err were the only exceptions.
Fix by sizing the server slot with xpt_locallen so the declared slot matches the copy length. The client slot and its assignment already agree on xpt_remotelen and are left untouched.
--- fs/nfsd/trace.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/nfsd/trace.h +2 -2
@@ -236,7 +236,7 @@ TRACE_EVENT_CONDITION(nfsd_fh_verify, TP_CONDITION(rqstp != NULL),TP_STRUCT__entry (__field (unsigned int ,netns_ino ) - __sockaddr(server, rqstp->rq_xprt->xpt_remotelen) + __sockaddr(server, rqstp->rq_xprt->xpt_locallen) __sockaddr(client, rqstp->rq_xprt->xpt_remotelen)__field (u32, xid) __field(u32, fh_hash)
@@ -275,7 +275,7 @@ TRACE_EVENT_CONDITION(nfsd_fh_verify_err TP_CONDITION(rqstp != NULL && error),TP_STRUCT__entry (__field (unsigned int ,netns_ino ) - __sockaddr(server, rqstp->rq_xprt->xpt_remotelen) + __sockaddr(server, rqstp->rq_xprt->xpt_locallen) __sockaddr(client, rqstp->rq_xprt->xpt_remotelen)__field (u32, xid) __field(u32, fh_hash)
Greg Kroah-Hartman
maintainerPATCH 114/552 nfsd: validate nseconds in TIME_DELEG decode paths
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Layton <[email protected]>
commit 0f4a767340fad392bd656115b8752005518c9065 upstream.
The xdrgen-based TIME_DELEG_ACCESS and TIME_DELEG_MODIFY decode arms store a raw uint32_t nseconds directly into tv_nsec without enforcing nseconds < NSEC_PER_SEC. The legacy nfsd4_decode_nfstime4 has this check but the TIME_DELEG paths do not. A malformed timespec can propagate through notify_change() to disk.
Add range checks in both nfs4xdr.c (SETATTR path) and nfs4callback.c (CB_GETATTR path).
--- fs/nfsd/nfs4callback.c | 4 ++++ fs/nfsd/nfs4xdr.c | 4 ++++ 2 files changed, 8 insertions(+)
fs/nfsd/nfs4callback.c +4 -0
@@ -108,6 +108,8 @@ static int decode_cb_fattr4(struct xdr_sif (!xdrgen_decode_fattr4_time_deleg_access (xdr, &access))return -EIO ; +if (access.nseconds >=NSEC_PER_SEC ) +return -EIO ; fattr->ncf_cb_atime.tv_sec = access.seconds; fattr->ncf_cb_atime.tv_nsec = access.nseconds;
@@ -117,6 +119,8 @@ static int decode_cb_fattr4(struct xdr_sif (!xdrgen_decode_fattr4_time_deleg_modify (xdr, &modify))return -EIO ; +if (modify.nseconds >=NSEC_PER_SEC ) +return -EIO ; fattr->ncf_cb_mtime.tv_sec = modify.seconds; fattr->ncf_cb_mtime.tv_nsec = modify.nseconds;
fs/nfsd/nfs4xdr.c +4 -0
@@ -526,6 +526,8 @@ nfsd4_decode_fattr4(struct nfsd4_compounif (!xdrgen_decode_fattr4_time_deleg_access (argp->xdr, &access))return nfserr_bad_xdr; +if (access.nseconds >=NSEC_PER_SEC ) +return nfserr_inval; iattr->ia_atime.tv_sec = access.seconds; iattr->ia_atime.tv_nsec = access.nseconds; iattr->ia_valid |=ATTR_ATIME |ATTR_ATIME_SET |ATTR_DELEG ;
@@ -535,6 +537,8 @@ nfsd4_decode_fattr4(struct nfsd4_compounif (!xdrgen_decode_fattr4_time_deleg_modify (argp->xdr, &modify))return nfserr_bad_xdr; +if (modify.nseconds >=NSEC_PER_SEC ) +return nfserr_inval; iattr->ia_mtime.tv_sec = modify.seconds; iattr->ia_mtime.tv_nsec = modify.nseconds; iattr->ia_ctime.tv_sec = modify.seconds;