7.2.10-rc1 review
Greg Kroah-Hartman
maintainercover 7.2.10-rc1 review
This is the start of the stable review cycle for the 7.2.10 release. There are 428 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, 11 Oct 2026 14:08:23 +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/v7.x/stable-review/patch-7.2.10-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-7.2.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 7.2.10-rc1
Michael Hennerich <[email protected]>
iio: buffer-dmaengine: fix sg entry iteration when building dma_vecs
Josef Bacik <[email protected]>
xen/netfront: drop RX packets with a short Ethernet header
Gilberto Conde <[email protected]>
net: usb: qmi_wwan: add Quectel EG120K-EA
Paulo Alcantara <[email protected]>
smb: client: only require read lease for size-extending preallocate
Beata Michalska <[email protected]>
arm64: errata: Add Cortex-A725 erratum 3821522 workaround
Beata Michalska <[email protected]>
arm64: errata: Factor out broken AMU const counter cap
Zhengchuan Liang <[email protected]>
perf: Require kernel access for text poke events
Dapeng Mi <[email protected]>
perf/core: Check kernel access when kernel callchains are requested
Francisco Beltrán Millalén <[email protected]>
drm/amdgpu: reset VI ASIC on MacBookPro14,3
Andre Eikmeyer <[email protected]>
drm/amdgpu: reset VI ASIC on MacBookPro15,1
Ray Wu <[email protected]>
drm/amd/display: map PWM brightness through custom backlight curve
Alice Ryhl <[email protected]>
rust: irq: pass RegistrationInner as cookie to request_irq
Mehmet Fide <[email protected]>
mtd: rawnand: vf610_nfc: fix false bitflips on reads of erased pages
Matthieu Baerts (NGI0) <[email protected]>
mptcp: fix msk->timer_ival reset
Fan Wu <[email protected]>
iio: trigger: cancel reenable_work before freeing trigger
Donggeun Yoo <[email protected]>
iio: proximity: vl53l0x-i2c: claim direct mode for raw reads
Salah Triki <[email protected]>
iio: proximity: vcnl3020: fix ISR bitmask check in IRQ handler
Zhang Jie <[email protected]>
iio: proximity: sx9324: Correct proximity channel resolution
Cong Nguyen <[email protected]>
iio: proximity: pulsedlight: fix iio_device left registered on PM setup failure
Salah Triki <[email protected]>
iio: proximity: isl29501: Fix return type of isl29501_register_write
Laxman Acharya Padhya <[email protected]>
iio: proximity: aw96103: validate firmware data length
Matti Vaittinen <[email protected]>
iio: pressure: rohm-bm1390: Return error when read fails
Hui Su <[email protected]>
iio: pressure: bmp280: fix out-of-bounds access in sampling frequency lookup
Matti Vaittinen <[email protected]>
iio: light: rohm-bu27034: Fix infinite delay on error
Fan Wu <[email protected]>
iio: light: gp2ap020a00f: drain irq_work after free_irq
Arka Mondal <[email protected]>
iio: imu: adis16480: fix unprotected debugfs reads
Arka Mondal <[email protected]>
iio: imu: adis16400: fix unprotected debugfs reads
Marco Chen <[email protected]>
iio: health: max30102: fix NULL dereference in interrupt handler
Arka Mondal <[email protected]>
iio: gyro: adis16136: fix unprotected debugfs reads
Salah Triki <[email protected]>
iio: frequency: admv1013: fix wrong channel field used in admv1013_read_raw()
Geert Uytterhoeven <[email protected]>
iio: frequency: adf4377: Fully initialize clk_init_data and clk_parent_data
Pengpeng Hou <[email protected]>
iio: cdc: ad7150: fix OF matching and publish module aliases
Jonathan Cameron <[email protected]>
iio: buffer: Ensure bounce buffer used for unaligned case is zeroed.
Jinseob Kim <[email protected]>
iio: buffer: serialize buffer teardown with mode claims
Runyu Xiao <[email protected]>
iio: admv1013: initialize callback mutex before registering notifier
Fan Wu <[email protected]>
iio: adc: xilinx-xadc: free IRQ before cancelling the unmask worker on unbind
Felix Gu <[email protected]>
iio: adc: sun4i-gpadc-iio: drop underflowing pm_runtime_put() calls
Felix Gu <[email protected]>
iio: adc: sun4i-gpadc-iio: clean up on thermal zone registration failure
Fabrice Gasnier <[email protected]>
iio: adc: stm32-adc: fix possible division by zero in processed channel
Fabrice Gasnier <[email protected]>
iio: adc: stm32-adc: fix check on internal channel availability
Matti Vaittinen <[email protected]>
iio: adc: rohm-bd79124: Fix rising alarm
Matti Vaittinen <[email protected]>
iio: adc: rohm-bd79124: Fix GPIO mask check
Matti Vaittinen <[email protected]>
iio: adc: rohm-bd79124: Fix channel initialization
Matti Vaittinen <[email protected]>
iio: adc: rohm-bd79124: Catch regmap errors at measurement start/stop
Slavin Liu <[email protected]>
iio: adc: pac1934: check ACPI label duplication
Cong Nguyen <[email protected]>
iio: adc: max1363: sign-extend bipolar differential channel reads
Vladyslav Ivashchenko <[email protected]>
iio: adc: axp288: Add TS bias override for Haier HV103H
Pengpeng Hou <[email protected]>
iio: adc: aspeed: propagate reset deassert errors
Janani Sunil <[email protected]>
iio: adc: adi-axi-adc: Initialize state mutex
Antoniu Miclaus <[email protected]>
iio: adc: ade9000: request interrupts after powering the device
Antoniu Miclaus <[email protected]>
iio: adc: ade9000: handle Phase C dip events in IRQ1 handler
Antoniu Miclaus <[email protected]>
iio: adc: ade9000: fix overlapping scan_index for current and voltage channels
Linmao Li <[email protected]>
iio: adc: ade9000: fix NULL pointer dereference in clkout registration
Fan Wu <[email protected]>
iio: adc: ad_sigma_delta: fix use-after-free on unbind
Marcelo Schmitt <[email protected]>
iio: adc: ad7173: Fix digital filter configuration
Salah Triki <[email protected]>
iio: adc: ad4030: fix invalid oversampling_ratio validation
Salah Triki <[email protected]>
iio: accel: sca3000: fix frequency divider condition check
Jiale Yao <[email protected]>
iio: accel: kxcjk-1013: reject duplicate event disable
Matti Vaittinen <[email protected]>
iio: accel: kionix-kx022a: Prevent memory leak and fix state
Frank Sorenson <[email protected]>
smb: client: split cifsFileInfo bitfields to avoid shared-byte RMW races
Paulo Alcantara <[email protected]>
smb: client: require stable pages for signed connections
Paulo Alcantara <[email protected]>
smb: client: drain and invalidate before server-side copy/clone
Paulo Alcantara <[email protected]>
smb: client: distinguish real EOF from a stale remote_i_size on read
Paulo Alcantara <[email protected]>
smb: client: flush dirty data before zeroing a range
Paulo Alcantara <[email protected]>
smb: client: only require read lease for size-extending zero range
Paulo Alcantara <[email protected]>
smb: client: flush and commit data before querying allocated ranges
Paulo Alcantara <[email protected]>
smb: client: discard post-EOF pagecache when extending a file via clone range
Paulo Alcantara <[email protected]>
smb: client: discard post-EOF pagecache when extending a file via copy range
Paulo Alcantara <[email protected]>
smb: client: discard post-EOF pagecache when extending a file via zero range
Daehyeon Ko <[email protected]>
thunderbolt: Reject oversized XDomain properties responses
Kurt Lieber <[email protected]>
thunderbolt: Disable CL states for the Anker Prime TB5 dock
Fedor Pchelkin <[email protected]>
thunderbolt: Fix NULL dereference in tb_remove_work()
Sven Peter <[email protected]>
thunderbolt: Don't access a DP tunnel after its DPRX read was canceled
Sven Peter <[email protected]>
thunderbolt: Fix domain reference leak when DPRX read is canceled
Sven Peter <[email protected]>
thunderbolt: Tear down inactive DP tunnels when the domain is stopped
Sven Peter <[email protected]>
thunderbolt: Mark discovered tunnels as active
Sven Peter <[email protected]>
thunderbolt: Make the DP tunnel activation callback mandatory
Sven Peter <[email protected]>
thunderbolt: Hold a router reference for each allocated HopID
Mika Westerberg <[email protected]>
thunderbolt: Fix KASAN reported use-after-free when request is canceled
Ian Lin <[email protected]>
USB: serial: option: add Compal EXC-T1 support
Sebastian Sjoholm <[email protected]>
USB: serial: option: add Quectel RG660QB
Ian Lin <[email protected]>
USB: serial: option: add Compal EXM-G1x support
Carlo Szelinsky <[email protected]>
USB: serial: option: add Quectel EG060W
Zhao Dongdong <[email protected]>
USB: serial: option: add support for SIMCom SIM8260C
Johan Hovold <[email protected]>
USB: serial: fix ioctl hangup race
Johan Hovold <[email protected]>
USB: serial: fix driver deregistration order
Johan Hovold <[email protected]>
USB: serial: fix dynamic id driver deregistration race
Johan Hovold <[email protected]>
USB: serial: ssu100: fix baud rate overflow
Johan Hovold <[email protected]>
USB: serial: quatech2: fix baud rate overflow
Jérémy Carrat <[email protected]>
USB: serial: cp210x: add Corsair AX1500i Power Supply
Yuqi Xu <[email protected]>
wifi: mac80211: handle empty FILS association request payload
Zihan Xi <[email protected]>
wifi: mac80211: fix mesh fast xmit path deletion UAF
Felix Fietkau <[email protected]>
wifi: mac80211: set info->band for 802.3 encap offload frames
Zhao Li <[email protected]>
wifi: mac80211: release mesh path quota on failed additions
Ruide Cao <[email protected]>
wifi: mac80211: reject invalid 320 MHz CSA bandwidth
Yuqi Xu <[email protected]>
wifi: mac80211: minstrel_ht: validate fixed rate index
Zhao Li <[email protected]>
wifi: mac80211: keep fallback association elements alive
Zhao Li <[email protected]>
wifi: mac80211: account proxy paths against the mesh path limit
Zhao Li <[email protected]>
wifi: mac80211: drain PS delivery work during station teardown
Zhao Li <[email protected]>
wifi: mac80211: shut down RX BA session timer on teardown
Zhiling Zou <[email protected]>
wifi: mac80211: keep paired old chanctx alive
Zhiling Zou <[email protected]>
wifi: mac80211: count only matching reservations in reserved switch
Guangshuo Li <[email protected]>
wifi: iwlegacy: 3945: free EEPROM data on remove
Tianchu Chen <[email protected]>
wifi: cw1200: fix TX padding OOB read leaking heap data to device
Stanislaw Gruszka <[email protected]>
wifi: cfg80211: fix RTS threshold setting for single-radio PHY
Mostafa Saleh <[email protected]>
KVM: arm64: Use stage-1 leaf size for VM_PFNMAP
Marc Zyngier <[email protected]>
KVM: arm64: vgic-its: Fix MOVALL handling of source redistributor
Marc Zyngier <[email protected]>
KVM: arm64: vgic: Take a refcount on IRQs referenced by last_lr_irq
Marc Zyngier <[email protected]>
KVM: arm64: vgic: Allow last_lr_irq to be NULL when LRs are not overflowing
Fuad Tabba <[email protected]>
KVM: arm64: Apply the fine-grained UNDEFs without FEAT_FGT
Fuad Tabba <[email protected]>
KVM: arm64: Clear HCR_EL2.RW for 32-bit non-protected vCPUs
Sean Christopherson <[email protected]>
KVM: SVM: Update control fields on #VMEXIT if and only if VMRUN succeeded
Sean Christopherson <[email protected]>
KVM: SVM: Preserve TLB control (i.e. pending TLB flush) on failed VMRUN
Sean Christopherson <[email protected]>
KVM: SVM: Use the active VMCB's MSR bitmap when checking if MSR is intercepted
Sean Christopherson <[email protected]>
KVM: x86/mmu: Bail from shadow walks if the root is invalid or a dummy
Sean Christopherson <[email protected]>
KVM: SEV: Do cache maintenance on the source VM *before* clearing SEV state
Sean Christopherson <[email protected]>
KVM: SEV: Nullify "have run CPUs" mask pointer when freeing it
Sean Christopherson <[email protected]>
KVM: nVMX: Force MSR bitmap refresh if runtime eVMCS controls are modified
Sagnik Sasmal <[email protected]>
mtd: spinand: Do not update the QE bit on devices without one
Nuno Sá <[email protected]>
mtd: spinand: fix zero oobavail when no ECC engine is used
Nuno Sá <[email protected]>
mtd: spinand: fix NULL pointer dereference with no ECC engine
Han Xu <[email protected]>
mtd: spinand: Enable QE on all dies
Runyu Xiao <[email protected]>
mtd: spi-nor: core: Fix mutex leak in spi_nor_rww_start_exclusive()
Mehmet Fide <[email protected]>
mtd: rawnand: vf610_nfc: fix reads on chips with more than 64 bytes of OOB
Runyu Xiao <[email protected]>
mtd: rawnand: cadence: Initialize IRQ state before requesting IRQ
Menachem Adin <[email protected]>
mtd: mtd_intel_dg: reset poll counter for each erase
Pei Xiao <[email protected]>
mtd: block2mtd: Fix divide error when erase_size is zero
Guixin Liu <[email protected]>
nvmet: copy the hostid into the ctrl before creating PR pc_refs
Daehyeon Ko <[email protected]>
nvmet: pci-epf: reject too-short SGL segments
Weiming Shi <[email protected]>
nvmet-auth: fix out-of-bounds write in nvmet_auth_challenge()
Bean Huo <[email protected]>
nvme-pci: add NVME_QUIRK_DMAPOOL_ALIGN_512 for Micron 4100AT
Daehyeon Ko <[email protected]>
nvme-multipath: fix underflow in ANA log bounds checks
Guixin Liu <[email protected]>
nvme-multipath: set BLK_FEAT_ZONED only after the zone info is known
Jiangshan Yi <[email protected]>
tpm: fix off-by-four bounds check in tpm2_get_random()
Mikhail Gavrilov <[email protected]>
x86/mm: Drop unnecessary PMD page copy when freeing
Laurent Wandrebeck <[email protected]>
x86/mm: Don't apply va_align to hugetlb mappings on AMD F15h
Chandrashekar Devegowda <[email protected]>
Bluetooth: btintel_pcie: reject oversized TX packets in send_frame()
Chandrashekar Devegowda <[email protected]>
Bluetooth: btintel_pcie: fix plen overflow in btintel_pcie_recv_frame()
Chandrashekar Devegowda <[email protected]>
Bluetooth: btintel: fix buffer over-read in btintel_hw_error()
Chengfeng Ye <[email protected]>
Bluetooth: hci_core: Serialize fragmented ISO packet queueing
Chengfeng Ye <[email protected]>
Bluetooth: hci_core: Serialize SCO and ISO scheduling with teardown
Chengfeng Ye <[email protected]>
Bluetooth: hci_core: Serialize ACL scheduling with channel deletion
Linmao Li <[email protected]>
Bluetooth: hci_core: Fix inquiry cache timestamps on 64-bit systems
Chengfeng Ye <[email protected]>
Bluetooth: hci_conn: Lock parent access during enhanced SCO setup
Chengfeng Ye <[email protected]>
Bluetooth: hci_sync: Fix inquiry cache use-after-free
Chengfeng Ye <[email protected]>
Bluetooth: Serialize SMP remote OOB data access
Chengfeng Ye <[email protected]>
Bluetooth: RFCOMM: Fix initial port reference race
Abdurrahman Hussain <[email protected]>
i2c: xiic: don't clobber msg->len to signal block-read completion
Abdurrahman Hussain <[email protected]>
i2c: xiic: defer RX_FULL until all trailing bytes are in FIFO
Abdurrahman Hussain <[email protected]>
i2c: xiic: preserve PEC byte length in SMBus block read setup
Rounak Das <[email protected]>
EDAC/altera: Fix device node reference leaks in the SDMMC ECC setup
Dinh Nguyen <[email protected]>
EDAC/altera: Fix use-after-free in error paths
Dinh Nguyen <[email protected]>
EDAC/altera: Fix memory leak on dci allocation failure
Dinh Nguyen <[email protected]>
EDAC/altera: Drop __init from ECC setup paths for re-probe safety
Dinh Nguyen <[email protected]>
EDAC/altera: Do not allow driver unbinding
Guangshuo Li <[email protected]>
EDAC/versalnet: Drop remote processor handle refcount on driver removal
Jakub Gawlik <[email protected]>
ALSA: hda/realtek: Add micmute LED quirk for Acer Swift SFG16-72
Yu-Hsiang Tseng <[email protected]>
ALSA: hda/realtek: Fix silent speaker on Higole F9B
Zhang Heng <[email protected]>
ALSA: hda/realtek: Fix square wave output on ASUS Strix G615LR
Xiang Mei <[email protected]>
ALSA: ua101: reject mismatched capture/playback packet sizes
Kyle Zeng <[email protected]>
ALSA: seq: Serialize compat port-info ioctls
Aaron Kling <[email protected]>
ALSA: hda/tegra: Re-enable SDO workaround for Tegra194
Zimeng Li <[email protected]>
ASoC: qcom: lpass-cpu: use DAI table index for playback constraints
Jiangshan Yi <[email protected]>
ASoC: codecs: rt1017-sdca-sdw: fix uninitialized stream_config->type
Jiangshan Yi <[email protected]>
ASoC: codecs: max98363: fix uninitialized stream_config->type
Liviu Nicoara <[email protected]>
ASoC: codecs: lpass-wsa-macro: rewrite the interpolator volume after enabling clocks
Andrea Parri <[email protected]>
arm64: mm: Fix the break-before-make flush range for erratum 2645198
Mark Rutland <[email protected]>
arm64/fpsimd: signal: Forbid non-streaming SVE payload on SME-only systems
Paul Mbewe <[email protected]>
serial: sc16is7xx: refill TX FIFO below trigger using fresh TXLVL
Paul Mbewe <[email protected]>
serial: sc16is7xx: fix TX gap caused by kfifo circular buffer wrap-around
Wentao Liang <[email protected]>
serial: vt8500: Fix clock reference leak in vt8500_serial_probe()
Simon Gassner <[email protected]>
serial: tegra: don't clear the Tx FIFO on an Rx-only reset
Wentao Liang <[email protected]>
serial: ma35d1: Fix clock reference leak in ma35d1serial_probe()
Johan Hovold <[email protected]>
serial: fix TIOCMIWAIT race
Johan Hovold <[email protected]>
serial: fix ioctl hangup race
Johan Hovold <[email protected]>
serial: revert guards in uart_wait_modem_status()
Ruslan Valiyev <[email protected]>
serial: core: fix NULL pointer dereference in serial_core_unregister_port()
Johan Hovold <[email protected]>
serial: abort TIOCMIWAIT on hangup
Kendall Willis <[email protected]>
serial: 8250_omap: fix wake irq cleared during suspend
Fan Wu <[email protected]>
serial: 8250_bcm7271: fix use-after-free in brcmuart_remove()
Ian Rogers <[email protected]>
perf: Replace perf_event_header__init_id with full header init
Fan Wu <[email protected]>
tty: serial: max3100: shut down timer before freeing port
Johan Hovold <[email protected]>
tty: fix saved termios reset race
Johan Hovold <[email protected]>
tty: abort break signalling on hangup
Viken Dadhaniya <[email protected]>
tty: serial: qcom_geni_serial: Keep console RX functional after deep idle
Johan Hovold <[email protected]>
tty: port: fix tty_port_tty_vhangup() race
Johan Hovold <[email protected]>
tty: tty_port: restore TTY_IO_ERROR on activation failure
Daniel Starke <[email protected]>
tty: n_gsm: fix missing modem controls after DLCI open in convergence layer type 2
Joshua Rogers <[email protected]>
tty: vcc: hold port lock when clearing tty pointer in vcc_cleanup
Joshua Rogers <[email protected]>
tty: vcc: zero-initialize control packet in vcc_send_ctl()
Johan Hovold <[email protected]>
tty: amiserial: fix broken TIOCMIWAIT
Mingyu Wang <[email protected]>
tty: vt: fix memory leak in vc_allocate()
Jie Deng <[email protected]>
usb: cdns3: Fix NULL pointer dereference in cdns3_pci_probe
Fan Wu <[email protected]>
usb: cdns3: fix use-after-free in cdns3_gadget_exit()
Jameson Thies <[email protected]>
usb: typec: ucsi: displayport: Current CAM OOB index fixup
Prashanth K <[email protected]>
usb: typec: ucsi: Get the connector fwnode based on reg value
Pannarat Wiriyaarritham <[email protected]>
usb: typec: ucsi: acpi: Assume UCSI 1.2 on Acer Nitro ANV15-41
Fan Wu <[email protected]>
usb: typec: ucsi: glink: fix use-after-free of ucsi on remove
Radhey Shyam Pandey <[email protected]>
usb: typec: tipd: fix uninitialized typec_partner_desc in cd321x_update_work()
Radhey Shyam Pandey <[email protected]>
usb: typec: tipd: fix uninitialized typec_partner_desc in tps6598x_connect()
Marian Rotariu <[email protected]>
usb: typec: tipd: don't send GAID when probe fails in APP mode
Amit Sunil Dhamne <[email protected]>
usb: typec: tcpm: recover after failure to start the frs ams
Runyu Xiao <[email protected]>
USB: dwc2: shut down wakeup timer before freeing HCD state
Hui Peng <[email protected]>
usb: core: clear both ep_in and ep_out for non-ep0 control endpoints
Myeonghun Pak <[email protected]>
usb: chipidea: tegra: disable runtime PM on resume failure
Yuchao Zhang <[email protected]>
usb: gadget: f_fs: Fix NULL pointer dereference in FUNCTIONFS_ENDPOINT_DESC
Alan Stern <[email protected]>
USB: gadget: dummy-hcd: Fix wait for outstanding request completions
Fan Wu <[email protected]>
usb: gadget: aspeed-vhub: cancel wake work on device removal
Jiazi Liu <[email protected]>
usb: dwc3: gadget: fix IRQ storm on invalid event buffer count
Radhey Shyam Pandey <[email protected]>
usb: dwc3: am62: Fix runtime PM usage count leak on probe error path
Marek Maslanka <[email protected]>
usb: typec: port-mapper: Only match USB4 port if host interface is available
Linkai Gong <[email protected]>
usb: typec: anx7411 - stop the IRQ before destroying the workqueue
Liu Chao <[email protected]>
usb: gadget: f_uac1_legacy: validate bRequest index in generic_{set,get}_cmd
Takashi Iwai <[email protected]>
usb: gadget: midi2: Fix the jack descriptor array sizes
Myeonghun Pak <[email protected]>
usb: ohci-st: disable controller wakeup on removal
Myeonghun Pak <[email protected]>
usb: ohci-spear: disable controller wakeup on removal
Myeonghun Pak <[email protected]>
usb: ohci-s3c2410: disable controller wakeup on removal
Myeonghun Pak <[email protected]>
usb: ohci-da8xx: disable controller wakeup on cleanup
Orgad Shaneh <[email protected]>
usb: octeon-hcd: fix the FIFO-flush timeout computation
Lovekesh Solanki <[email protected]>
usb: hub: use shorter 120ms post resume hold for SS root hubs
Syed Labeeq Sajid Bukhari <[email protected]>
usb: storage: sierra_ms: reject short SWoC info transfers
Johan Hovold <[email protected]>
USB: serial: fix port tear down use-after-free
Yuchao Zhang <[email protected]>
USB: cdc-acm: skip URB restart in port_shutdown if disconnected
Johan Hovold <[email protected]>
USB: cdc-acm: fix racy TIOCMIWAIT implementation
Viken Dadhaniya <[email protected]>
soc: qcom: geni-se: Correct QUP Core ICC vote constants
Alice Ryhl <[email protected]>
rust_binder: reschedule node refcount update on thread exit
Alice Ryhl <[email protected]>
rust_binder: cancel deferred work items in thread exit
Yuxiao Wang <[email protected]>
nitro_enclaves: fix use-after-free on SLOT_ALLOC failure
Raphaël Larocque <[email protected]>
Input: synaptics - limit T440p InterTouch quirk to LEN0036
Lovekesh Solanki <[email protected]>
Input: synaptics - add LEN205b entry to smbus_pnp_ids for ThinkPad T490
David Heidelberg <[email protected]>
Input: s6sy761 - fix resume ordering and restore sensing
Lovekesh Solanki <[email protected]>
Input: i8042 - add nomux quirk for Fujitsu LIFEBOOK U7410
Martino Papero <[email protected]>
Input: atkbd - skip deactivate for Lenovo IdeaPad Slim 3 15IWC11
Wentao Liang <[email protected]>
kgdboc: Fix tty driver reference leak in configure_kgdboc()
Karl Mehltretter <[email protected]>
hrtimer: Use the mask to clear TIF_HRTIMER_REARM from the exit work
Troy Mitchell <[email protected]>
clk: spacemit: k3: add CPU PLL rate tables
Peiyang He <[email protected]>
binderfs: fix UAF write in binder_add_device
Tomer Pomeranc <[email protected]>
binder: fix leaked fd fixups on TF_UPDATE_TXN supersede
Tomer Pomeranc <[email protected]>
binder: fix is_failure flag for superseded transaction cleanup
Theo Andersen Carton <[email protected]>
drm/amdgpu: skip the noirq suspend reset for a switcheroo-parked GPU
Guangshuo Li <[email protected]>
drm/amdgpu: fix ACP MFD device leak on init failure
Alex Deucher <[email protected]>
drm/amdgpu: drop userq callback assignment for sdma 7.1
Pierre-Eric Pelloux-Prayer <[email protected]>
drm/amdgpu: implement workaround for sdma dcc corruption
Guangshuo Li <[email protected]>
drm/amdgpu: fix IP instance memory leak on kobject add failure
Wentao Liang <[email protected]>
drm/mediatek: Fix pdev reference leak in mtk_drm_bind()
Guangshuo Li <[email protected]>
drm/mediatek: Fix ovl adaptor platform device leak
Haojie Li <[email protected]>
drm/mediatek: Add missing IS_ERR check for ovl_adaptor platform device
Imre Kaloz <[email protected]>
drm/radeon: Read the VRAM VBIOS signature with readb()
Mitul Golani <[email protected]>
drm/i915/vrr: Disable DC balance by default
Alex Deucher <[email protected]>
drm/amdgpu/gmc12: properly pass flush_type to gmc_v12_0_flush_vm_hub()
Alex Deucher <[email protected]>
drm/amdgpu/gmc12.1: properly pass flush_type to gmc_v12_1_flush_vm_hub()
Willian Oliveira <[email protected]>
drm/amdgpu/gfx6: fix firmware leak on teardown
Timur Kristóf <[email protected]>
drm/amd/pm/si: Fix updating clock limits on AC/DC
Timur Kristóf <[email protected]>
drm/amd/pm/si: Check AMD_IS_MOBILITY flag for PPSMC_SYSTEMFLAG_GPIO_DC
Timur Kristóf <[email protected]>
drm/amd/display: Mark DCE 6.4 as not APU
Simon Polack <[email protected]>
drm/amd/display: Fix stale replay_events after mod_power stream removal
Timur Kristóf <[email protected]>
drm/amd/display: Fix fast updates on DCE 8.1
Timur Kristóf <[email protected]>
drm/amd/display: Fix fast updates on DCE 6.x
Jiangshan Yi <[email protected]>
drm/amd/display: check dc_state_create_copy() for NULL in dm_suspend
Arthur Heymans <[email protected]>
drm/amd/display: Preserve eDP mode on initial ASSR failure
Hari Mishal <[email protected]>
drm/amd/display: guard dc_sink dereferences in MST mode validation
Nikola Prica <[email protected]>
PCI: Accept AtomicOps already enabled by the hypervisor
Ömer Mete Kaya <[email protected]>
bpf: Fix missing migration protection in __rhtab_map_lookup_and_delete_batch()
Chris Mason <[email protected]>
futex: Fix private hash use-after-free on resize
Wentao Liang <[email protected]>
drm/mediatek: Fix runtime PM leak in mtk_hdmi_ddc_v2_probe()
Alexei Starovoitov <[email protected]>
bpf: Fix objects stuck in free_by_rcu_ttrace
Alexei Starovoitov <[email protected]>
bpf: Factor out __do_call_rcu_ttrace()
Richard Fitzgerald <[email protected]>
spi: cs42l43: Workaround for wrong speaker ID on Dell XPS 13 DX13260
Takashi Iwai <[email protected]>
ALSA: ice1712: Fix the error handling via auto-cleanup at probe
Takashi Iwai <[email protected]>
ALSA: core: Define auto-cleanup for snd_card_free()
Luo Gengkun <[email protected]>
perf: Fix race between perf_event_exit_task() and perf_pending_task()
Hongjian Dai <[email protected]>
i2c: at91: release DMA channels when probe defers
Lorenzo Bianconi <[email protected]>
net: mvneta: clear XDP pfmemalloc flag between frames
Eric Dumazet <[email protected]>
ipv6: sr: use skb_get_hash_net() in seg6_make_flowlabel()
Prathamesh Deshpande <[email protected]>
net/mlx5e: Fix AF_XDP TX timestamp teardown NULL dereference
Quentin Freimanis <[email protected]>
net: sparx5: make ports inherit the switch base mac address type
Yuho Choi <[email protected]>
of: Put coreboot node after compatibility check
Harshit Mogalapalli <[email protected]>
net: microchip: vcap: stop scanning after deleting key field
Pablo Neira Ayuso <[email protected]>
netfilter: flowtable: generalize pending status bit
Fernando Fernandez Mancera <[email protected]>
netfilter: bpf: reject invalid NAT manipulation types
Julian Anastasov <[email protected]>
ipvs: filter some flags received in the backup server
Julian Anastasov <[email protected]>
ipvs: do not create invisible templates
Julian Anastasov <[email protected]>
ipvs: fix missing counter decrement in lblc
Jeff Jo <[email protected]>
tcp: refresh TS.Recent for accepted old ACKs
Quentin Freimanis <[email protected]>
net: sparx5: skip ptp deinit if init was skipped
Yongzhao Chen <[email protected]>
net: phy: qcom: at803x: Fix IPQ5018 short-cable DAC values
Sandeep Haemoon <[email protected]>
net: ethernet: mtk_eth_soc: allocate dummy netdev sooner
Jamal Hadi Salim <[email protected]>
net: cap skb->queue_mapping when the tx queue is picked
Nicolai Buchwitz <[email protected]>
net: bcmgenet: fix NULL dereference in set_coalesce before first open
Yoshihisa Yamamoto <[email protected]>
net: pcs: rzn1-miic: Clear MIIC protection state before unprotect sequence
Niklas Cassel <[email protected]>
virtio_blk: set the zone write granularity
Takashi Iwai <[email protected]>
ALSA: usb-audio: Apply boot quirk for Behringer models generically
Sebastian Dalfuß <[email protected]>
ALSA: usb-audio: Add boot quirk for Behringer CM1A
Jamal Hadi Salim <[email protected]>
net/sched: sch_codel: match the no-drop threshold to the packet size
Jamal Hadi Salim <[email protected]>
net/sched: fq_codel: match the no-drop threshold to the packet size
Hannu Varjoranta <[email protected]>
gve: DQO: accept TSO packets with non-protocol gso_type bits
Florent Revest (Anthropic) <[email protected]>
bpf: Skip detached progs in trampoline images that are still in use
Florent Revest (Anthropic) <[email protected]>
bpf: Wait for an RCU tasks grace period before freeing trampoline progs
Eric Dumazet <[email protected]>
net: restrict SO_RESERVE_MEM to TCP sockets and cap max value
Nicolai Buchwitz <[email protected]>
net: ethtool: let tsconfig reach a PHY-only timestamp provider
Andrea Mayer <[email protected]>
seg6: ensure packet data is writable before modifying SRH and IPv6 DA
Lorenzo Bianconi <[email protected]>
net: stmmac: fix rx Scatter-Gather support
Mina Almasry <[email protected]>
net: page_pool: fix use-after-free in page_pool_recycle_ring_bulk()
Jérémy Jean <[email protected]>
tipc: prevent GCM nonce reuse on peer key changes
Baha Mesleh <[email protected]>
octeontx2-af: mcs: Fix SC resource cleanup loop
Geetha sowjanya <[email protected]>
octeontx2-pf: Fix aura BPID assignment when CONFIG_DCB is enabled
Anirudh Virdi <[email protected]>
net/mlx5: Fix slab-out-of-bounds when handling team device events
Florian Fainelli <[email protected]>
net: systemport: Fix RUNT MIB counter register offset calculation
Florian Fainelli <[email protected]>
net: systemport: Fix buffer overflow in bcm_sysport_get_stats()
Julien Stephan <[email protected]>
drm/mediatek: mtk_hdmi_v2: fix VID_DOWNSAMPLE_CONFIG register offset
Nguyen Ngoc Thang <[email protected]>
Bluetooth: hci_sync: don't drain cmd_sync backlog on unregister
Marcin Bernatowicz <[email protected]>
drm/xe/pf: Keep VF LMEM BAR size low if no VFs enabled
Michal Wajdeczko <[email protected]>
drm/xe/pf: Refactor VF LMEM BAR resize helper function
Kailang Yang <[email protected]>
ALSA: hda/realtek - Add headset mode for Dell Pro QC1255
Cen Zhang (Microsoft) <[email protected]>
wifi: mac80211: fix slab-out-of-bounds read in ieee80211_monitor_select_queue()
Florian Westphal <[email protected]>
netfilter: ipset: do not update comments from kernel-side adds
Qishuai Liu <[email protected]>
ipv6: fix prefix route expiry in modify_prefix_route()
Nicolai Buchwitz <[email protected]>
net: bcmgenet: allocate RX buffers as page fragments
Jamal Hadi Salim <[email protected]>
net/sched: cls_api: reclaim an empty proto on the error path
Binbin Deng <[email protected]>
net/mctp: publish the mctp_dev only after it is initialised
Kumar Kartikeya Dwivedi <[email protected]>
bpf: Hold map BTF for the memory allocator destructor record
Yao Sang <[email protected]>
nvme: fix command effects log lifetime for multipath heads
Arnd Bergmann <[email protected]>
nvme: work around -Wformat-security warning
John Garry <[email protected]>
nvme: fix cdev lifetime
John Garry <[email protected]>
nvme: add nvme_get_ns_head()
Vineet Gupta <[email protected]>
ARC: arch_cmpxchg_relaxed to use size of pointed type not pointer
Alexei Starovoitov <[email protected]>
bpf: Fix overflow of jump offset in constant blinding
Arnd Bergmann <[email protected]>
drbd: remove unused drbd_nl_mcgrps[] array
Maciej Strozek <[email protected]>
ASoC: SDCA: Add better pm_runtime error handling in func probe
Maciej Strozek <[email protected]>
ASoC: SDCA: Set suspended flag after resuming within system suspend
Oleg Keri <[email protected]>
arm64: topology: fix arch_freq_get_on_cpu() overflow above 4.19 GHz
Harry Yoo (Meta) <[email protected]>
mm/slab: do not wake up kswapd in __kfree_rcu_sheaf()
Harry Yoo (Oracle) <[email protected]>
mm/slab: handle the !allow_spin case in kfree_rcu_sheaf()
Sai Teja Aluvala <[email protected]>
Bluetooth: btintel: validate DDC record lengths
Sang-Hoon Choi <[email protected]>
Bluetooth: hci_core: free the HCI ID if naming fails
Keith Busch <[email protected]>
blk-mq: set RQF_USE_SCHED when the operation is known
Yang Xiuwei <[email protected]>
block: reject polled dio with user integrity metadata
Cezary Rojewski <[email protected]>
ASoC: codecs: rt274: Fix format setting for 44100 rate
Cezary Rojewski <[email protected]>
ASoC: codecs: rt286: Revert delay value for jack setup
Felix Fietkau <[email protected]>
wifi: mac80211: prevent AP VLAN tx from other interfaces
Zhao Li <[email protected]>
wifi: cfg80211: preserve hidden-group beacon IE ownership
Yuqi Xu <[email protected]>
wifi: mac80211: validate TX status rate metadata
Manush Prajwal <[email protected]>
rtc: mpfs: fix unchecked devm_clk_get() error pointer in probe()
Aamir Ahmed <[email protected]>
rtc: ac100: Fix clock provider use-after-free on probe failure
Liu Dalin <[email protected]>
rtc: dev: zero-initialize struct rtc_wkalrm to prevent information leak
Georgios Karantzas <[email protected]>
wifi: ath9k_htc: bound TX aggregation to MAX_TX_BUF_SIZE
Pengpeng Hou <[email protected]>
wifi: ath9k: reject short WMI command responses
Toke Høiland-Jørgensen <[email protected]>
wifi: ath9k: Clean up device initialisation guards
Nicolas Escande <[email protected]>
wifi: ath11k: reset ar->num_stations on hardware start
Yuchao Zhang <[email protected]>
wifi: mac80211: drop oversized fragments to avoid extra_len overflow
Sheetal <[email protected]>
ASoC: tegra: Fix ASRC Stream6 input threshold control
Aamir Ahmed <[email protected]>
wifi: wfx: validate MIB read length before copying to caller
HyeongJun An <[email protected]>
ASoC: wm8903: Move the DRC QR threshold to the register that holds it
Abdurrahman Hussain <[email protected]>
of/overlay: don't create "//" paths for fragments targeting the root
Abdurrahman Hussain <[email protected]>
of/overlay: don't leak fragment references when changeset init fails
Karl Mehltretter <[email protected]>
random: fix vgetrandom_opaque_params kernel-doc
Hao Zhang <[email protected]>
blk-cgroup: save IRQ state in blkg_tryget_closest()
Julian Sun <[email protected]>
nvmet: preserve device path on allocation failure
Karl Mehltretter <[email protected]>
mtd: core: call _get_device() with the master MTD
Karl Mehltretter <[email protected]>
mtd: core: avoid double-free of OTP NVMEM device
Matti Vaittinen <[email protected]>
iio: accel: kionix-kx022a: Fix array boundary check
Matti Vaittinen <[email protected]>
iio: light: rohm-bu27034: Fix error return
Matti Vaittinen <[email protected]>
iio: dac: rohm-bd79703: Do not allow writing SCALE
Alberto Garcia <[email protected]>
ext4: don't enable large folios on encrypted inodes
Xiang Mei <[email protected]>
ALSA: line6: reject oversized playback packets
Harin Lee <[email protected]>
ALSA: ctxfi: Fix silent playback on Titanium HD (SB1270)
Nguyen Ngoc Thang <[email protected]>
ALSA: caiaq: unregister the input device when probe fails
Wentao Liang <[email protected]>
wifi: wlcore: Fix runtime PM leak in wlcore_remove()
Zizhi Wo <[email protected]>
vt: skip screen update for DEC alignment test on backgroup consoles
Hui Peng <[email protected]>
vt: selection: Fix unsigned underflow and slab-out-of-bounds read in paste_selection()
Yi Yang <[email protected]>
vc_screen: reload vc pointer before if (ret) in vcs_write() to avoid UAF
Baolin Wang <[email protected]>
mm: shmem: ignore sysfs configs for shmem forced collapse
Lorenzo Stoakes (ARM) <[email protected]>
mm/vma: predicate setting mmap_prepare VMA fields on new vma alloc
SJ Park <[email protected]>
mm/damon/core: don't skip damos_adjust_quota() while esz is not zero
Zhichen Wang <[email protected]>
virt: vmgenid: set driver_data before registering notification handlers
Vitaly Kuznetsov <[email protected]>
virt: vmgenid: remap memory as decrypted
Hao Ge <[email protected]>
module: fix lost error code from codetag_load_module()
Paulo Alcantara <[email protected]>
netfs: zero the tail of a short DIO/unbuffered read
Paulo Alcantara <[email protected]>
netfs: zero gaps in read-gaps folio to avoid writing back stale data
Paulo Alcantara <[email protected]>
netfs: clear post-EOF pagecache when extending a file via write
Surendran Kanagaraj <[email protected]>
tpm: Disable TPM on null key name mismatch
Zhan Xusheng <[email protected]>
time/jiffies: Saturate in mult_hz() instead of wrapping
Zhan Xusheng <[email protected]>
sysctl: Negate before converting in the int read path
Jun Yang <[email protected]>
sctp: check RCV_SHUTDOWN after the sendmsg connect wait
Runyu Xiao <[email protected]>
rtc: spear: initialize IRQ state before requesting alarm IRQ
Aamir Ahmed <[email protected]>
rtc: ac100: Assign .num before accessing .hws
Nathan Chancellor <[email protected]>
random: vDSO: avoid call to memset() when zeroing reserved parameter
Oleksij Rempel <[email protected]>
r8169: disable EEE on RTL8168h/8111h
Xuanqiang Luo <[email protected]>
pfcp: fix socket lifetime on netdevice registration failure
Ilkka Lappeteläinen <[email protected]>
net/packet: prevent TX_RING byte count overflow
Aohan Mei <[email protected]>
netfilter: nft_flow_offload: drop flowtable reference on init error path
Bartosz Golaszewski <[email protected]>
net: phy: aquantia: fix system interface type not updated in forced mode
Alireza Asgari <[email protected]>
net: fix checksum offsets in skb_splice_from_iter()
Willem de Bruijn <[email protected]>
net: extend IPv6 exthdr detection of tunneled packets
Zihan Xi <[email protected]>
net: gso: limit recursive IP-in-IP segmentation
Abdurrahman Hussain <[email protected]>
of/overlay: only treat a positive changeset id as registered
Abdurrahman Hussain <[email protected]>
of/overlay: put property on deadprops only after changeset add succeeds
Wentao Liang <[email protected]>
of/irq: Fix remaining refcount leaks in of_irq_init()
Jari Seppälä <[email protected]>
octeontx2-pf: Fix RSS indirection table size
Leon Hwang <[email protected]>
kprobes: Skip disarmed probes when checking optkprobe overlap
Andrey Ryabinin <[email protected]>
kasan: unpoison task stack below watermark only in generic mode
Zhiling Zou <[email protected]>
ipvs: bound LBLCR and LBLC cache growth
Jens Axboe <[email protected]>
io_uring: fix task_work add use-after-free with SQPOLL
Junyuan Feng <[email protected]>
io_uring/zcrx: requeue multishot receives stopped by a local resource
lollipopkit <[email protected]>
io_uring/cmd_net: end TX_TIMESTAMP multishot when the CQ is full
Aldo Ariel Panzardo <[email protected]>
HID: multitouch: stop the release timer from being rearmed on remove
Benjamin Tissoires <[email protected]>
HID: bpf: cast size to ssize_t when checking hid_bpf_hw_request
Masami Hiramatsu (Google) <[email protected]>
fprobe: Use guard(rcu_sched_notrace) and check rcu_is_watching()
Mohamad Raizudeen <[email protected]>
crypto: x86/aes-gcm - fix always true check for last AAD segment
Jérémy Jean <[email protected]>
audit: fix exe mark UAF in kill_rules()
Takashi Iwai <[email protected]>
ALSA: usb-audio: Apply IGNORE_CTL_ERROR quirk to all Audient devices
Sean Christopherson <[email protected]>
KVM: x86: Fill kvm_run exit fields in common get_nested_state_pages() error paths
Tibor Harcsa <[email protected]>
Bluetooth: btusb: Add IMC Networks QCA9377 to quirks table
Richard Fitzgerald <[email protected]>
ASoC: sdw_utils: Set snd_soc_dai_link_ch_map.codec_ch_mask for capture
Sean Christopherson <[email protected]>
KVM: x86: Re-pend GET_NESTED_STATE_PAGES if getting said pages fails
Tejun Heo <[email protected]>
sched_ext: Wait for SCX_OPSS_DISPATCHING before reenqueueing a task
fangqiurong <[email protected]>
sched_ext: Don't run ops.dequeue() with a DSQ lock held
Tejun Heo <[email protected]>
sched_ext: Add a size argument to scx_bpf_cid_topo() so struct scx_cid_topo can grow
Tejun Heo <[email protected]>
sched_ext: Build the cid tables privately and publish them with RCU
Chen Yu <[email protected]>
sched/cache: Skip kernel threads for cache aware scheduling to rubustify the code
Tim Chen <[email protected]>
sched/cache: Introduce task_struct->sched_cache_grp to fix UAF
Lu Wang <[email protected]>
sched/cache: Honor migrate_llc_task semantics in active load balance, to fix LLC mis-scheduling bug
Tim Chen <[email protected]>
sched/cache: Keep nr_pref_llc_running in the runnable domain, to fix LLC mis-scheduling bug
Tim Chen <[email protected]>
sched/fair: Avoid creating misfits during cache-aware balancing
Joshua Hahn <[email protected]>
selftests/cgroup: account for zswap shrinker writeback
Heikki Krogerus <[email protected]>
drm/xe/i2c: Keep the i2c controller always enabled
Bryam Vargas <[email protected]>
dm-pcache: bound the logical key offset from persistent memory
Bryam Vargas <[email protected]>
dm-pcache: reject a kset that overruns its segment
-------------
Diffstat:
Documentation/arch/arm64/silicon-errata.rst | 2 + Documentation/filesystems/netfs_library.rst | 26 ++ Makefile | 4 +- arch/arc/include/asm/atomic64-arcv2.h | 6 + arch/arc/include/asm/cmpxchg.h | 4 +- arch/arm64/Kconfig | 30 ++ arch/arm64/kernel/cpu_errata.c | 24 +- arch/arm64/kernel/cpufeature.c | 2 +- arch/arm64/kernel/signal.c | 34 +- arch/arm64/kernel/topology.c | 17 +- arch/arm64/kernel/vdso/Makefile | 2 +- arch/arm64/kvm/emulate-nested.c | 3 - arch/arm64/kvm/hyp/nvhe/pkvm.c | 9 + arch/arm64/kvm/mmu.c | 47 +-- arch/arm64/kvm/vgic/vgic-its.c | 12 +- arch/arm64/kvm/vgic/vgic-v2.c | 6 +- arch/arm64/kvm/vgic/vgic-v3.c | 6 +- arch/arm64/kvm/vgic/vgic.c | 21 +- arch/arm64/mm/mmu.c | 2 +- arch/arm64/net/bpf_jit_comp.c | 37 +- arch/arm64/tools/cpucaps | 2 +- arch/loongarch/net/bpf_jit.c | 60 ++-- arch/loongarch/vdso/Makefile | 1 + arch/powerpc/kernel/vdso/Makefile | 1 + arch/powerpc/net/bpf_jit_comp.c | 45 +-- arch/powerpc/perf/imc-pmu.c | 23 +- arch/riscv/kernel/vdso/Makefile | 1 + arch/riscv/net/bpf_jit_comp64.c | 56 +++- arch/s390/kernel/vdso/Makefile | 1 + arch/s390/net/bpf_jit_comp.c | 46 ++- arch/x86/crypto/aesni-intel_glue.c | 2 +- arch/x86/entry/vdso/vdso64/Makefile | 2 +- arch/x86/kernel/sys_x86_64.c | 15 +- arch/x86/kvm/mmu/mmu.c | 6 + arch/x86/kvm/svm/nested.c | 7 +- arch/x86/kvm/svm/sev.c | 46 ++- arch/x86/kvm/svm/svm.c | 38 +-- arch/x86/kvm/svm/svm.h | 1 + arch/x86/kvm/vmx/nested.c | 21 +- arch/x86/kvm/x86.c | 4 + arch/x86/mm/pgtable.c | 38 +-- arch/x86/net/bpf_jit_comp.c | 26 +- block/blk-cgroup.c | 5 +- block/blk-mq.c | 59 ++-- block/fops.c | 5 + block/mq-deadline.c | 2 +- drivers/android/binder.c | 3 +- drivers/android/binder/node.rs | 20 +- drivers/android/binder/node/wrapper.rs | 34 +- drivers/android/binder/thread.rs | 8 +- drivers/android/binderfs.c | 3 +- drivers/block/drbd/drbd_nl_gen.c | 4 - drivers/block/virtio_blk.c | 1 + drivers/bluetooth/btintel.c | 15 +- drivers/bluetooth/btintel_pcie.c | 12 +- drivers/bluetooth/btusb.c | 2 + drivers/char/tpm/tpm2-cmd.c | 2 +- drivers/char/tpm/tpm2-sessions.c | 1 + drivers/clk/spacemit/ccu-k3.c | 92 +++++ drivers/edac/altera_edac.c | 67 ++-- drivers/edac/versalnet_edac.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c | 13 +- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 2 + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 8 + drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 8 +- drivers/gpu/drm/amd/amdgpu/gfx_v6_0.c | 9 + drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v12_1.c | 2 +- drivers/gpu/drm/amd/amdgpu/sdma_v7_1.c | 4 - drivers/gpu/drm/amd/amdgpu/vi.c | 21 ++ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 103 +++++- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 6 +- drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../dc/link/protocols/link_edp_panel_control.c | 4 +- .../amd/display/dc/resource/dce60/dce60_resource.c | 13 +- .../amd/display/dc/resource/dce80/dce80_resource.c | 2 + drivers/gpu/drm/amd/display/modules/power/power.c | 2 + drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c | 39 +-- .../gpu/drm/i915/display/intel_display_params.c | 4 + .../gpu/drm/i915/display/intel_display_params.h | 1 + drivers/gpu/drm/i915/display/intel_vrr.c | 4 +- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 17 +- drivers/gpu/drm/mediatek/mtk_hdmi_ddc_v2.c | 4 +- drivers/gpu/drm/mediatek/mtk_hdmi_regs_v2.h | 2 +- drivers/gpu/drm/radeon/radeon_bios.c | 6 +- drivers/gpu/drm/xe/xe_i2c.c | 49 ++- drivers/gpu/drm/xe/xe_i2c.h | 1 + drivers/gpu/drm/xe/xe_pci_sriov.c | 30 +- drivers/hid/bpf/hid_bpf_dispatch.c | 2 +- drivers/hid/hid-multitouch.c | 2 +- drivers/i2c/busses/i2c-at91-master.c | 8 +- drivers/i2c/busses/i2c-xiic.c | 61 +++- drivers/iio/accel/kionix-kx022a.c | 30 +- drivers/iio/accel/kxcjk-1013.c | 2 +- drivers/iio/accel/sca3000.c | 2 +- drivers/iio/adc/ad4030.c | 11 +- drivers/iio/adc/ad7173.c | 4 +- drivers/iio/adc/ad_sigma_delta.c | 31 +- drivers/iio/adc/ade9000.c | 36 +- drivers/iio/adc/adi-axi-adc.c | 4 + drivers/iio/adc/aspeed_adc.c | 4 +- drivers/iio/adc/axp288_adc.c | 8 + drivers/iio/adc/max1363.c | 8 + drivers/iio/adc/pac1934.c | 4 + drivers/iio/adc/rohm-bd79124.c | 20 +- drivers/iio/adc/stm32-adc.c | 47 +-- drivers/iio/adc/sun4i-gpadc-iio.c | 10 +- drivers/iio/adc/xilinx-xadc-core.c | 9 +- drivers/iio/buffer/industrialio-buffer-dmaengine.c | 16 +- drivers/iio/cdc/ad7150.c | 8 +- drivers/iio/dac/rohm-bd79703.c | 3 + drivers/iio/frequency/adf4377.c | 4 +- drivers/iio/frequency/admv1013.c | 9 +- drivers/iio/gyro/adis16136.c | 2 +- drivers/iio/health/max30102.c | 12 +- drivers/iio/imu/adis16400.c | 2 +- drivers/iio/imu/adis16480.c | 4 +- drivers/iio/industrialio-buffer.c | 7 +- drivers/iio/industrialio-trigger.c | 2 + drivers/iio/light/gp2ap020a00f.c | 2 + drivers/iio/light/rohm-bu27034.c | 62 ++-- drivers/iio/pressure/bmp280-core.c | 2 +- drivers/iio/pressure/rohm-bm1390.c | 2 +- drivers/iio/proximity/aw96103.c | 30 +- drivers/iio/proximity/isl29501.c | 2 +- drivers/iio/proximity/pulsedlight-lidar-lite-v2.c | 4 +- drivers/iio/proximity/sx9324.c | 2 +- drivers/iio/proximity/vcnl3020.c | 24 +- drivers/iio/proximity/vl53l0x-i2c.c | 3 + drivers/input/keyboard/atkbd.c | 8 + drivers/input/mouse/synaptics.c | 7 +- drivers/input/serio/i8042-acpipnpio.h | 9 + drivers/input/touchscreen/s6sy761.c | 14 +- drivers/md/dm-pcache/cache_gc.c | 5 + drivers/md/dm-pcache/cache_key.c | 14 + drivers/md/dm-pcache/cache_writeback.c | 5 + drivers/mtd/devices/block2mtd.c | 2 +- drivers/mtd/devices/mtd_intel_dg.c | 3 +- drivers/mtd/mtdcore.c | 3 +- drivers/mtd/nand/ecc.c | 7 + drivers/mtd/nand/raw/cadence-nand-controller.c | 6 +- drivers/mtd/nand/raw/vf610_nfc.c | 85 ++++- drivers/mtd/nand/spi/core.c | 53 ++- drivers/mtd/spi-nor/core.c | 2 +- drivers/net/ethernet/broadcom/bcmsysport.c | 8 +- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 34 +- drivers/net/ethernet/broadcom/genet/bcmgenet.h | 2 + drivers/net/ethernet/google/gve/gve_tx_dqo.c | 14 +- drivers/net/ethernet/marvell/mvneta.c | 2 +- drivers/net/ethernet/marvell/octeontx2/af/mcs.c | 4 +- drivers/net/ethernet/marvell/octeontx2/nic/cn20k.c | 11 +- .../ethernet/marvell/octeontx2/nic/otx2_common.c | 18 +- .../ethernet/marvell/octeontx2/nic/otx2_common.h | 9 + drivers/net/ethernet/mediatek/mtk_eth_soc.c | 38 ++- drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c | 3 + drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c | 10 +- .../net/ethernet/microchip/sparx5/sparx5_main.c | 1 + .../net/ethernet/microchip/sparx5/sparx5_main.h | 1 + .../net/ethernet/microchip/sparx5/sparx5_netdev.c | 1 + drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c | 3 + drivers/net/ethernet/microchip/vcap/vcap_api.c | 2 +- drivers/net/ethernet/realtek/r8169_main.c | 6 + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 83 +++-- drivers/net/pcs/pcs-rzn1-miic.c | 3 + drivers/net/pfcp.c | 3 + drivers/net/phy/aquantia/aquantia_main.c | 5 +- drivers/net/phy/qcom/at803x.c | 8 +- drivers/net/usb/qmi_wwan.c | 1 + drivers/net/wireless/ath/ath11k/mac.c | 1 + drivers/net/wireless/ath/ath9k/hif_usb.c | 21 +- drivers/net/wireless/ath/ath9k/htc.h | 1 - drivers/net/wireless/ath/ath9k/htc_drv_init.c | 7 +- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 8 +- drivers/net/wireless/ath/ath9k/wmi.c | 28 +- drivers/net/wireless/ath/ath9k/wmi.h | 1 + drivers/net/wireless/intel/iwlegacy/3945-mac.c | 1 + drivers/net/wireless/silabs/wfx/hif_tx.c | 4 +- drivers/net/wireless/st/cw1200/bh.c | 8 +- drivers/net/wireless/st/cw1200/txrx.c | 14 + drivers/net/wireless/ti/wlcore/main.c | 4 +- drivers/net/xen-netfront.c | 12 +- drivers/nvme/host/core.c | 74 ++-- drivers/nvme/host/multipath.c | 43 +-- drivers/nvme/host/nvme.h | 10 +- drivers/nvme/host/pci.c | 2 + drivers/nvme/target/configfs.c | 9 +- drivers/nvme/target/core.c | 5 +- drivers/nvme/target/fabrics-cmd-auth.c | 2 +- drivers/nvme/target/pci-epf.c | 3 + drivers/of/base.c | 10 +- drivers/of/irq.c | 2 + drivers/of/overlay.c | 17 +- drivers/pci/pci.c | 15 +- drivers/rtc/dev.c | 2 +- drivers/rtc/rtc-ac100.c | 39 +-- drivers/rtc/rtc-mpfs.c | 6 +- drivers/rtc/rtc-spear.c | 11 +- drivers/spi/spi-cs42l43.c | 97 ++++++ drivers/staging/greybus/uart.c | 3 +- drivers/thunderbolt/ctl.c | 63 ++-- drivers/thunderbolt/quirks.c | 3 + drivers/thunderbolt/switch.c | 9 +- drivers/thunderbolt/tb.c | 37 +- drivers/thunderbolt/test.c | 58 +++- drivers/thunderbolt/tunnel.c | 73 ++-- drivers/thunderbolt/tunnel.h | 8 +- drivers/thunderbolt/xdomain.c | 4 + drivers/tty/amiserial.c | 9 +- drivers/tty/n_gsm.c | 47 +-- drivers/tty/serial/8250/8250_bcm7271.c | 2 +- drivers/tty/serial/8250/8250_omap.c | 15 +- drivers/tty/serial/kgdboc.c | 9 + drivers/tty/serial/ma35d1_serial.c | 6 +- drivers/tty/serial/max3100.c | 13 +- drivers/tty/serial/qcom_geni_serial.c | 5 +- drivers/tty/serial/sc16is7xx.c | 53 ++- drivers/tty/serial/serial-tegra.c | 18 +- drivers/tty/serial/serial_core.c | 76 +++-- drivers/tty/serial/vt8500_serial.c | 1 + drivers/tty/tty_io.c | 54 ++- drivers/tty/tty_port.c | 91 +++-- drivers/tty/vcc.c | 5 +- drivers/tty/vt/selection.c | 4 +- drivers/tty/vt/vc_screen.c | 23 +- drivers/tty/vt/vt.c | 5 +- drivers/usb/cdns3/cdns3-gadget.c | 4 + drivers/usb/cdns3/cdns3-pci-wrap.c | 5 + drivers/usb/chipidea/ci_hdrc_tegra.c | 4 +- drivers/usb/class/cdc-acm.c | 41 ++- drivers/usb/class/cdc-acm.h | 1 - drivers/usb/core/hub.c | 7 +- drivers/usb/core/message.c | 8 +- drivers/usb/dwc2/hcd.c | 3 +- drivers/usb/dwc3/core.h | 19 ++ drivers/usb/dwc3/dwc3-am62.c | 1 + drivers/usb/dwc3/ep0.c | 9 + drivers/usb/dwc3/gadget.c | 108 +++++- drivers/usb/gadget/function/f_fs.c | 15 +- drivers/usb/gadget/function/f_midi2.c | 4 +- drivers/usb/gadget/function/f_uac1_legacy.c | 6 + drivers/usb/gadget/udc/aspeed-vhub/core.c | 4 + drivers/usb/gadget/udc/aspeed-vhub/dev.c | 2 +- drivers/usb/gadget/udc/aspeed-vhub/hub.c | 5 +- drivers/usb/gadget/udc/aspeed-vhub/vhub.h | 1 + drivers/usb/gadget/udc/dummy_hcd.c | 4 + drivers/usb/host/octeon-hcd.c | 2 +- drivers/usb/host/ohci-da8xx.c | 2 + drivers/usb/host/ohci-s3c2410.c | 1 + drivers/usb/host/ohci-spear.c | 1 + drivers/usb/host/ohci-st.c | 1 + drivers/usb/serial/bus.c | 6 +- drivers/usb/serial/cp210x.c | 1 + drivers/usb/serial/generic.c | 10 +- drivers/usb/serial/option.c | 14 + drivers/usb/serial/quatech2.c | 19 +- drivers/usb/serial/ssu100.c | 18 +- drivers/usb/serial/usb-serial.c | 127 +++++-- drivers/usb/serial/xr_serial.c | 10 +- drivers/usb/storage/sierra_ms.c | 7 + drivers/usb/typec/anx7411.c | 5 +- drivers/usb/typec/port-mapper.c | 21 +- drivers/usb/typec/tcpm/tcpm.c | 2 +- drivers/usb/typec/tipd/core.c | 11 +- drivers/usb/typec/ucsi/displayport.c | 9 +- drivers/usb/typec/ucsi/ucsi.c | 17 +- drivers/usb/typec/ucsi/ucsi_acpi.c | 34 ++ drivers/usb/typec/ucsi/ucsi_glink.c | 15 +- drivers/virt/nitro_enclaves/ne_misc_dev.c | 1 + drivers/virt/vmgenid.c | 9 +- fs/exec.c | 1 + fs/ext4/inode.c | 3 +- fs/netfs/buffered_read.c | 7 + fs/netfs/buffered_write.c | 9 + fs/netfs/direct_write.c | 9 + fs/netfs/internal.h | 2 + fs/netfs/misc.c | 99 ++++++ fs/netfs/read_collect.c | 24 ++ fs/smb/client/cifsfs.c | 41 ++- fs/smb/client/cifsglob.h | 10 +- fs/smb/client/inode.c | 2 + fs/smb/client/smb2ops.c | 114 +++++-- fs/smb/client/smb2pdu.c | 10 +- include/linux/bpf.h | 45 ++- include/linux/hrtimer_rearm.h | 2 +- include/linux/mtd/nand.h | 2 + include/linux/netfilter_netdev.h | 2 +- include/linux/netfs.h | 2 + include/linux/perf_event.h | 7 +- include/linux/rtnetlink.h | 7 +- include/linux/sched.h | 14 + include/linux/skbuff.h | 2 +- include/linux/soc/qcom/geni-se.h | 15 +- include/linux/tty.h | 1 + include/linux/tty_driver.h | 6 + include/linux/tty_port.h | 22 +- include/linux/usb/serial.h | 1 + include/net/bluetooth/hci_core.h | 5 +- include/net/gso.h | 8 + include/net/netfilter/nf_flow_table.h | 2 +- include/net/sch_generic.h | 9 + include/net/xdp.h | 5 + include/sound/core.h | 9 + include/uapi/linux/random.h | 2 +- init/Kconfig | 5 + io_uring/cmd_net.c | 19 +- io_uring/io_uring.c | 4 +- io_uring/tw.c | 3 + io_uring/zcrx.c | 9 +- kernel/audit_tree.c | 36 +- kernel/bpf/core.c | 10 +- kernel/bpf/hashtab.c | 19 +- kernel/bpf/memalloc.c | 57 +++- kernel/bpf/syscall.c | 19 +- kernel/bpf/trampoline.c | 85 ++++- kernel/events/core.c | 313 ++++++++--------- kernel/events/ring_buffer.c | 7 +- kernel/exit.c | 33 +- kernel/fork.c | 2 + kernel/futex/core.c | 10 +- kernel/kprobes.c | 8 +- kernel/module/main.c | 8 +- kernel/sched/ext/cid.c | 138 +++++--- kernel/sched/ext/cid.h | 2 +- kernel/sched/ext/ext.c | 77 +++-- kernel/sched/ext/types.h | 4 + kernel/sched/fair.c | 372 ++++++++++++++++----- kernel/sysctl.c | 2 +- kernel/time/jiffies.c | 2 + kernel/trace/fprobe.c | 26 +- mm/damon/core.c | 2 +- mm/kasan/common.c | 13 +- mm/shmem.c | 7 +- mm/slab.h | 18 +- mm/slab_common.c | 2 +- mm/slub.c | 37 +- mm/vma.c | 4 +- net/bluetooth/hci_conn.c | 18 +- net/bluetooth/hci_core.c | 54 ++- net/bluetooth/hci_debugfs.c | 2 +- net/bluetooth/hci_sync.c | 19 +- net/bluetooth/rfcomm/tty.c | 7 +- net/bluetooth/smp.c | 2 + net/core/dev.c | 78 +++-- net/core/dev_ioctl.c | 3 +- net/core/gso.c | 1 + net/core/page_pool.c | 2 +- net/core/skbuff.c | 8 +- net/core/sock.c | 4 +- net/ethtool/tsconfig.c | 24 +- net/ipv4/af_inet.c | 3 + net/ipv4/tcp_input.c | 6 + net/ipv6/addrconf.c | 2 +- net/ipv6/ip6_offload.c | 4 + net/ipv6/seg6_iptunnel.c | 2 +- net/ipv6/seg6_local.c | 140 ++++++-- net/mac80211/agg-rx.c | 2 +- net/mac80211/chan.c | 50 ++- net/mac80211/drop.h | 1 + net/mac80211/fils_aead.c | 8 + net/mac80211/ieee80211_i.h | 2 +- net/mac80211/iface.c | 4 +- net/mac80211/mesh_pathtbl.c | 30 +- net/mac80211/mlme.c | 4 +- net/mac80211/rc80211_minstrel_ht.c | 89 ++++- net/mac80211/rx.c | 6 + net/mac80211/spectmgmt.c | 4 +- net/mac80211/sta_info.c | 6 +- net/mac80211/status.c | 70 ++++ net/mac80211/tx.c | 45 ++- net/mctp/device.c | 6 +- net/mptcp/protocol.c | 2 +- net/netfilter/ipset/ip_set_bitmap_gen.h | 2 +- net/netfilter/ipvs/ip_vs_conn.c | 3 + net/netfilter/ipvs/ip_vs_lblc.c | 4 + net/netfilter/ipvs/ip_vs_lblcr.c | 3 + net/netfilter/ipvs/ip_vs_sync.c | 33 +- net/netfilter/nf_flow_table_core.c | 7 +- net/netfilter/nf_flow_table_offload.c | 14 +- net/netfilter/nf_nat_bpf.c | 3 + net/netfilter/nf_nat_core.c | 5 +- net/netfilter/nft_flow_offload.c | 7 +- net/packet/af_packet.c | 3 + net/sched/act_ct.c | 2 +- net/sched/act_skbedit.c | 5 +- net/sched/cls_api.c | 15 +- net/sched/sch_codel.c | 2 +- net/sched/sch_fq_codel.c | 4 +- net/sctp/socket.c | 2 +- net/tipc/crypto.c | 20 +- net/wireless/nl80211.c | 11 +- net/wireless/scan.c | 22 +- rust/kernel/irq/request.rs | 89 +++-- sound/core/seq/seq_compat.c | 4 +- sound/hda/codecs/realtek/alc269.c | 6 +- sound/hda/controllers/tegra.c | 3 +- sound/pci/ctxfi/cthw20k2.c | 2 + sound/pci/ice1712/ice1712.c | 2 +- sound/soc/codecs/lpass-wsa-macro.c | 3 + sound/soc/codecs/max98363.c | 2 +- sound/soc/codecs/rt1017-sdca-sdw.c | 27 +- sound/soc/codecs/rt274.c | 4 +- sound/soc/codecs/rt286.c | 2 +- sound/soc/codecs/wm8903.c | 2 +- sound/soc/qcom/lpass-cpu.c | 4 +- sound/soc/sdca/sdca_class_function.c | 19 +- sound/soc/sdw_utils/soc_sdw_utils.c | 20 +- sound/soc/tegra/tegra186_asrc.c | 2 +- sound/usb/caiaq/device.c | 3 + sound/usb/line6/playback.c | 7 + sound/usb/misc/ua101.c | 9 + sound/usb/quirks.c | 29 +- tools/sched_ext/include/scx/common.bpf.h | 4 +- tools/testing/selftests/cgroup/test_zswap.c | 28 +- 413 files changed, 5137 insertions(+), 2033 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/428 dm-pcache: reject a kset that overruns its segment
7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <[email protected]>
[ Upstream commit 7ac1f10f987a2ffae4aecf0e2ceca8f552b665cb ]
cache_replay(), the writeback worker and the GC worker read a kset of get_kset_onmedia_size() bytes and advance the position by it. A forged key_num makes that size exceed the segment's remaining space, so the advance walks past the segment and trips the cache_pos_advance() BUG_ON.
Reject a kset whose on-media size exceeds cache_seg_remain() before use.
--- drivers/md/dm-pcache/cache_gc.c | 5 +++++ drivers/md/dm-pcache/cache_key.c | 5 +++++ drivers/md/dm-pcache/cache_writeback.c | 5 +++++ 3 files changed, 15 insertions(+)
drivers/md/dm-pcache/cache_gc.c +5 -0
@@ -146,6 +146,11 @@ void pcache_cache_gc_fn(struct work_struct *work)continue ; } +if (get_kset_onmedia_size (kset_onmedia) >cache_seg_remain (&key_tail)) { +atomic_inc (&cache->gc_errors); +return ; + } +for (i =0 ; i < kset_onmedia->key_num; i++) {struct pcache_cache_key key_tmp = {0 };
drivers/md/dm-pcache/cache_key.c +5 -0
@@ -822,6 +822,11 @@ int cache_replay(struct pcache_cache *cache) }/* Replay the kset and check for errors. */ +if (get_kset_onmedia_size (kset_onmedia) >cache_seg_remain (pos)) { + ret = -EIO ; + goto out; + } + ret =kset_replay (cache, kset_onmedia);if (ret) goto out;
drivers/md/dm-pcache/cache_writeback.c +5 -0
@@ -261,6 +261,11 @@ void cache_writeback_fn(struct work_struct *work) goto queue_work; } +if (get_kset_onmedia_size (kset_onmedia) >cache_seg_remain (&dirty_tail)) { +atomic_inc (&cache->writeback_errors); + goto unlock; + } + ret =cache_kset_insert_tree (cache, kset_onmedia);if (ret) {atomic_inc (&cache->writeback_errors);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 2/428 dm-pcache: bound the logical key offset from persistent memory
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <[email protected]>
[ Upstream commit 97fc4b53dbe4a983fdf093243067fa6a64562307 ]
cache_key_decode() takes a key's logical off from the cache device and later indexes req_key_tree->subtrees[] by it in get_subtree(). An off past the device forms a subtree pointer outside the array, which rb_insert() writes through during replay.
Reject a key of zero length, or whose off+len (computed in 64 bits) exceeds the device size, before it is used.
--- drivers/md/dm-pcache/cache_key.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/md/dm-pcache/cache_key.c +9 -0
@@ -90,10 +90,19 @@ int cache_key_decode(struct pcache_cache *cache, struct pcache_cache_key *key) {struct dm_pcache *pcache =CACHE_TO_PCACHE (cache); +u64 dev_bytes = (u64 )cache->dev_size <<SECTOR_SHIFT ; key->off = key_onmedia->off; key->len = key_onmedia->len; +if (key_onmedia->len ==0 || + key_onmedia->len > dev_bytes || + key_onmedia->off > dev_bytes - key_onmedia->len) { +pcache_dev_err (pcache,"key off %llu + len %u exceeds device size\n" , + key_onmedia->off, key_onmedia->len); +return -EIO ; + } +if (!cache_seg_id_valid (cache, key_onmedia->cache_seg_id)) {pcache_dev_err (pcache,"invalid cache_seg_id %u in cache key (n_segs %u)\n" , key_onmedia->cache_seg_id, cache->n_segs);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 3/428 drm/xe/i2c: Keep the i2c controller always enabled
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Heikki Krogerus <[email protected]>
[ Upstream commit 244abef7f280a6a84297bfab5fd2e77147bc419a ]
Some platforms make an assumption that the i2c controller's enabled state indicates also the power state of the controller. This can create a problem when the controller is in disabled state, because the hardware may assume incorrectly that it is then also in low-power state.
To fix this, the controller is kept enabled by taking over the IC_ENABLE register. The controller has to be disabled when the configuration is updated and when the target address or the slave address are assigned, so disabling it when IC_CON, IC_TAR or IC_SAR registers are programmed, and then re-enabling it again.
--- drivers/gpu/drm/xe/xe_i2c.c | 49 ++++++++++++++++++++++++++++++++++++- drivers/gpu/drm/xe/xe_i2c.h | 1 + 2 files changed, 49 insertions(+), 1 deletion(-)
drivers/gpu/drm/xe/xe_i2c.c +48 -1
@@ -8,6 +8,7 @@#include <drm/drm_print.h> #include <linux/array_size.h> #include <linux/container_of.h> +#include <linux/delay.h> #include <linux/device.h> #include <linux/err.h> #include <linux/i2c.h>
@@ -215,11 +216,40 @@ void xe_i2c_irq_postinstall(struct xe_device *xe)xe_mmio_rmw32 (mmio,I2C_CONFIG_CMD ,PCI_COMMAND_INTX_DISABLE ,0 ); } +/* See "Disabling DW_apb_i2c" in the DesignWare DW_abp_i2c databook. */ +static void xe_i2c_disable (struct xe_i2c *i2c) +{ +int timeout =100 ; +u32 status; + +xe_mmio_rmw32 (i2c->mmio,I2C_REG (DW_IC_ENABLE ),DW_IC_ENABLE_ENABLE ,0 ); + +do { + status =xe_mmio_read32 (i2c->mmio,I2C_REG (DW_IC_ENABLE_STATUS )); +if (!(status &DW_IC_ENABLE_ENABLE )) +return ; +/* Can't sleep here. */ +udelay (25 ); + }while (timeout--); + +dev_warn (i2c->drm_dev,"timeout in disabling i2c adapter\n" ); +} +static int xe_i2c_read (void *context,unsigned int reg,unsigned int *val) {struct xe_i2c *i2c = context; - *val =xe_mmio_read32 (i2c->mmio,XE_REG (reg +I2C_MEM_SPACE_OFFSET )); + *val =xe_mmio_read32 (i2c->mmio,I2C_REG (reg)); + +switch (reg) { +case DW_IC_ENABLE : +case DW_IC_ENABLE_STATUS : +FIELD_MODIFY (DW_IC_ENABLE_ENABLE , val, + i2c->ic_enable &DW_IC_ENABLE_ENABLE ); +break ; +default : +break ; + }return 0 ; }
@@ -229,6 +259,23 @@ static int xe_i2c_write(void *context, unsigned int reg, unsigned int val)struct xe_i2c *i2c = context;switch (reg) { +case DW_IC_CON : +case DW_IC_TAR : +case DW_IC_SAR : +/* Disable the controller. */ +xe_i2c_disable (i2c); + +/* Write the register. */ +xe_mmio_write32 (i2c->mmio,I2C_REG (reg), val); + +/* Enable the controller. */ +xe_mmio_rmw32 (i2c->mmio,I2C_REG (DW_IC_ENABLE ),0 ,DW_IC_ENABLE_ENABLE ); +return 0 ; +case DW_IC_ENABLE : + i2c->ic_enable = val; +/* Other fields can be updated except the enable bit. */ + val |=DW_IC_ENABLE_ENABLE ; +break ;case DW_IC_SMBUS_INTR_MASK :/* Make sure the Alert is never masked. */ val |=DW_IC_SMBUS_INTR_ALERT ;
drivers/gpu/drm/xe/xe_i2c.h +1 -0
@@ -37,6 +37,7 @@ struct xe_i2c {struct platform_device *pdev;struct i2c_adapter *adapter;struct i2c_client *client[XE_I2C_MAX_CLIENTS ]; +unsigned int ic_enable;struct notifier_block bus_notifier;struct work_struct work;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 4/428 selftests/cgroup: account for zswap shrinker writeback
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joshua Hahn <[email protected]>
[ Upstream commit 8c7fdc0b4c64d6583fff3e8f7696237a16ff7c29 ]
The test_no_invasive_cgroup_shrink selftest checks that when a cgroup has zswapped out more memory than memory.zswap.max, it does not trigger writeback for other cgroups. To do this, it compares the writeback count in a control cgroup and makes sure that it is 0, and then checks the writeback count in an aggressor cgroup who does expect to see writeback.
However, when the zswap shrinker is enabled, the victim cgroup can see legitimate writebacks not triggered by the aggressor. In some Meta CI tests, we have seen this failure mode happen.
Instead of checking that the victim cgroup has 0 writeback, compare the writeback values before and after the aggressor runs and check that the victim cgroup did not perform any additional writeback. Note that this can still lead to probabilistic failures if writebacks take longer than 5 seconds, but this should fix the systematic failure case and make "not ok test_no_invasive_cgroup_shrink" less likely.
--- tools/testing/selftests/cgroup/test_zswap.c | 28 +++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-)
tools/testing/selftests/cgroup/test_zswap.c +26 -2
@@ -20,6 +20,7 @@ static int page_size;#define PATH_ZSWAP "/sys/module/zswap"#define PATH_ZSWAP_ENABLED "/sys/module/zswap/parameters/enabled" +#define PATH_ZSWAP_SHRINKER_ENABLED "/sys/module/zswap/parameters/shrinker_enabled"static int read_int (const char *path,size_t *value) {
@@ -443,6 +444,16 @@ static int test_zswap_writeback_disabled(const char *root)return test_zswap_writeback (root, false); } +static bool zswap_shrinker_enabled (void ) +{ +char value[2 ]; + +if (read_text (PATH_ZSWAP_SHRINKER_ENABLED , value,sizeof (value)) <=0 ) +return 0 ; + +return value[0 ] =='Y' ; +} +/* * When trying to store a memcg page in zswap, if the memcg hits its memory * limit in zswap, writeback should affect only the zswapped pages of that
@@ -452,6 +463,7 @@ static int test_no_invasive_cgroup_shrink(const char *root) {int ret =KSFT_FAIL ;unsigned int off; +long zswpwb_before, zswpwb_after, zswpwb_target;size_t allocation_size = page_size *1024 ;unsigned int nr_pages = allocation_size / page_size;char zswap_max_buf[32 ], mem_max_buf[32 ];
@@ -487,6 +499,14 @@ static int test_no_invasive_cgroup_shrink(const char *root)if (cg_read_key_long (zw_group,"memory.stat" ,"zswapped" ) <1 ) goto out; +/* If the shrinker is enabled, try to let the writebacks finish first */ +if (zswap_shrinker_enabled ()) +sleep (5 ); + + zswpwb_before =get_cg_wb_count (zw_group); +if (zswpwb_before <0 ) + goto out; +/* Push wb_group memory into zswap with hard-to-compress data to trigger wb */ if (cg_enter_current (wb_group)) goto out;
@@ -499,9 +519,13 @@ static int test_no_invasive_cgroup_shrink(const char *root)getrandom (&wb_allocation[off], page_size/4 ,0 ); } -/* Verify that only zswapped memory from gwb_group has been written back */ -if (wait_for_writeback (wb_group,5000 ) >0 &&get_cg_wb_count (zw_group) ==0 ) +/* Verify that only zswapped memory from wb_group has been written back */ + zswpwb_target =wait_for_writeback (wb_group,5000 ); + zswpwb_after =get_cg_wb_count (zw_group); + +if (zswpwb_target >0 && zswpwb_before == zswpwb_after) ret =KSFT_PASS ; + out:cg_enter_current (root);if (zw_group) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 5/428 sched/fair: Avoid creating misfits during cache-aware balancing
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tim Chen <[email protected]>
[ Upstream commit f0d243a96f2684ad771d678767d17972cf840bd7 ]
Cache-aware load balancing biases tasks toward their preferred LLC. On asymmetric CPU capacity systems (e.g. big.LITTLE) the destination LLC may contain CPUs that are too small to run the task. Pulling the task there turns it into a misfit, trading a cache-locality gain for a capacity loss that's more detrimental to performance.
Guard both cache-aware migration entry points against this:
- can_migrate_llc_task(): forbid the LLC migration when the task fits its source CPU but would not fit the destination CPU.
- alb_break_llc(): veto the active balance under the same condition so the runnable task is not pushed onto a CPU that cannot accommodate it.
Both checks are gated with checks for hybrid processors, so symmetric systems are unaffected. Tasks that already do not fit their source CPU are left to the existing LLC policy, since the move cannot make their fitness worse (this also preserves misfit up-migration to bigger CPUs).
Additionally, if there are misfit tasks found in the load balancing classification phase, prioritize misfit task migrations over LLC load aggregation on asymmetric systems. A better fitting CPU will boost performance more than better cache locality.
Stable-dep-of: d6013e2465d9 ("sched/cache: Honor migrate_llc_task semantics in active load balance, to fix LLC mis-scheduling bug")
--- kernel/sched/fair.c | 50 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-)
kernel/sched/fair.c +45 -5
@@ -10651,18 +10651,41 @@ static enum llc_mig can_migrate_llc(int src_cpu, int dst_cpu,return mig_llc; } +static inline bool task_misfits_asym_cpu (struct lb_env *env,struct task_struct *p) +{ +/* +* On asymmetric CPU capacity domains, do not let cache-aware +* balancing pull the task onto a destination CPU that cannot +* accommodate it. Doing so would turn the task into a misfit on +* the destination, trading a cache-locality gain for a capacity +* loss. If the task already does not fit its source CPU, the move +* cannot make things worse, so let the LLC preference decide. +*/ +if ((env->sd->flags &SD_ASYM_CPUCAPACITY ) && p && + !task_fits_cpu (p, env->dst_cpu) && +task_fits_cpu (p, env->src_cpu)) +return true; + +return false; +} +/* * Check if task p can migrate from source LLC to * destination LLC in terms of cache aware load balance. */ -static enum llc_mig can_migrate_llc_task (int src_cpu,int dst_cpu, +static enum llc_mig can_migrate_llc_task (struct lb_env *env,struct task_struct *p) {struct sched_cache_group *grp;struct mm_struct *mm;bool to_pref; -int cpu; +int cpu, src_cpu, dst_cpu; + +if (task_misfits_asym_cpu (env, p)) +return mig_forbid; + src_cpu = env->src_cpu; + dst_cpu = env->dst_cpu; mm = p->mm;if (!mm)return mig_unrestricted;
@@ -10723,6 +10746,14 @@ alb_break_llc(struct lb_env *env)unsigned long util =0 ;struct task_struct *cur; +/* +* Migrating misfit tasks from current CPU +* to CPU with a better fit. +* Prioritize that over LLC preference. +*/ +if (env->migration_type == migrate_misfit) +return false; +if (env->src_rq->nr_running <=1 )return true;
@@ -10730,7 +10761,8 @@ alb_break_llc(struct lb_env *env)if (cur && cur->sched_class == &fair_sched_class) util =task_util (cur); -if (can_migrate_llc (env->src_cpu, env->dst_cpu, +if (task_misfits_asym_cpu (env, cur) || +can_migrate_llc (env->src_cpu, env->dst_cpu, util, false) == mig_forbid)return true; }
@@ -10770,8 +10802,7 @@ static bool migrate_degrades_llc(struct task_struct *p, struct lb_env *env) READ_ONCE(p->preferred_llc) != llc_id(env->dst_cpu))return true; -if (can_migrate_llc_task (env->src_cpu, - env->dst_cpu, p) != mig_forbid) +if (can_migrate_llc_task (env, p) != mig_forbid)return false;return true;
@@ -11834,6 +11865,15 @@ static inline bool llc_balance(struct lb_env *env, struct sg_lb_stats *sgs,if (env->sd->flags &SD_SHARE_LLC )return false; +/* +* On asymmetric domains, group_misfit_task_load +* should be prioritized to move tasks to CPU that fit them +* over aggregating tasks to their preferred LLC. +*/ +if ((env->sd->flags &SD_ASYM_CPUCAPACITY ) && + sgs->group_misfit_task_load) +return false; +/* * Skip cache aware tagging if nr_balanced_failed is sufficiently high. * Threshold of cache_nice_tries is set to 1 higher than nr_balance_failed
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 6/428 sched/cache: Keep nr_pref_llc_running in the runnable domain, to fix LLC mis-scheduling bug
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tim Chen <[email protected]>
[ Upstream commit 0d6526f82c3cdefcca47f73f5fc08dc6f335eac6 ]
alb_break_llc() decides whether to break LLC preference during active load balance. It does so by testing that every runnable fair task on the source rq prefers its LLC:
env->src_rq->nr_pref_llc_running == env->src_rq->cfs.h_nr_runnable
But the two counters cover different sets. nr_pref_llc_running is updated in account_llc_enqueue()/account_llc_dequeue(), next to cfs_rq->nr_queued, so it follows queued tasks. h_nr_runnable is updated in set_delayed()/ clear_delayed() and drops delay-dequeued tasks.
So under DELAY_DEQUEUE, a preferring task that goes to sleep stays counted in nr_pref_llc_running while h_nr_runnable falls. The equality then breaks, alb_break_llc() returns false, and active balance is free to pull a task off its preferred LLC. Active balance only moves runnable tasks, and this is the only LLC check it consults: once the stopper runs, LBF_ACTIVE_LB skips the per-task test in can_migrate_task(). The runnable set is the one we want.
Fix it on the counter side. A task should be counted in nr_pref_llc_running exactly while it is both queued on its preferred LLC (pref_llc_queued) and runnable (!sched_delayed). Define that membership once in task_pref_llc_runnable(), and adjust the counter only through pref_llc_running_inc()/pref_llc_running_dec() from the four sites that change either input: account_llc_enqueue(), account_llc_dequeue(), set_delayed() and clear_delayed(). Gating every update on the same predicate keeps the delay, wake and dequeue paths from double-counting or underflowing; see the comments at those sites for the ordering.
nr_llc_running and sd->llc_counts are not touched and stay on queued semantics.
--- kernel/sched/fair.c | 63 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 5 deletions(-)
kernel/sched/fair.c +58 -5
@@ -1517,6 +1517,28 @@ static bool invalid_llc_nr(struct mm_struct *mm, struct task_struct *p, (scale * per_cpu(sd_llc_size, cpu))); } +/* +* A task counts in nr_pref_llc_running while it is queued on its preferred +* LLC (pref_llc_queued) and runnable (!sched_delayed), keeping the counter in +* the runnable domain so alb_break_llc() can compare it with h_nr_runnable. +*/ +static bool task_pref_llc_runnable (struct task_struct *p) +{ +return p->pref_llc_queued && !p->se.sched_delayed; +} + +static void pref_llc_running_inc (struct rq *rq,struct task_struct *p) +{ +if (task_pref_llc_runnable (p)) + rq->nr_pref_llc_running++; +} + +static void pref_llc_running_dec (struct rq *rq,struct task_struct *p) +{ +if (task_pref_llc_runnable (p)) + rq->nr_pref_llc_running--; +} +static void account_llc_enqueue (struct rq *rq,struct task_struct *p) {int pref_llc, pref_llc_queued;
@@ -1528,7 +1550,6 @@ static void account_llc_enqueue(struct rq *rq, struct task_struct *p) pref_llc_queued = (pref_llc ==task_llc (p)); rq->nr_llc_running++; - rq->nr_pref_llc_running += pref_llc_queued;/* * Record whether p is enqueued on its preferred
@@ -1546,6 +1567,9 @@ static void account_llc_enqueue(struct rq *rq, struct task_struct *p)*/ p->pref_llc_queued = pref_llc_queued; +/* Skipped while delayed; clear_delayed() adds it back on wake. */ +pref_llc_running_inc (rq, p); + sd =rcu_dereference_all (rq->sd);if (sd && (unsigned int )pref_llc < sd->llc_max) sd->llc_counts[pref_llc]++;
@@ -1562,7 +1586,12 @@ static void account_llc_dequeue(struct rq *rq, struct task_struct *p) rq->nr_llc_running--;if (p->pref_llc_queued) { - rq->nr_pref_llc_running--; +/* +* Skipped if still delayed (set_delayed() already removed it); +* clearing pref_llc_queued below also stops clear_delayed() +* from re-adding it. +*/ +pref_llc_running_dec (rq, p);/* * Update the status in case * other logic might query
@@ -2027,6 +2056,7 @@ void init_sched_mm(struct task_struct *p)* polluting account_llc_enqueue(). */ p->preferred_llc =-1 ; + p->pref_llc_queued = 0; }#else /* CONFIG_SCHED_CACHE */
@@ -2048,6 +2078,10 @@ static void account_llc_enqueue(struct rq *rq, struct task_struct *p) {}static void account_llc_dequeue (struct rq *rq,struct task_struct *p) {} +static void pref_llc_running_inc (struct rq *rq,struct task_struct *p) {} + +static void pref_llc_running_dec (struct rq *rq,struct task_struct *p) {} +#endif /* CONFIG_SCHED_CACHE */ /*
@@ -6278,15 +6312,27 @@ static __always_inline void return_cfs_rq_runtime(struct cfs_rq *cfs_rq);static void set_delayed (struct sched_entity *se) { - se->sched_delayed =1 ; -/* * Delayed se of cfs_rq have no tasks queued on them. * Do not adjust h_nr_runnable since dequeue_entities() * will account it for blocked tasks. +* +* This check can be removed because when flat pick +* patches get merged as only task can get delayed, +* same for clear_delayed(). */ -if (!entity_is_task (se)) +if (!entity_is_task (se)) { + se->sched_delayed =1 ;return ; + } + +/* +* Drop a task leaving the runnable set. +* Needs to be called before sched_delayed is set. +* clear_delayed() mirrors this after clearing the flag. +*/ +pref_llc_running_dec (rq_of (cfs_rq_of (se)),task_of (se)); + se->sched_delayed =1 ;for_each_sched_entity (se) {struct cfs_rq *cfs_rq =cfs_rq_of (se);
@@ -6308,6 +6354,13 @@ static void clear_delayed(struct sched_entity *se)if (!entity_is_task (se))return ; +/* +* Re-add on wake, after sched_delayed is cleared. On a final delayed +* dequeue account_llc_dequeue() already cleared pref_llc_queued, so +* this does nothing. +*/ +pref_llc_running_inc (rq_of (cfs_rq_of (se)),task_of (se)); +for_each_sched_entity (se) {struct cfs_rq *cfs_rq =cfs_rq_of (se);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 7/428 sched/cache: Honor migrate_llc_task semantics in active load balance, to fix LLC mis-scheduling bug
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lu Wang <[email protected]>
[ Upstream commit d6013e2465d98d524b030a81c1223882a1bb7e4c ]
Cache aware scheduling introduced the migrate_llc_task migration type to direct tasks toward their preferred LLC, but its semantics can be lost when passive load balance falls back to active load balance (ALB). This may allow ALB to select a candidate whose preferred LLC does not match the destination, moving it away from its preferred LLC.
Example scenario:
src_rq has two runnable tasks, p1 and p2. p1 prefers dst_rq (dst_llc), while p2 prefers src_rq (src_llc). In this case, migrate_llc_task is set because src_rq has at least one task, p1, that wants to migrate to dst_rq. In ALB, can_migrate_task() finds p2 and returns true for it, thus moving p2 out of its preferred LLC.
Solution:
The CPU stopper in ALB constructs a fresh lb_env that does not inherit migration_type from the passive load-balance pass. Two approaches are possible:
(a) Add a new member to struct rq so ALB can inherit migrate_llc_task from the passive LB that triggered it.
(b) Define a new flag LBF_ACTIVE_LB_LLC and select the stopper callback at kick time to preserve the migration semantics across the asynchronous boundary.
We choose (b) because it avoids passing migration_type through the stopper, which would affect the meaning of migration_type for delayed-dequeue tasks.
--- kernel/sched/fair.c | 57 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 6 deletions(-)
kernel/sched/fair.c +51 -6
@@ -10395,6 +10395,7 @@ enum migration_type {#define LBF_SOME_PINNED 0x08#define LBF_ACTIVE_LB 0x10#define LBF_LLC_PINNED 0x20 +#define LBF_ACTIVE_LB_LLC 0x40struct lb_env {struct sched_domain *sd;
@@ -10823,6 +10824,21 @@ alb_break_llc(struct lb_env *env)return false; } +/* +* Returns true if p's preferred LLC does not match the destination CPU +* under migrate_llc_task semantics. Passive LB passes migrate_llc_task +* in env->migration_type, while active LB carries LBF_ACTIVE_LB_LLC in +* env->flags to avoid overwriting env->migration_type. +*/ +static inline bool +migrate_llc_task_wrong_dst (struct task_struct *p,struct lb_env *env) +{ +return sched_cache_enabled () && + (env->migration_type == migrate_llc_task || + env->flags &LBF_ACTIVE_LB_LLC ) && +READ_ONCE (p->preferred_llc) !=llc_id (env->dst_cpu); +} +/* * Check if migrating task p from env->src_cpu to * env->dst_cpu breaks LLC localiy.
@@ -10851,8 +10867,7 @@ static bool migrate_degrades_llc(struct task_struct *p, struct lb_env *env)* run on env->dst_cpu, skip the tasks do not prefer * env->dst_cpu, and find the one that prefers. */ -if (env->migration_type == migrate_llc_task && -READ_ONCE (p->preferred_llc) !=llc_id (env->dst_cpu)) +if (migrate_llc_task_wrong_dst (p, env))return true;if (can_migrate_llc_task (env, p) != mig_forbid)
@@ -10874,6 +10889,12 @@ alb_break_llc(struct lb_env *env)return false; } +static inline bool +migrate_llc_task_wrong_dst (struct task_struct *p,struct lb_env *env) +{ +return false; +} +static inline bool migrate_degrades_llc (struct task_struct *p,struct lb_env *env) {
@@ -10973,7 +10994,7 @@ int can_migrate_task(struct task_struct *p, struct lb_env *env)* 4) too many balance attempts have failed. */ if (env->flags &LBF_ACTIVE_LB ) -return 1 ; +return !migrate_llc_task_wrong_dst (p, env); degrades =migrate_degrades_locality (p, env);if (!degrades) {
@@ -13344,6 +13365,20 @@ static int need_active_balance(struct lb_env *env) }static int active_load_balance_cpu_stop (void *data); +static int active_load_balance_llc_cpu_stop (void *data); + +/* +* migration_type is checked elsewhere to decide migration policy, so +* it shouldn't be repurposed just to flag an LLC-directed active +* balance across the stopper. Pick the callback here instead. +*/ +static inline cpu_stop_fn_t alb_stop_fn (struct lb_env *env) +{ +if (env->migration_type == migrate_llc_task) +return active_load_balance_llc_cpu_stop; + +return active_load_balance_cpu_stop; +}static int should_we_balance (struct lb_env *env) {
@@ -13680,7 +13715,7 @@ static int sched_balance_rq(int this_cpu, struct rq *this_rq,raw_spin_rq_unlock_irqrestore (busiest, flags);if (active_balance) {stop_one_cpu_nowait (cpu_of (busiest), - active_load_balance_cpu_stop, busiest, +alb_stop_fn (&env), busiest, &busiest->active_balance_work); }preempt_enable ();
@@ -13791,7 +13826,7 @@ update_next_balance(struct sched_domain *sd, unsigned long *next_balance)* least 1 task to be running on each physical CPU where possible, and * avoids physical / logical imbalances. */ -static int active_load_balance_cpu_stop (void *data) +static int __active_load_balance_cpu_stop (void *data,unsigned int lb_flags) {struct rq *busiest_rq = data;int busiest_cpu =cpu_of (busiest_rq);
@@ -13841,7 +13876,7 @@ static int active_load_balance_cpu_stop(void *data) .src_cpu = busiest_rq->cpu, .src_rq = busiest_rq, .idle = CPU_IDLE, - .flags = LBF_ACTIVE_LB, + .flags = LBF_ACTIVE_LB | lb_flags, };schedstat_inc (sd->alb_count);
@@ -13869,6 +13904,16 @@ static int active_load_balance_cpu_stop(void *data)return 0 ; } +static int active_load_balance_cpu_stop (void *data) +{ +return __active_load_balance_cpu_stop (data,0 ); +} + +static int active_load_balance_llc_cpu_stop (void *data) +{ +return __active_load_balance_cpu_stop (data,LBF_ACTIVE_LB_LLC ); +} +/* * Scale the max sched_balance_rq interval with the number of CPUs in the system. * This trades load-balance latency on larger machines for less cross talk.
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 8/428 sched/cache: Introduce task_struct->sched_cache_grp to fix UAF
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tim Chen <[email protected]>
[ Upstream commit b636fef85bda7d1bab9c0a45067ab1508d79d946 ]
Add a sched_cache_grp pointer to task_struct so that scheduler code can access the cache group directly via the task, without going through mm->sched_cache_grp. This decouples the scheduler's hot-path accesses from the mm_struct.
Each task holds its own refcount on the sched_cache_group, separate from the reference held by its mm_struct. The reference is acquired in copy_mm() (fork) and exec_mmap() (exec), and released in exit_mm(). This fixes the use-after-free when account_mm_sched() reaches the group through a task whose mm is being switched, as reported by Hyunwoo:
https://lore.kernel.org/lkml/apPb-Dr4nPYuHQOK@v4bel/
Convert all scheduler code in fair.c and exit.c to use p->sched_cache_grp instead of p->mm->sched_cache_grp.
Keep the fork/exec/exit reference management out of the generic mm
paths: add sched_cache_fork(), sched_cache_fork_cleanup(), sched_cache_exec_mmap() and sched_cache_exit_mm() in kernel/sched/cache_sched.c (with empty stubs for !CONFIG_SCHED_CACHE), so fs/exec.c, kernel/fork.c and kernel/exit.c each call one helper instead of open-coding the refcounting under #ifdef. Also add sched_cache_group_get() and task_cache_group_get().
--- fs/exec.c | 1 + include/linux/sched.h | 14 +++ kernel/exit.c | 33 +------ kernel/fork.c | 2 + kernel/sched/fair.c | 196 +++++++++++++++++++++++++++++------------- 5 files changed, 154 insertions(+), 92 deletions(-)
fs/exec.c +1 -0
@@ -882,6 +882,7 @@ static int exec_mmap(struct linux_binprm *bprm) active_mm = tsk->active_mm; tsk->active_mm = mm; tsk->mm = mm; +sched_cache_exec_mmap (tsk, mm);mm_init_cid (mm, tsk); exec_state =task_exec_state_replace (tsk, exec_state);/*
include/linux/sched.h +14 -0
@@ -1421,6 +1421,7 @@ struct task_struct {#ifdef CONFIG_SCHED_CACHE struct callback_head cache_work; +struct sched_cache_group __rcu *sched_cache_grp;int preferred_llc;/* 1: task was enqueued to its preferred LLC, 0 otherwise */ int pref_llc_queued;
@@ -2410,10 +2411,23 @@ struct sched_cache_group {struct rcu_head rcu; } ____cacheline_aligned_in_smp; +struct sched_cache_group *sched_cache_group_get (struct sched_cache_group *grp); +struct sched_cache_group *task_cache_group_get (struct task_struct *p); + +void sched_cache_fork (struct task_struct *p); +void sched_cache_fork_cleanup (struct task_struct *p); +void sched_cache_exec_mmap (struct task_struct *p,struct mm_struct *mm); +void sched_cache_exit_mm (struct task_struct *p); +#else struct sched_cache_group { }; +static inline void sched_cache_fork (struct task_struct *p) { } +static inline void sched_cache_fork_cleanup (struct task_struct *p) { } +static inline void sched_cache_exec_mmap (struct task_struct *p,struct mm_struct *mm) { } +static inline void sched_cache_exit_mm (struct task_struct *p) { } +#endif #ifndef MODULE
kernel/exit.c +1 -32
@@ -552,37 +552,6 @@ void mm_update_next_owner(struct mm_struct *mm) }#endif /* CONFIG_MEMCG */ -#if defined(CONFIG_SCHED_CACHE ) && defined(CONFIG_NUMA_BALANCING ) -/* -* Subtract the memory footprint of the current task from -* mm. -*/ -static void exit_mm_sched_cache (struct mm_struct *mm) -{ -struct sched_cache_group *grp; -unsigned long fp, sub; - -if (!current->total_numa_faults) -return ; -/* -* No lock protection due to performance considerations. -* Make sure the group footprint does not become -* negative. -*/ - grp =READ_ONCE (mm->sched_cache_grp); -if (!grp) -return ; - - fp =READ_ONCE (grp->footprint); - sub =min (fp, current->total_numa_faults); -WRITE_ONCE (grp->footprint, fp - sub); -} -#else -static inline void exit_mm_sched_cache (struct mm_struct *mm) -{ -} -#endif /* CONFIG_SCHED_CACHE CONFIG_NUMA_BALANCING */ -/* * Turn us into a lazy TLB process if we * aren't already..
@@ -595,7 +564,7 @@ static void exit_mm(void)if (!mm)return ; -exit_mm_sched_cache (mm); +sched_cache_exit_mm (current);mmap_read_lock (mm);mmgrab_lazy_tlb (mm);
kernel/fork.c +2 -0
@@ -1598,6 +1598,7 @@ static int copy_mm(u64 clone_flags, struct task_struct *tsk) tsk->mm = mm; tsk->active_mm = mm; +sched_cache_fork (tsk);return 0 ; }
@@ -2583,6 +2584,7 @@ __latent_entropy struct task_struct *copy_process( bad_fork_cleanup_namespaces:exit_nsproxy_namespaces (p); bad_fork_cleanup_mm: +sched_cache_fork_cleanup (p);if (p->mm) {mm_clear_owner (p->mm, p);mmput (p->mm);
kernel/sched/fair.c +136 -60
347 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 9/428 sched/cache: Skip kernel threads for cache aware scheduling to rubustify the code
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen Yu <[email protected]>
[ Upstream commit 65efcccddc83d6a19e8a2e2a6117811e39e589bf ]
Kernel thread should not be covered by cache aware scheduling as it borrows the statistics from the user space thread. Filter the kernel thread in account_mm_sched().
In theory a kernel thread does not have any valid cache group, so !grp should gate the kernel thread. Add the PF_KTHREAD check explicitly here for safety reasons, to guard against future modifications and to pair with task_tick_cache().
--- kernel/sched/fair.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
kernel/sched/fair.c +8 -2
@@ -1868,8 +1868,14 @@ void account_mm_sched(struct rq *rq, struct task_struct *p, s64 delta_exec)/* * init_task, kthreads and user thread created * by user_mode_thread() don't have a cache group. -*/ -if (!grp || !grp->pcpu_sched) +* In theory a kernel thread does not have any valid +* cache group, because sched_cache_fork() is not +* invoked for a kernel thread - !grp should gate the +* kernel thread. Use the PF_KTHREAD check explicitly +* here for safety reasons, to guard against future +* modifications and to pair with task_tick_cache(). +*/ +if (p->flags &PF_KTHREAD || !grp || !grp->pcpu_sched)return ; pcpu_sched =per_cpu_ptr (grp->pcpu_sched,cpu_of (rq));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 10/428 sched_ext: Build the cid tables privately and publish them with RCU
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tejun Heo <[email protected]>
[ Upstream commit 3a773220d39ba993dfe5d135f8b610be10794d5d ]
The cid tables are visible to the cid kfuncs while being modified: the first enable publishes the global pointers before filling them, ops.init_cids() overrides rewrite them in place, and re-enables rebuild them in place. A racing TRACING or SYSCALL program can read unfilled entries, including uninitialized memory in the kmalloc'd tables, or torn topo updates.
Tie the tables' lifetimes to the root sched instead: each root enable builds a fresh set privately and publishes the per-table __rcu globals once the layout is final, and root disable unpublishes and RCU-frees the set. A non-NULL global is now always a fully built table which stays valid for the reader's RCU read section, and lookups stay two loads. Kfuncs treat NULL as no-mapping, also after the scheduler exits instead of reporting the stale last mapping.
The cid kfuncs are available whether the root scheduler is cid-form or cpu-form, the latter to allow gradual migration to cids. Every root therefore builds and publishes a default mapping.
Every reader must either be gated on scheduler liveness or NULL-check inside an RCU read section. Fix the two kfuncs that were neither:scx_bpf_this_cid() read the table with no RCU or preemption protection and scx_bpf_task_cid() relied on KF_RCU, which doesn't put a sleepable program in an RCU read section. The hotplug callbacks are instead serialized by retiring the tables inside the cpus_read_lock() section that clears scx_root.
v2: Document why every root builds the tables (desc + cid.c comment).
[ Stable dependency adaptation for 94480606a677:
Limit private construction and RCU publication to scx_cid_topo, the table read by the target. 7.2 has no cid shards or sub.c and permits overrides from ops.init(), not ops.init_cids(). Keep its existing cpu<->cid arrays and callback interface. Build a fresh topology table on every enable and override, publish only complete tables, and revoke the table on root disable. Reclaim replaced tables after synchronize_rcu(), outside the override's read-side critical section. Reuse existing functions; omit upstream's new allocation/publication/free helpers and shard changes.
Publish the default topology before ops.init() and override replacements before returning, preserving topology queries during this callback. Allocation and validation failures release unpublished temporary tables.
Also fold in the existing-function/prototype changes from b38332be61a8 (sched_ext: Make scx_bpf_kick_cid() return void). This matches the adjacent context in the target's common.bpf.h hunk; in-tree callers do not consume the return value. The target applies cleanly with a three-way application. This dependency does not change scx_bpf_cid_topo()'s signature. ]
[ sashal: Reduced backport -- upstream 3a773220d39ba touches 5 file(s), this
backport carries 4. Not backported here:
kernel/sched/ext/internal.h
kernel/sched/ext/sub.c
This note is generated from the file lists only; see the resolution record for the reasoning. ]
Stable-dep-of: 94480606a677 ("sched_ext: Add a size argument to scx_bpf_cid_topo() so struct scx_cid_topo can grow")
--- kernel/sched/ext/cid.c | 114 ++++++++++++++--------- kernel/sched/ext/cid.h | 2 +- kernel/sched/ext/ext.c | 19 ++-- tools/sched_ext/include/scx/common.bpf.h | 2 +- 4 files changed, 83 insertions(+), 54 deletions(-)
kernel/sched/ext/cid.c +68 -46
@@ -13,14 +13,15 @@/* * cid tables. * -* Pointers are published once on first enable and never revoked. The default -* mapping is populated before ops.init() runs; scx_bpf_cid_override() commits -* before it returns. As long as the BPF scheduler only uses the tables from -* those points onward, it sees a consistent view. +* The cpu<->cid arrays are allocated once and populated before ops.init(). +* The topology table is built privately and published with RCU, including +* when ops.init() overrides the mapping. Published topology tables are never +* modified and are retired after an RCU grace period. Root disable revokes +* the topology table, so readers must check for NULL. */ s16 *scx_cid_to_cpu_tbl;s16 *scx_cpu_to_cid_tbl; -struct scx_cid_topo *scx_cid_topo; +struct scx_cid_topo __rcu *scx_cid_topo;#define SCX_CID_TOPO_NEG (struct scx_cid_topo) { \ .core_cid = -1, .core_idx = -1, .llc_cid = -1, .llc_idx = -1, \
@@ -43,30 +44,26 @@ static const struct cpumask *cpu_llc_mask(int cpu, struct cpumask *fallbacks)return &ci->info_list[ci->num_leaves -1 ].shared_cpu_map; } -/* Allocate the cid tables once on first enable; never freed. */ +/* Allocate the cpu<->cid arrays once on first enable; never freed. */ static s32 scx_cid_arrays_alloc (void ) {u32 npossible =num_possible_cpus ();s16 *cid_to_cpu, *cpu_to_cid; -struct scx_cid_topo *cid_topo;if (scx_cid_to_cpu_tbl)return 0 ; cid_to_cpu =kzalloc_objs (*scx_cid_to_cpu_tbl, npossible,GFP_KERNEL ); cpu_to_cid =kzalloc_objs (*scx_cpu_to_cid_tbl, nr_cpu_ids,GFP_KERNEL ); - cid_topo =kmalloc_objs (*scx_cid_topo, npossible,GFP_KERNEL ); -if (!cid_to_cpu || !cpu_to_cid || !cid_topo) { +if (!cid_to_cpu || !cpu_to_cid) {kfree (cid_to_cpu);kfree (cpu_to_cid); -kfree (cid_topo);return -ENOMEM ; }WRITE_ONCE (scx_cid_to_cpu_tbl, cid_to_cpu);WRITE_ONCE (scx_cpu_to_cid_tbl, cpu_to_cid); -WRITE_ONCE (scx_cid_topo, cid_topo);return 0 ; }
@@ -88,6 +85,8 @@ s32 scx_cid_init(struct scx_sched *sch) cpumask_var_t core_scratch __free(free_cpumask_var) = CPUMASK_VAR_NULL; cpumask_var_t llc_fallback __free(free_cpumask_var) = CPUMASK_VAR_NULL; cpumask_var_t online_no_topo __free(free_cpumask_var) = CPUMASK_VAR_NULL; + struct scx_cid_topo *topo __free(kfree) = NULL; +struct scx_cid_topo *old_topo;u32 next_cid =0 ;s32 next_node_idx =0 , next_llc_idx =0 , next_core_idx =0 ;s32 cpu, ret;
@@ -101,6 +100,10 @@ s32 scx_cid_init(struct scx_sched *sch)if (ret)return ret; + topo =kmalloc_objs (*topo,num_possible_cpus (),GFP_KERNEL ); +if (!topo) +return -ENOMEM ; + if (!zalloc_cpumask_var(&to_walk, GFP_KERNEL) || !zalloc_cpumask_var(&node_scratch, GFP_KERNEL) || !zalloc_cpumask_var(&llc_scratch, GFP_KERNEL) ||
@@ -165,7 +168,7 @@ s32 scx_cid_init(struct scx_sched *sch) scx_cid_to_cpu_tbl[cid] = ccpu; scx_cpu_to_cid_tbl[ccpu] = cid; - scx_cid_topo[cid] = (struct scx_cid_topo ){ + topo[cid] = (struct scx_cid_topo ){ .core_cid = core_cid, .core_idx = core_idx, .llc_cid = llc_cid,
@@ -198,7 +201,7 @@ s32 scx_cid_init(struct scx_sched *sch) cid = next_cid++; scx_cid_to_cpu_tbl[cid] = cpu; scx_cpu_to_cid_tbl[cpu] = cid; - scx_cid_topo[cid] =SCX_CID_TOPO_NEG ; + topo[cid] =SCX_CID_TOPO_NEG ; }if (!cpumask_empty (llc_fallback))
@@ -208,6 +211,13 @@ s32 scx_cid_init(struct scx_sched *sch)pr_warn ("scx_cid: online cpus with no usable topology: %*pbl\n" ,cpumask_pr_args (online_no_topo)); +/* Root enable and ops.init() serialize topology table updates. */ + old_topo =rcu_replace_pointer (scx_cid_topo,no_free_ptr (topo), true); +if (old_topo) { +synchronize_rcu (); +kfree (old_topo); + } +return 0 ; }
@@ -291,51 +301,60 @@ __bpf_kfunc void scx_bpf_cid_override(const s32 *cpu_to_cid, u32 cpu_to_cid__sz, const struct bpf_prog_aux *aux) { cpumask_var_t seen __free(free_cpumask_var) = CPUMASK_VAR_NULL; + struct scx_cid_topo *topo __free(kfree) = NULL; +struct scx_cid_topo *old_topo;struct scx_sched *sch;bool alloced;s32 cpu, cid;/* GFP_KERNEL alloc must happen before the rcu read section */ alloced =zalloc_cpumask_var (&seen,GFP_KERNEL ); + topo =kmalloc_objs (*topo,num_possible_cpus (),GFP_KERNEL ); -guard (rcu)(); - - sch =scx_prog_sched (aux); -if (unlikely (!sch)) -return ; +scoped_guard (rcu) { + sch =scx_prog_sched (aux); +if (unlikely (!sch)) +return ; -if (!alloced) { -scx_error (sch,"scx_bpf_cid_override: failed to allocate cpumask" ); -return ; - } +if (!alloced || !topo) { +scx_error (sch,"scx_bpf_cid_override: failed to allocate tables" ); +return ; + } -if (scx_parent (sch)) { -scx_error (sch,"scx_bpf_cid_override() only allowed from root sched" ); -return ; - } +if (scx_parent (sch)) { +scx_error (sch,"scx_bpf_cid_override() only allowed from root sched" ); +return ; + } -if (cpu_to_cid__sz != nr_cpu_ids *sizeof (s32)) { -scx_error (sch,"scx_bpf_cid_override: expected %zu bytes, got %u" , - nr_cpu_ids *sizeof (s32), cpu_to_cid__sz); -return ; - } +if (cpu_to_cid__sz != nr_cpu_ids *sizeof (s32)) { +scx_error (sch,"scx_bpf_cid_override: expected %zu bytes, got %u" , + nr_cpu_ids *sizeof (s32), cpu_to_cid__sz); +return ; + } -for_each_possible_cpu (cpu) { -s32 c = cpu_to_cid[cpu]; +for_each_possible_cpu (cpu) { +s32 c = cpu_to_cid[cpu]; -if (!cid_valid (sch, c)) -return ; -if (cpumask_test_and_set_cpu (c, seen)) { -scx_error (sch,"cid %d assigned to multiple cpus" , c); -return ; +if (!cid_valid (sch, c)) +return ; +if (cpumask_test_and_set_cpu (c, seen)) { +scx_error (sch,"cid %d assigned to multiple cpus" , c); +return ; + } + scx_cpu_to_cid_tbl[cpu] = c; + scx_cid_to_cpu_tbl[c] = cpu; } - scx_cpu_to_cid_tbl[cpu] = c; - scx_cid_to_cpu_tbl[c] = cpu; + +/* The override carries no topology. Publish a complete replacement. */ +for (cid =0 ; cid <num_possible_cpus (); cid++) + topo[cid] =SCX_CID_TOPO_NEG ; + + old_topo =rcu_replace_pointer (scx_cid_topo,no_free_ptr (topo), true); } -/* Invalidate stale topo info - the override carries no topology. */ -for (cid =0 ; cid <num_possible_cpus (); cid++) - scx_cid_topo[cid] =SCX_CID_TOPO_NEG ; +/* This sleepable kfunc must leave its RCU read section before waiting. */ +synchronize_rcu (); +kfree (old_topo); }/**
@@ -660,22 +679,25 @@ bool scx_cmask_empty(const struct scx_cmask *m)* * Fill @out__uninit with the topology info for @cid. Trigger scx_error() if * @cid is out of range. If @cid is valid but in the no-topo section, all fields -* are set to -1. +* are set to -1. All fields are also set to -1 when no cid tables have been +* published yet, which a program may observe while racing the root enable. */ __bpf_kfunc void scx_bpf_cid_topo(s32 cid, struct scx_cid_topo *out__uninit,const struct bpf_prog_aux *aux) { +struct scx_cid_topo *topo;struct scx_sched *sch;guard (rcu)(); sch =scx_prog_sched (aux); -if (unlikely (!sch) || !cid_valid (sch, cid)) { + topo =rcu_dereference (scx_cid_topo); +if (unlikely (!sch) || !cid_valid (sch, cid) ||unlikely (!topo)) { *out__uninit =SCX_CID_TOPO_NEG ;return ; } - *out__uninit =READ_ONCE (scx_cid_topo)[cid]; + *out__uninit = topo[cid]; }__bpf_kfunc_end_defs ();
kernel/sched/ext/cid.h +1 -1
@@ -50,7 +50,7 @@ struct scx_sched;*/ extern s16 *scx_cid_to_cpu_tbl;extern s16 *scx_cpu_to_cid_tbl; -extern struct scx_cid_topo *scx_cid_topo; +extern struct scx_cid_topo __rcu *scx_cid_topo;extern struct btf_id_set8 scx_kfunc_ids_init;void scx_cmask_clear (struct scx_cmask *m);
kernel/sched/ext/ext.c +13 -6
@@ -6221,6 +6221,7 @@ static inline void scx_sub_disable(struct scx_sched *sch) { }static void scx_root_disable (struct scx_sched *sch) { +struct scx_cid_topo *topo;struct scx_task_iter sti;struct task_struct *p;bool was_switched_all;
@@ -6350,8 +6351,15 @@ static void scx_root_disable(struct scx_sched *sch)*/ cpus_read_lock ();RCU_INIT_POINTER (scx_root,NULL ); + topo =rcu_replace_pointer (scx_cid_topo,NULL , +lockdep_is_held (&scx_enable_mutex));cpus_read_unlock (); +if (topo) { +synchronize_rcu (); +kfree (topo); + } +/* * Delete the kobject from the hierarchy synchronously. Otherwise, sysfs * could observe an object of the same name still in the hierarchy when
@@ -9625,10 +9633,10 @@ __bpf_kfunc void scx_bpf_kick_cpu(s32 cpu, u64 flags, const struct bpf_prog_aux* @flags: %SCX_KICK_* flags * @aux: implicit BPF argument to access bpf_prog_aux hidden from BPF progs * -* cid-addressed equivalent of scx_bpf_kick_cpu(). Return 0 on success, -* -errno otherwise. +* cid-addressed equivalent of scx_bpf_kick_cpu(). An invalid @cid aborts the +* scheduler via scx_cid_to_cpu(). */ -__bpf_kfunc s32 scx_bpf_kick_cid(s32 cid, u64 flags, const struct bpf_prog_aux *aux) +__bpf_kfunc void scx_bpf_kick_cid(s32 cid, u64 flags, const struct bpf_prog_aux *aux) {struct scx_sched *sch;s32 cpu;
@@ -9636,12 +9644,11 @@ __bpf_kfunc s32 scx_bpf_kick_cid(s32 cid, u64 flags, const struct bpf_prog_aux *guard (rcu)(); sch =scx_prog_sched (aux);if (unlikely (!sch)) -return -ENODEV ; +return ; cpu =scx_cid_to_cpu (sch, cid);if (cpu <0 ) -return cpu; +return ;scx_kick_cpu (sch, cpu, flags); -return 0 ; }/**
tools/sched_ext/include/scx/common.bpf.h +1 -1
@@ -105,7 +105,7 @@ void scx_bpf_events(struct scx_event_stats *events, size_t events__sz) __ksym __ s32 scx_bpf_cpu_to_cid(s32 cpu) __ksym __weak; s32 scx_bpf_cid_to_cpu(s32 cid) __ksym __weak; void scx_bpf_cid_topo(s32 cid, struct scx_cid_topo *out) __ksym __weak; -s32 scx_bpf_kick_cid(s32 cid, u64 flags) __ksym __weak; +void scx_bpf_kick_cid(s32 cid, u64 flags) __ksym __weak; s32 scx_bpf_task_cid(const struct task_struct *p) __ksym __weak; s32 scx_bpf_this_cid(void) __ksym __weak;struct task_struct *scx_bpf_cid_curr (s32 cid) __ksym__weak ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 11/428 sched_ext: Add a size argument to scx_bpf_cid_topo() so struct scx_cid_topo can grow
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tejun Heo <[email protected]>
[ Upstream commit 94480606a677deb68d5622cf0ded88626514b3f2 ]
scx_bpf_cid_topo() copies struct scx_cid_topo into a buffer the BPF program sized from its own vmlinux.h while the verifier sizes the write from the running kernel's BTF. The struct may grow and each growth then breaks every scheduler built against the older layout, rejected at load or written past its buffer. This is the usual hole for a struct handed to BPF, closed elsewhere with a size argument, and it was missed here.
Take the buffer size, copy the smaller of it and the kernel's struct and set the rest to -1. Accesses to the copy are CO-RE relocated, so the struct can grow by appending fields, which its comment now states. The kfunc changes in
place: the cid interface is still being finalized and no released scheduler uses the current form.
--- kernel/sched/ext/cid.c | 26 +++++++++++++++--------- kernel/sched/ext/types.h | 4 ++++ tools/sched_ext/include/scx/common.bpf.h | 2 +- 3 files changed, 21 insertions(+), 11 deletions(-)
kernel/sched/ext/cid.c +16 -10
@@ -674,30 +674,36 @@ bool scx_cmask_empty(const struct scx_cmask *m)/** * scx_bpf_cid_topo - Copy out per-cid topology info * @cid: cid to look up -* @out__uninit: where to copy the topology info; fully written by this call +* @out: where to copy the topology info +* @out__sz: size of @out, the program's sizeof(struct scx_cid_topo) * @aux: implicit BPF argument to access bpf_prog_aux hidden from BPF progs * -* Fill @out__uninit with the topology info for @cid. Trigger scx_error() if -* @cid is out of range. If @cid is valid but in the no-topo section, all fields -* are set to -1. All fields are also set to -1 when no cid tables have been -* published yet, which a program may observe while racing the root enable. +* Fill @out with the topology info for @cid. Trigger scx_error() if @cid is out +* of range. If @cid is valid but in the no-topo section, all fields are set to +* -1. All fields are also set to -1 when no cid tables have been published yet, +* which a program may observe while racing the root enable. +* +* The program's struct may be older or newer than the kernel's. The smaller of +* @out__sz and the kernel's size is copied and the rest of @out is set to -1. */ -__bpf_kfunc void scx_bpf_cid_topo(s32 cid, struct scx_cid_topo *out__uninit, +__bpf_kfunc void scx_bpf_cid_topo(s32 cid, struct scx_cid_topo *out, size_t out__sz,const struct bpf_prog_aux *aux) { +size_t len =min (out__sz,sizeof (*out));struct scx_cid_topo *topo;struct scx_sched *sch; +/* the error cases and fields the kernel lacks read as -1 */ +memset (out,0xff , out__sz); +guard (rcu)(); sch =scx_prog_sched (aux); topo =rcu_dereference (scx_cid_topo); -if (unlikely (!sch) || !cid_valid (sch, cid) ||unlikely (!topo)) { - *out__uninit =SCX_CID_TOPO_NEG ; +if (unlikely (!sch) || !cid_valid (sch, cid) ||unlikely (!topo))return ; - } - *out__uninit = topo[cid]; +memcpy (out, &topo[cid], len); }__bpf_kfunc_end_defs ();
kernel/sched/ext/types.h +4 -0
@@ -53,6 +53,10 @@ enum scx_consts {* over [0, nr_cores_at_init) with no gaps. No-topo cids have all fields set * to -1. * +* New fields are appended, never inserted: scx_bpf_cid_topo() copies this +* struct out sized by the program's own layout, and an older program's copy +* must stay a prefix of the kernel's. +* * @core_cid: first cid of this cid's core (smt-sibling group) * @core_idx: global index of that core, in [0, nr_cores_at_init) * @llc_cid: first cid of this cid's LLC
tools/sched_ext/include/scx/common.bpf.h +1 -1
@@ -104,7 +104,7 @@ u64 scx_bpf_now(void) __ksym __weak; void scx_bpf_events(struct scx_event_stats *events, size_t events__sz) __ksym __weak; s32 scx_bpf_cpu_to_cid(s32 cpu) __ksym __weak; s32 scx_bpf_cid_to_cpu(s32 cid) __ksym __weak; -void scx_bpf_cid_topo(s32 cid, struct scx_cid_topo *out) __ksym __weak; +void scx_bpf_cid_topo(s32 cid, struct scx_cid_topo *out, size_t out__sz) __ksym __weak; void scx_bpf_kick_cid(s32 cid, u64 flags) __ksym __weak; s32 scx_bpf_task_cid(const struct task_struct *p) __ksym __weak; s32 scx_bpf_this_cid(void) __ksym __weak;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 12/428 sched_ext: Dont run ops.dequeue() with a DSQ lock held
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: fangqiurong <[email protected]>
[ Upstream commit cb86607ada73185f321baa7f9d94a08a3a40bbf5 ]
ops.dequeue() is invoked with the source user DSQ's lock still held on the consume and move paths (scx_consume_dispatch_q(), move_task_between_dsqs()). A BPF scheduler which locks the source user DSQ from ops.dequeue() - e.g. by iterating it with bpf_iter_scx_dsq - self-deadlocks.
ops.dequeue() can only call the "any" kfuncs and none of them can lock a builtin DSQ, so the global and bypass paths can't deadlock; however, all DSQ locks share one lockdep class, so iterating any user DSQ from ops.dequeue() on those paths trips the recursion check.
Move the invocation after the DSQ unlock on all three paths. SCX_TASK_IN_CUSTODY is cleared under the lock serializing the transfer so that the callback is invoked exactly once.
--- kernel/sched/ext/ext.c | 48 +++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 22 deletions(-)
kernel/sched/ext/ext.c +26 -22
@@ -1450,20 +1450,14 @@ static inline bool task_scx_migrating(struct task_struct *p)return p->scx.sticky_cpu >=0 ; } -/* -* Call ops.dequeue() if the task is in BPF custody and not migrating. -* Clears %SCX_TASK_IN_CUSTODY when the callback is invoked. -*/ -static void call_task_dequeue (struct scx_sched *sch,struct rq *rq, -struct task_struct *p,u64 deq_flags) +/* Must be called under the lock serializing @p's custody transfers. */ +static bool task_leave_custody (struct task_struct *p) {if (!(p->scx.flags &SCX_TASK_IN_CUSTODY ) ||task_scx_migrating (p)) -return ; - -if (SCX_HAS_OP (sch, dequeue)) -SCX_CALL_OP_TASK (sch, dequeue, rq, p, deq_flags); +return false; p->scx.flags &= ~SCX_TASK_IN_CUSTODY ; +return true; } static void local_dsq_post_enq(struct scx_sched *sch, struct scx_dispatch_q *dsq,
@@ -1471,7 +1465,8 @@ static void local_dsq_post_enq(struct scx_sched *sch, struct scx_dispatch_q *dsq { struct rq *rq = container_of(dsq, struct rq, scx.local_dsq); -call_task_dequeue (sch, rq, p,0 ); +if (task_leave_custody (p) &&SCX_HAS_OP (sch, dequeue)) +SCX_CALL_OP_TASK (sch, dequeue, rq, p,0 );/* * Note that @rq's lock may be dropped between this enqueue and @p
@@ -1634,16 +1629,28 @@ static void dispatch_enqueue(struct scx_sched *sch, struct rq *rq,if (is_local) {local_dsq_post_enq (sch, dsq, p, enq_flags); }else { +bool call_dequeue = false; +/* -* Task on global/bypass DSQ: leave custody, task on -* non-terminal DSQ: enter custody. +* Global and bypass DSQs are terminal - the task leaves the +* scheduler's custody, so ops.dequeue() fires. It can run +* without @p's rq lock (finish_dispatch() passes the dispatch +* rq); that's safe because dequeue_task_scx() waits on +* SCX_OPSS_DISPATCHING (see the ops_state note above) and so +* can't race it. A non-terminal DSQ keeps the task in custody. +* The custody transfer happens under @dsq->lock so that later +* consumers see the flag clear; the callback runs after +* @dsq->lock is dropped because it may lock a DSQ itself. */ if (dsq->id ==SCX_DSQ_GLOBAL || dsq->id ==SCX_DSQ_BYPASS ) -call_task_dequeue (sch, rq, p,0 ); + call_dequeue =task_leave_custody (p);else p->scx.flags |=SCX_TASK_IN_CUSTODY ;raw_spin_unlock (&dsq->lock); + +if (call_dequeue &&SCX_HAS_OP (sch, dequeue)) +SCX_CALL_OP_TASK (sch, dequeue, rq, p,0 ); }/*
@@ -2111,7 +2118,7 @@ static void ops_dequeue(struct rq *rq, struct task_struct *p, u64 deq_flags)/* * A queued task must always be in BPF scheduler's custody. If * SCX_TASK_IN_CUSTODY is clear, finish_dispatch() on another -* CPU has already passed call_task_dequeue() (which clears the +* CPU has already passed task_leave_custody() (which clears the * flag), but has not yet written SCX_OPSS_NONE. That final * store does not require this rq's lock, so retrying with * cpu_relax() is bounded: we will observe NONE (or DISPATCHING,
@@ -2159,7 +2166,8 @@ static void ops_dequeue(struct rq *rq, struct task_struct *p, u64 deq_flags)* NONE but the task may still have %SCX_TASK_IN_CUSTODY set until * it is enqueued on the destination. */ -call_task_dequeue (sch, rq, p, deq_flags); +if (task_leave_custody (p) &&SCX_HAS_OP (sch, dequeue)) +SCX_CALL_OP_TASK (sch, dequeue, rq, p, deq_flags); }static bool dequeue_task_scx (struct rq *rq,struct task_struct *p,int core_deq_flags)
@@ -2263,13 +2271,10 @@ static void wakeup_preempt_scx(struct rq *rq, struct task_struct *p, int wake_flstatic void move_local_task_to_local_dsq (struct scx_sched *sch,struct task_struct *p,u64 enq_flags, -struct scx_dispatch_q *src_dsq,struct rq *dst_rq) {struct scx_dispatch_q *dst_dsq = &dst_rq->scx.local_dsq; -/* @dsq is locked and @p is on @dst_rq */ -lockdep_assert_held (&src_dsq->lock);lockdep_assert_rq_held (dst_rq);WARN_ON_ONCE (p->scx.holding_cpu >=0 );
@@ -2513,9 +2518,8 @@ static struct rq *move_task_between_dsqs(struct scx_sched *sch,/* @p is going from a non-local DSQ to a local DSQ */ if (src_rq == dst_rq) {task_unlink_from_dsq (p, src_dsq); -move_local_task_to_local_dsq (sch, p, enq_flags, - src_dsq, dst_rq);raw_spin_unlock (&src_dsq->lock); +move_local_task_to_local_dsq (sch, p, enq_flags, dst_rq); }else {raw_spin_unlock (&src_dsq->lock); move_remote_task_to_local_dsq(p, enq_flags,
@@ -2566,8 +2570,8 @@ static bool consume_dispatch_q(struct scx_sched *sch, struct rq *rq,if (rq == task_rq) {task_unlink_from_dsq (p, dsq); -move_local_task_to_local_dsq (sch, p, enq_flags, dsq, rq);raw_spin_unlock (&dsq->lock); +move_local_task_to_local_dsq (sch, p, enq_flags, rq);return true; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 13/428 sched_ext: Wait for SCX_OPSS_DISPATCHING before reenqueueing a task
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tejun Heo <[email protected]>
[ Upstream commit 7de9a6fb44eae4f05e68c805d58b9c618815adfa ]
ebf1ccff79c4 ("sched_ext: Fix ops.dequeue() semantics") moved the final ops_state store in scx_dispatch_enqueue() after the DSQ unlock so that the custody update and ops.dequeue() precede it. A task can thus be found on a DSQ while still SCX_OPSS_DISPATCHING.
The dequeue and core-sched pick paths wait for the state to clear in ops_dequeue() but the reenqueue paths don't. A reenqueue in that window runs ops.enqueue() and sets SCX_OPSS_QUEUED before the dispatch has completed. The dispatcher's final store then overwrites it with SCX_OPSS_NONE and finish_dispatch() drops every later dispatch of the task.
Wait for SCX_OPSS_DISPATCHING to clear before dequeueing a task for reenqueue, the same way ops_dequeue() does.
--- kernel/sched/ext/ext.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
kernel/sched/ext/ext.c +10 -0
@@ -4294,6 +4294,14 @@ static u32 reenq_local(struct scx_sched *sch, struct rq *rq, u64 reenq_flags)if (!local_task_should_reenq (p, &reenq_flags, &reason))continue ; +/* +* The dispatcher stores the final ops_state after dropping the DSQ +* lock, so @p can be found on a DSQ while still +* %SCX_OPSS_DISPATCHING. Reenqueueing @p before that store lands +* would have it clobber the new %SCX_OPSS_QUEUED. +*/ +if (unlikely (atomic_long_read_acquire (&p->scx.ops_state) ==SCX_OPSS_DISPATCHING )) +wait_ops_state (p,SCX_OPSS_DISPATCHING );dispatch_dequeue (rq, p);if (WARN_ON_ONCE (p->scx.flags &SCX_TASK_REENQ_REASON_MASK ))
@@ -4416,6 +4424,8 @@ static void reenq_user(struct rq *rq, struct scx_dispatch_q *dsq, u64 reenq_flag }/* @p is on @dsq, its rq and @dsq are locked */ +if (unlikely (atomic_long_read_acquire (&p->scx.ops_state) ==SCX_OPSS_DISPATCHING )) +wait_ops_state (p,SCX_OPSS_DISPATCHING );dispatch_dequeue_locked (p, dsq);raw_spin_unlock (&dsq->lock);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 14/428 KVM: x86: Re-pend GET_NESTED_STATE_PAGES if getting said pages fails
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
[ Upstream commit 10180a277549339020b08000206092c07e0bff5a ]
Re-pend GET_NESTED_STATE_PAGES before exiting to userspace if getting the nested pages fails in the KVM_RUN path. If userspace re-runs the vCPU, and vmcs02 holds valid PFNs from the *previous* run of L2, then KVM could re-enter L2 with stale, unpinned PFNs mapped into e.g. the vAPIC page.
Note, both SVM and VMX (as of commit 11722439fb20 ("KVM: nVMX: Ensure KVM_REQ_GET_NESTED_STATE_PAGES is cleared on VM-Exit") ensure the request is cleared on VM-Exit (including the "forced" case), i.e. there is no risk of double-mapping due to emulated VMLAUNCH/VMRESUME/VMRUN *and* the request trying to map the nested pages.
--- arch/x86/kvm/x86.c | 1 + 1 file changed, 1 insertion(+)
arch/x86/kvm/x86.c +1 -0
@@ -10694,6 +10694,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)if (kvm_check_request (KVM_REQ_GET_NESTED_STATE_PAGES , vcpu)) {if (unlikely (!kvm_nested_call (get_nested_state_pages)(vcpu))) { +kvm_make_request (KVM_REQ_GET_NESTED_STATE_PAGES , vcpu); r =0 ; goto out; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 15/428 ASoC: sdw_utils: Set snd_soc_dai_link_ch_map.codec_ch_mask for capture
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Richard Fitzgerald <[email protected]>
[ Upstream commit 290845e151cd4e307cc1f25319583aaceb4eeb30 ]
In asoc_sdw_hw_params() set the codec_ch_mask member of struct snd_soc_dai_link_ch_map for capture streams. ASoC will then pass the correct number of channels to each codec hw_params(). This prevents trying to enable more channels on the codec DP than have been allocated bitslots in the SoundWire frame, which would cause bus clash errors.
In theory codec_ch_mask could also be set for playback streams, but for those the CPU is the only sender so there is no risk of bus clash. For playback streams codec_ch_mask is set to 0 to preserve the existing behavior and avoid introducing bugs.
--- sound/soc/sdw_utils/soc_sdw_utils.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-)
sound/soc/sdw_utils/soc_sdw_utils.c +14 -6
@@ -1510,7 +1510,7 @@ int asoc_sdw_hw_params(struct snd_pcm_substream *substream,struct snd_soc_pcm_runtime *rtd =snd_soc_substream_to_rtd (substream);struct snd_soc_dai_link_ch_map *ch_maps;int ch =params_channels (params); -unsigned int ch_mask; +unsigned int cpu_ch_mask, codec_ch_mask;int num_codecs;int step;int i;
@@ -1520,8 +1520,9 @@ int asoc_sdw_hw_params(struct snd_pcm_substream *substream,/* Identical data will be sent to all codecs in playback */ if (substream->stream ==SNDRV_PCM_STREAM_PLAYBACK ) { - ch_mask =GENMASK (ch -1 ,0 ); + cpu_ch_mask =GENMASK (ch -1 ,0 ); step =0 ; + codec_ch_mask =0 ; }else { num_codecs = rtd->dai_link->num_codecs;
@@ -1531,17 +1532,24 @@ int asoc_sdw_hw_params(struct snd_pcm_substream *substream,return -EINVAL ; } - ch_mask =GENMASK (ch / num_codecs -1 ,0 ); - step =hweight_long (ch_mask); + cpu_ch_mask =GENMASK (ch / num_codecs -1 ,0 ); + step =hweight_long (cpu_ch_mask); + codec_ch_mask = cpu_ch_mask; }/* * The captured data will be combined from each cpu DAI if the dai * link has more than one codec DAIs. Set codec channel mask and * ASoC will set the corresponding channel numbers for each cpu dai. +* +* sdw_stream_add_slave() assigns different payload offsets to each +* codec in a capture stream, so that the same channels on each +* codec map to different channels on the CPU. */ -for_each_link_ch_maps (rtd->dai_link, i, ch_maps) - ch_maps->cpu_ch_mask = ch_mask << (i * step); +for_each_link_ch_maps (rtd->dai_link, i, ch_maps) { + ch_maps->cpu_ch_mask = cpu_ch_mask << (i * step); + ch_maps->codec_ch_mask = codec_ch_mask; + }return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 16/428 Bluetooth: btusb: Add IMC Networks QCA9377 to quirks table
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tibor Harcsa <[email protected]>
[ Upstream commit dc16388d45ecbd3be0d8c9424dbbaa2c81806578 ]
Add the USB ID (13d3:3503) for the IMC Networks Qualcomm Atheros QCA9377 Bluetooth controller to the btusb quirks table. This device requires Qualcomm Rome firmware and wideband speech support to function properly; otherwise, BLE scanning fails with HCI unexpected event opcode 0x2005 errors.
The device reports the following in /sys/kernel/debug/usb/devices:
P: Vendor=13d3 ProdID=3503 Rev= 0.01
C:* #Ifs= 2 Cfg#= 1 Atr=e0 MxPwr=100mA
I:* If#= 0 Alt= 0 #EPs= 3 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb
E: Ad=81(I) Atr=03(Int.) MxPS= 16 Ivl=1ms E: Ad=82(I) Atr=02(Bulk) MxPS= 64 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 64 Ivl=0ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 0 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 0 Ivl=1ms I: If#= 1 Alt= 1 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 9 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 9 Ivl=1ms I: If#= 1 Alt= 2 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 17 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 17 Ivl=1ms I: If#= 1 Alt= 3 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 25 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 25 Ivl=1ms I: If#= 1 Alt= 4 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 33 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 33 Ivl=1ms I: If#= 1 Alt= 5 #EPs= 2 Cls=e0(wlcon) Sub=01 Prot=01 Driver=btusb E: Ad=83(I) Atr=01(Isoc) MxPS= 49 Ivl=1ms E: Ad=03(O) Atr=01(Isoc) MxPS= 49 Ivl=1ms
--- drivers/bluetooth/btusb.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/bluetooth/btusb.c +2 -0
@@ -308,6 +308,8 @@ static const struct usb_device_id quirks_table[] = { BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x13d3, 0x3501), .driver_info = BTUSB_QCA_ROME | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x13d3, 0x3503), .driver_info = BTUSB_QCA_ROME | + BTUSB_WIDEBAND_SPEECH }, /* QCA WCN6855 chipset */ { USB_DEVICE(0x0489, 0xe0c7), .driver_info = BTUSB_QCA_WCN6855 |
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 17/428 KVM: x86: Fill kvm_run exit fields in common get_nested_state_pages() error paths
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
[ Upstream commit c1214f293d77c6e425a379f90d09bdb4815993a8 ]
Fill kvm_run with "internal error, emulation" in the common error handling paths for getting nested state pages, as requiring each check to manually fill kvm_run is error prone and requires a non-trivial amount of copy+paste.
Specifically, both SVM and VMX fail to fill kvm_run if load_pdptrs() fails, and SVM fails to fill kvm_run if kvm_hv_verify_vp_assist() fails. If those flows fail, the *best* case scenario is that KVM will exit to userspace with KVM_EXIT_UNKNOWN. The worst case scenario is that KVM exits with a stale exit_reason and confuses userspace.
Note, SVM never exits to userspace if something goes sideways when dealing with vmcb12 assets while emulating VMRUN, i.e. lack of SVM-specific code is not a bug.
--- arch/x86/kvm/svm/nested.c | 7 +------ arch/x86/kvm/vmx/nested.c | 15 +++++---------- arch/x86/kvm/x86.c | 3 +++ 3 files changed, 9 insertions(+), 16 deletions(-)
arch/x86/kvm/svm/nested.c +1 -6
@@ -2131,13 +2131,8 @@ static bool svm_get_nested_state_pages(struct kvm_vcpu *vcpu)return false; } -if (!nested_svm_merge_msrpm (vcpu)) { - vcpu->run->exit_reason =KVM_EXIT_INTERNAL_ERROR ; - vcpu->run->internal.suberror = -KVM_INTERNAL_ERROR_EMULATION ; - vcpu->run->internal.ndata =0 ; +if (!nested_svm_merge_msrpm (vcpu))return false; - }if (kvm_hv_verify_vp_assist (vcpu))return false;
arch/x86/kvm/vmx/nested.c +5 -10
@@ -3469,10 +3469,6 @@ static bool nested_get_vmcs12_pages(struct kvm_vcpu *vcpu) }else {pr_debug_ratelimited ("%s: no backing for APIC-access address in vmcs12\n" , __func__); - vcpu->run->exit_reason =KVM_EXIT_INTERNAL_ERROR ; - vcpu->run->internal.suberror = -KVM_INTERNAL_ERROR_EMULATION ; - vcpu->run->internal.ndata =0 ;return false; } }
@@ -3543,11 +3539,6 @@ static bool vmx_get_nested_state_pages(struct kvm_vcpu *vcpu)if (!nested_get_evmcs_page (vcpu)) {pr_debug_ratelimited ("%s: enlightened vmptrld failed\n" , __func__); - vcpu->run->exit_reason =KVM_EXIT_INTERNAL_ERROR ; - vcpu->run->internal.suberror = -KVM_INTERNAL_ERROR_EMULATION ; - vcpu->run->internal.ndata =0 ; -return false; }#endif
@@ -3919,8 +3910,12 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch) vmentry_failed: vcpu->arch.nested_run_pending =0 ; -if (status ==NVMX_VMENTRY_KVM_INTERNAL_ERROR ) +if (status ==NVMX_VMENTRY_KVM_INTERNAL_ERROR ) { + vcpu->run->exit_reason =KVM_EXIT_INTERNAL_ERROR ; + vcpu->run->internal.suberror =KVM_INTERNAL_ERROR_EMULATION ; + vcpu->run->internal.ndata =0 ;return 0 ; + }if (status ==NVMX_VMENTRY_VMEXIT )return 1 ;WARN_ON_ONCE (status !=NVMX_VMENTRY_VMFAIL );
arch/x86/kvm/x86.c +3 -0
@@ -10694,6 +10694,9 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)if (kvm_check_request (KVM_REQ_GET_NESTED_STATE_PAGES , vcpu)) {if (unlikely (!kvm_nested_call (get_nested_state_pages)(vcpu))) { + vcpu->run->exit_reason =KVM_EXIT_INTERNAL_ERROR ; + vcpu->run->internal.suberror =KVM_INTERNAL_ERROR_EMULATION ; + vcpu->run->internal.ndata =0 ;kvm_make_request (KVM_REQ_GET_NESTED_STATE_PAGES , vcpu); r =0 ; goto out;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 18/428 ALSA: usb-audio: Apply IGNORE_CTL_ERROR quirk to all Audient devices
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
[ Upstream commit a154f7b9f197b3d5e41fa3ad62083f5aa93b1fe8 ]
Faaris reported a problem with Audient EVO4 device and it turned out to be a regression by the recent fix commit 87a6f2fa6e6c ("ALSA:
usb-audio: Propagate write errors in generic mixer put callbacks"). It exhibited that the hardware gives errors at accessing the mixer unit 10 on certain channels, and the change above made it a fatal error.
We had already a quirk for Audient iD14 to work around such errors from the mixer controls, and we can simply apply the same for EVO4. OTOH, it's highly possible that other Audient devices suffer from the same issue; they must be using similar firmware, after all.
So, in this patch, we apply the quirk generically to all devices with the vendor ID Audient (2708), instead. Ignoring the control error isn't usually less critical than overreaction to the firmware misbehavior.
--- sound/usb/quirks.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
sound/usb/quirks.c +2 -2
@@ -2478,8 +2478,6 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { QUIRK_FLAG_FORCE_IFACE_RESET | QUIRK_FLAG_IFACE_DELAY),DEVICE_FLG (0x262a ,0x9302 ,/* ddHiFi TC44C */ QUIRK_FLAG_DSD_RAW ), -DEVICE_FLG (0x2708 ,0x0002 ,/* Audient iD14 */ -QUIRK_FLAG_IGNORE_CTL_ERROR ),DEVICE_FLG (0x2772 ,0x0502 ,/* Musical Fidelity M6s DAC */ 0 ),/* for avoiding QUIRK_FLAG_DSD_RAW with vendor match */ DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */
@@ -2576,6 +2574,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = { QUIRK_FLAG_DSD_RAW),VENDOR_FLG (0x2622 ,/* IAG Limited devices */ QUIRK_FLAG_DSD_RAW ), +VENDOR_FLG (0x2708 ,/* Audient devices */ +QUIRK_FLAG_IGNORE_CTL_ERROR ),VENDOR_FLG (0x2772 ,/* Musical Fidelity devices */ QUIRK_FLAG_DSD_RAW ), VENDOR_FLG(0x278b, /* Rotel? */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 19/428 audit: fix exe mark UAF in kill_rules()
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jérémy Jean <[email protected]>
commit aa650d87a498844060eecb1d336f4d46f4d1b0b3 upstream.
kill_rules() removes mixed AUDIT_DIR and AUDIT_EXE rules when an audit tree is pruned. It drops entry->rule.exe before removing the rule from the RCU-visible filter lists.
After a rule has been installed with AUDIT_ADD_RULE, which requires CAP_AUDIT_CONTROL, removing the watched directory can race with another task that is still evaluating the rule. In that case, fsnotify can free the executable mark before the reader reaches audit_mark_compare(), causing a use-after-free.
KASAN reports:
BUG: KASAN: slab-use-after-free in audit_mark_compare+0x8d/0xa0
Unlink the published rules from the RCU-visible lists and retain them on tree->rules for cleanup. If any rule has an executable mark, wait for a single RCU grace period before removing the marks and scheduling the entries for freeing. Otherwise, call_rcu() already provides the required deferred freeing without a synchronous wait.
--- kernel/audit_tree.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-)
kernel/audit_tree.c +20 -4
@@ -545,22 +545,38 @@ static void kill_rules(struct audit_cont {struct audit_krule *rule, *next;struct audit_entry *entry; +bool need_sync = false;list_for_each_entry_safe (rule, next, &tree->rules, rlist) { entry = container_of(rule, struct audit_entry, rule); -list_del_init (&rule->rlist);if (rule->tree) {/* not a half-baked one */ audit_tree_log_remove_rule (context, rule); -if (entry->rule.exe) -audit_remove_mark (entry->rule.exe); rule->tree =NULL ;list_del_rcu (&entry->list);list_del (&entry->rule.list); -call_rcu (&entry->rcu, audit_free_rule_rcu); +if (entry->rule.exe) + need_sync = true; + }else { +list_del_init (&rule->rlist); } } + +if (list_empty (&tree->rules)) +return ; + +if (need_sync) +synchronize_rcu (); + +list_for_each_entry_safe (rule, next, &tree->rules, rlist) { + entry = container_of(rule, struct audit_entry, rule); + +list_del_init (&rule->rlist); +if (entry->rule.exe) +audit_remove_mark (entry->rule.exe); +call_rcu (&entry->rcu, audit_free_rule_rcu); + } }/*
Greg Kroah-Hartman
maintainerPATCH 20/428 crypto: x86/aes-gcm - fix always true check for last AAD segment
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mohamad Raizudeen <[email protected]>
commit 226154ea87952ad7141ce2dcf52a6c2edd71b8fe upstream.
In gcm_process_assoc(), a segment that is not the last one must have its length rounded down to a multiple of 16 bytes, as required by the assembly. The check for a non-last segment is if (unlikely(assoclen)) /* Not the last segment yet? */ where assoclen is the number of AAD bytes remaining after the current segment.
Since the conversion to the new scatterwalk API, assoclen is decremented at the end of the loop body rather than the beginning, so it still includes the current segment when the check executes, making the check always true.
As a result the last segment was rounded down as well, causing some avoidable extra work: an additional memcpy into the temporary buffer and an additional call into the assembly after the loop. The GCM authentication tag is unaffected either way, so the self-tests pass and this went unnoticed. It is purely an efficiency issue rather than a correctness one.
Fix this by moving the assoclen decrement back to the beginning of the loop body.
--- arch/x86/crypto/aesni-intel_glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/crypto/aesni-intel_glue.c +1 -1
@@ -1293,6 +1293,7 @@ static void gcm_process_assoc(const struunsigned int len;const u8 *src = walk.addr; + assoclen -= orig_len_this_step;if (unlikely (pos)) { len =min (len_this_step,16 - pos);memcpy (&buf[pos], src, len);
@@ -1320,7 +1321,6 @@ next:kernel_fpu_end ();kernel_fpu_begin (); } - assoclen -= orig_len_this_step; }if (unlikely (pos))aes_gcm_aad_update (key, ghash_acc, buf, pos, flags);
Greg Kroah-Hartman
maintainerPATCH 21/428 fprobe: Use guard(rcu_sched_notrace) and check rcu_is_watching()
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masami Hiramatsu (Google) <[email protected]>
commit e0a6249190402a28f1e2925a81acf573157d55ef upstream.
unregister_fprobe() and unregister_fprobe_async() (used by BPF kprobe-multi) rely on standard RCU grace periods (synchronize_rcu() and call_rcu()) to wait until in-flight fprobe handlers complete before freeing the fprobe.
However, if an fprobe handler executes while RCU is not watching (such as in the idle loop or nohz_full extended quiescent states), standard RCU does not track preemption-disabled sections. Consequently, synchronize_rcu() does not wait for those executions, which can lead to a use-after-free if the fprobe is freed immediately after unregistration. Ensure handlers exit early when !rcu_is_watching().
Furthermore, fprobe_fgraph_entry() and fprobe_ftrace_entry() previously used guard(rcu)() and rcu_read_lock(), which invoke lockdep on every hit under CONFIG_PROVE_LOCKING. This adds overhead and can cause lockdep recursion if probed functions interact with lockdep.
Since rhltable_lookup() and rhl_for_each_entry_rcu() use rcu_dereference_all_check() (which checks rcu_read_lock_any_held()), holding preemption disabled via rcu_read_lock_sched_notrace() is fully valid and sufficient so long as rcu_is_watching() is true.
Define and use guard(rcu_sched_notrace)() across fprobe_ftrace_entry(), fprobe_fgraph_entry(), and fprobe_return(). This eliminates fast-path rcu_read_lock() and lockdep overhead while guaranteeing safe grace period synchronization.
--- kernel/trace/fprobe.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-)
kernel/trace/fprobe.c +16 -10
@@ -47,6 +47,10 @@ static struct rhltable fprobe_ip_table;static DEFINE_MUTEX (fprobe_mutex);static struct fgraph_ops fprobe_graph_ops; +DEFINE_LOCK_GUARD_0 (rcu_sched_notrace, +rcu_read_lock_sched_notrace (), + rcu_read_unlock_sched_notrace()) +static u32 fprobe_node_hashfn (const void *data,u32 len,u32 seed) {return hash_ptr (*(unsigned long **)data,32 );
@@ -329,16 +333,14 @@ static void fprobe_ftrace_entry(unsignedstruct fprobe *fp;int bit; +if (!rcu_is_watching ()) +return ; + bit =ftrace_test_recursion_trylock (ip, parent_ip);if (bit <0 )return ; -/* -* ftrace_test_recursion_trylock() disables preemption, but -* rhltable_lookup() checks whether rcu_read_lcok is held. -* So we take rcu_read_lock() here. -*/ -rcu_read_lock (); +guard (rcu_sched_notrace)(); head =rhltable_lookup (&fprobe_ip_table, &ip, fprobe_rht_params);rhl_for_each_entry_rcu (node, pos, head, hlist) {
@@ -353,7 +355,6 @@ static void fprobe_ftrace_entry(unsignedelse __fprobe_handler (ip, parent_ip, fp, fregs,NULL ); } -rcu_read_unlock ();ftrace_test_recursion_unlock (bit); }NOKPROBE_SYMBOL (fprobe_ftrace_entry);
@@ -574,10 +575,13 @@ static int fprobe_fgraph_entry(struct ftstruct fprobe *fp;int used, ret; +if (!rcu_is_watching ()) +return 0 ; +if (WARN_ON_ONCE (!fregs))return 0 ; -guard (rcu)(); +guard (rcu_sched_notrace)(); head =rhltable_lookup (&fprobe_ip_table, &func, fprobe_rht_params); reserved_words =0 ;rhl_for_each_entry_rcu (node, pos, head, hlist) {
@@ -672,13 +676,16 @@ static void fprobe_return(struct ftrace_int size, curr;int size_words; +if (!rcu_is_watching ()) +return ; + fgraph_data = (unsigned long *)fgraph_retrieve_data (gops->idx, &size);if (WARN_ON_ONCE (!fgraph_data))return ; size_words =SIZE_IN_LONG (size); ret_ip =ftrace_regs_get_instruction_pointer (fregs); -preempt_disable_notrace (); +guard (rcu_sched_notrace)(); curr =0 ;while (size_words > curr) {
@@ -694,7 +701,6 @@ static void fprobe_return(struct ftrace_ } curr += size; } -preempt_enable_notrace (); }NOKPROBE_SYMBOL (fprobe_return);
Greg Kroah-Hartman
maintainerPATCH 22/428 HID: bpf: cast size to ssize_t when checking hid_bpf_hw_request
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Tissoires <[email protected]>
commit 3afefbfe55c2a8a0c4bdf6f4cc1f773da120027c upstream.
As reported by Sashiko:
If a transport driver encounters a hardware error and returns a negative error code such as -EPIPE, ret is implicitly promoted to size_t when compared against size. This causes the negative error code to evaluate as a large positive number, making the (ret > size) condition true.
This silently converts the hardware error into a success return value and copies the unmodified buffer back, which could leave BPF programs operating on uninitialized or stale data.
Fix this by casting size into ssize_t to return the actual negative error code.
--- drivers/hid/bpf/hid_bpf_dispatch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/hid/bpf/hid_bpf_dispatch.c +1 -1
@@ -453,7 +453,7 @@ hid_bpf_hw_request(struct hid_bpf_ctx *c (u64 )(long )ctx, true); /* prevent infinite recursions */ -if (ret > size) +if (ret > (ssize_t )size) ret = size;if (ret >0 )memcpy (buf, dma_data, ret);
Greg Kroah-Hartman
maintainerPATCH 23/428 HID: multitouch: stop the release timer from being rearmed on remove
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aldo Ariel Panzardo <[email protected]>
commit 5acb2dace582f061aab5e14c399ac9480315f44b upstream.
mt_remove() quiesces the sticky-finger timer before stopping the hardware:
timer_delete_sync(&td->release_timer);
sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group);
hid_hw_stop(hdev);timer_delete_sync() waits for a running callback and dequeues the timer, but it does not stop the timer from being armed again. The transport is still delivering reports at that point, and the report path rearms it:
if (app->quirks & MT_QUIRK_STICKY_FINGERS) {
if (td->mt_io_flags & MT_IO_SLOTS_MASK)
mod_timer(&td->release_timer,
jiffies + msecs_to_jiffies(100));A report that arrives after timer_delete_sync() has returned therefore leaves the timer queued. td is allocated with devm_kzalloc() against hdev->dev, so it is freed when the driver is unbound, after mt_remove() returns. When the timer fires afterwards, mt_expired_timeout() dereferences the freed td:
struct mt_device *td = timer_container_of(td, t, release_timer);
struct hid_device *hdev = td->hdev;
if (test_and_set_bit_lock(MT_IO_FLAGS_RUNNING, &td->mt_io_flags))Simply moving the teardown after hid_hw_stop() does not fix this on its own, because mt_expired_timeout() calls mt_release_contacts(), which walks hdev->inputs; the timer still has to be quiesced before hid_hw_stop() tears the input devices down.
Use timer_shutdown_sync() instead, which additionally makes any later mod_timer() a no-op, so neither ordering constraint has to be traded off against the other. This is the final-teardown pattern the function was introduced for, and hid-wiimote already uses it for the same reason.
--- drivers/hid/hid-multitouch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/hid/hid-multitouch.c +1 -1
@@ -2260,7 +2260,7 @@ static void mt_remove(struct hid_device {struct mt_device *td =hid_get_drvdata (hdev); -timer_delete_sync (&td->release_timer); +timer_shutdown_sync (&td->release_timer);sysfs_remove_group (&hdev->dev.kobj, &mt_attribute_group);hid_hw_stop (hdev);
Greg Kroah-Hartman
maintainerPATCH 24/428 io_uring/cmd_net: end TX_TIMESTAMP multishot when the CQ is full
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: lollipopkit <[email protected]>
commit 3a3d93070c5ec8b8049d57025987ba313420bda9 upstream.
SOCKET_URING_OP_TX_TIMESTAMP arms an EPOLLERR apoll multishot and, on each error queue edge, posts one 32 byte aux CQE per timestamp skb. Aux CQEs have no overflow backing, so io_uring_cmd_post_mshot_cqe32() fails once the CQ ring is full. The loop then stops, splices the unprocessed skbs back onto sk_error_queue and returns -EAGAIN.
-EAGAIN is IOU_RETRY, so the request goes idle until the next poll event. io_arm_apoll() forces EPOLLET and draining the CQ does not re-run the command, so the spliced-back timestamps stay queued until an unrelated later timestamp produces a new edge.
End the multishot when a CQE cannot be posted, as multishot poll and recv already do. There is no partial result to report, so complete with -ENOBUFS: no CQ space is left for the timestamp CQEs. This command does not use provided buffers, so the value cannot be confused with a buffer ring running empty. The terminal CQE still reaches userspace because request completions can go to the overflow list. The application sees a CQE without IORING_CQE_F_MORE, which it already has to handle, and the first issue of the re-armed request delivers the queued timestamps.
A timestamp that cannot be extracted keeps its current behaviour.
This was found with LLM assistance while reviewing io_uring multishot handlers for the pattern behind a RECV_ZC stall reported earlier (see Link), and confirmed with a reproducer on v7.3-rc2 and an A/B run of this patch.
--- io_uring/cmd_net.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-)
io_uring/cmd_net.c +14 -5
@@ -69,8 +69,8 @@ static inline int io_uring_cmd_setsockop optlen); } -static bool io_process_timestamp_skb (struct io_uring_cmd *cmd,struct sock *sk, -struct sk_buff *skb,unsigned issue_flags) +static int io_process_timestamp_skb (struct io_uring_cmd *cmd,struct sock *sk, +struct sk_buff *skb,unsigned int issue_flags) {struct sock_exterr_skb *serr =SKB_EXT_ERR (skb);struct io_uring_cqe cqe[2 ];
@@ -83,7 +83,7 @@ static bool io_process_timestamp_skb(str ret =skb_get_tx_timestamp (skb, sk, &ts);if (ret <0 ) -return false; +return ret; tskey = serr->ee.ee_data; tstype = serr->ee.ee_info;
@@ -98,7 +98,9 @@ static bool io_process_timestamp_skb(str iots = (struct io_timespec *)&cqe[1 ]; iots->tv_sec = ts.tv_sec; iots->tv_nsec = ts.tv_nsec; -return io_uring_cmd_post_mshot_cqe32 (cmd, issue_flags, cqe); +if (!io_uring_cmd_post_mshot_cqe32 (cmd, issue_flags, cqe)) +return -ENOBUFS ; +return 0 ; } static int io_uring_cmd_timestamp(struct socket *sock,
@@ -135,7 +137,8 @@ static int io_uring_cmd_timestamp(struct skb =skb_peek (&list);if (!skb)break ; -if (!io_process_timestamp_skb (cmd, sk, skb, issue_flags)) + ret =io_process_timestamp_skb (cmd, sk, skb, issue_flags); +if (ret)break ;__skb_dequeue (&list);consume_skb (skb);
@@ -145,6 +148,12 @@ static int io_uring_cmd_timestamp(struct scoped_guard(spinlock_irqsave, &q->lock)skb_queue_splice (&list, q); } +/* +* Aux CQEs cannot overflow and the poll is edge triggered, so nothing +* re-runs the command once the CQ drains. End the multishot instead. +*/ +if (ret == -ENOBUFS ) +return -ENOBUFS ;return -EAGAIN ; }
Greg Kroah-Hartman
maintainerPATCH 25/428 io_uring/zcrx: requeue multishot receives stopped by a local resource
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Junyuan Feng <[email protected]>
commit 98ad5b63f5041dc354a6e694f4a9436f74e0681b upstream.
A multishot RECV_ZC can go idle with unread TCP data when a receiver-local resource runs out. An empty copy-fallback niov freelist returns -ENOMEM; a full CQ returns -ENOSPC. After partial progress the stop reason is lost: io_zcrx_copy_chunk() and io_zcrx_recv_skb() report the copied bytes, and tcp_read_sock() drops an error from a later call once earlier data was consumed. The edge-triggered request is then not requeued, so it cannot consume the remaining data until another socket event arrives.
Record in io_zcrx_recv_skb() when a walk stops before consuming the length it was offered, and requeue if the pass still returned data. The failed chunk is first on the next pass. The resource is usually still exhausted by then, so that pass fails at once and ends the request with an error CQE, which the application must handle by re-arming. The request does not spin, and the stall becomes a visible error. Keep the existing skb limit and SOCK_DONE handling.
--- io_uring/zcrx.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
io_uring/zcrx.c +7 -2
@@ -340,6 +340,7 @@ struct io_zcrx_args {struct io_kiocb *req;struct io_zcrx_ifq *ifq;unsigned nr_skbs; +bool stopped_early; };static const struct memory_provider_ops io_uring_pp_zc_ops;
@@ -1727,6 +1728,9 @@ io_zcrx_recv_skb(read_descriptor_t *desc } out: +/* Bytes left in len mean an error stopped the walk early. */ +if (len) + args->stopped_early = true;if (offset == start_off)return ret; desc->count -= (offset - start_off);
@@ -1763,8 +1767,9 @@ static int io_zcrx_tcp_recvmsg(struct io ret = -ENOTCONN ; else ret = -EAGAIN ; - }else if (unlikely (args.nr_skbs >IO_SKBS_PER_CALL_LIMIT ) && - (issue_flags &IO_URING_F_MULTISHOT )) { + }else if ((issue_flags &IO_URING_F_MULTISHOT ) && + (unlikely (args.nr_skbs >IO_SKBS_PER_CALL_LIMIT ) || + args.stopped_early)) { ret =IOU_REQUEUE ; }else if (sock_flag (sk,SOCK_DONE )) {/* Make it to retry until it finally gets 0. */
Greg Kroah-Hartman
maintainerPATCH 26/428 io_uring: fix task_work add use-after-free with SQPOLL
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jens Axboe <[email protected]>
commit a92193c91e8839fe5fc209616ea95465ae4b919d upstream.
For SQPOLL, the sqpoll thread runs task_work off its own list and doesn't need to be told about it, so it can pop and complete a request as soon as mpscq_push() has published it. If that was the last request holding the ring alive, io_ring_exit_work() then frees the ctx, stops the thread, and with it the tctx, while io_req_normal_work_add() is still looking at both after the push:
BUG: KASAN: slab-use-after-free in io_req_normal_work_add+0x439/0x510 Read of size 4 at addr ff11000000ca0000 by task repro/55 (...) BUG: KASAN: slab-use-after-free in queue_work_on+0x25/0x70 Write of size 8 at addr ff11000000c3bd00 by task repro/55
Hold an RCU read lock across the add, like io_req_local_work_add() already does, and have io_ring_exit_work() wait for a grace period for SQPOLL rings as well before freeing the ctx.
--- io_uring/io_uring.c | 4 ++-- io_uring/tw.c | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-)
io_uring/io_uring.c +2 -2
@@ -2412,8 +2412,8 @@ static __cold void io_ring_exit_work(strspin_lock (&ctx->completion_lock);spin_unlock (&ctx->completion_lock); -/* pairs with RCU read section in io_req_local_work_add() */ -if (ctx->flags &IORING_SETUP_DEFER_TASKRUN ) +/* pairs with the RCU read sections in the task_work add paths */ +if (ctx->flags & (IORING_SETUP_DEFER_TASKRUN |IORING_SETUP_SQPOLL ))synchronize_rcu ();io_ring_ctx_free (ctx);
io_uring/tw.c +3 -0
@@ -210,6 +210,9 @@ void io_req_normal_work_add(struct io_kistruct io_uring_task *tctx = req->tctx;struct io_ring_ctx *ctx = req->ctx; +/* SQPOLL can retire the request on push, see io_ring_exit_work() */ +guard (rcu)(); +/* tw run already pending, nothing else to do */ if (!mpscq_push (&tctx->task_list, &req->io_task_work.node))return ;
Greg Kroah-Hartman
maintainerPATCH 27/428 ipvs: bound LBLCR and LBLC cache growth
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhiling Zou <[email protected]>
commit 2a3c3de660f96865f303fd25f1285f2ffbfd521d upstream.
ip_vs_lblcr_new() and ip_vs_lblc_new() create cache entries for every previously unseen destination address. The table max_size only tells the periodic collector to reclaim entries after the cache has already exceeded the limit. It does not reclaim entries that the attacker continues to use.
Reject new cache entries once either table reaches max_size * 3 / 2. The extra headroom lets the periodic collector catch up while the existing scheduler fallback continues to use the selected destination when cache creation fails. New traffic therefore stays serviceable without growing the tables further.
--- net/netfilter/ipvs/ip_vs_lblc.c | 3 +++ net/netfilter/ipvs/ip_vs_lblcr.c | 3 +++ 2 files changed, 6 insertions(+)
net/netfilter/ipvs/ip_vs_lblc.c +3 -0
@@ -204,6 +204,9 @@ ip_vs_lblc_new(struct ip_vs_lblc_table *return en;ip_vs_lblc_del (en); } +if (atomic_read (&tbl->entries) >= tbl->max_size *3 /2 ) +return NULL ; + en =kmalloc_obj (*en,GFP_ATOMIC );if (!en)return NULL ;
net/netfilter/ipvs/ip_vs_lblcr.c +3 -0
@@ -363,6 +363,9 @@ ip_vs_lblcr_new(struct ip_vs_lblcr_table en =ip_vs_lblcr_get (af, tbl, daddr);if (!en) { +if (atomic_read (&tbl->entries) >= tbl->max_size *3 /2 ) +return NULL ; + en =kmalloc_obj (*en,GFP_ATOMIC );if (!en)return NULL ;
Greg Kroah-Hartman
maintainerPATCH 28/428 kasan: unpoison task stack below watermark only in generic mode
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrey Ryabinin <[email protected]>
commit 22ab0647764c38924669673634ae333578d77768 upstream.
CPU resume and BPF exception handling can discard stack frames without running their compiler-generated epilogues. Generic KASAN needs kasan_unpoison_task_stack_below() to clear the redzones left behind by those frames before the stack is reused.
CONFIG_KASAN_STACK also enables this helper for SW_TAGS. The helper derives the stack base from an untagged stack pointer, so kasan_unpoison() writes KASAN_TAG_KERNEL (0xff) into the shadow for [base, watermark). For a vmapped task stack, vm_area->addr still carries the original random allocation tag. This creates a tag mismatch at the stack base even if that memory has never held an instrumented stack object.
When the task exits and its stack is not cached, thread_stack_free_rcu() passes vm_area->addr to vfree(). In RCU callback context this reaches vfree_atomic(), whose llist_add() writes to the allocation base through the tagged pointer and triggers a false KASAN invalid-access report:
BUG: KASAN: invalid-access in vfree_atomic+0x90/0x150 Write of size 8 at addr c2ffffc0a8f70000 by task rcuop/7/75 Pointer tag: [c2], memory tag: [ff] Call trace: __hwasan_store8_noabort+0xe8/0xf8 vfree_atomic+0x90/0x150 vfree+0x220/0x298 thread_stack_free_rcu+0x3c/0x4c rcu_do_batch+0x308/0xaf0 rcu_nocb_cb_kthread+0x33c/0x708
The deferred-free path started using the tagged vm_area->addr in commit 449e0b4ed5a1 ("fork: clean-up naming of vm_stack/vm_struct variables in vmap stacks code"). Previously it freed the untagged pointer derived from tsk->stack, so the write was never tag-checked.
SW_TAGS does not need the blanket shadow reset to make subsequent stack accesses valid: untagged kernel pointers have the match-all 0xff tag, and the compiler initializes the shadow tags of instrumented stack objects before use.
Return early unless CONFIG_KASAN_GENERIC is enabled. Keep the mode check in the common helper so it covers both resume and bpf_throw().
--- mm/kasan/common.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
mm/kasan/common.c +12 -1
@@ -114,12 +114,23 @@ void kasan_unpoison_task_stack(struct ta/* Unpoison the stack for the current task beyond a watermark sp value. */ asmlinkage void kasan_unpoison_task_stack_below(const void *watermark) { +void *base; + +/* +* Only the generic mode needs this. In the tag-based mode the +* compiler fully initializes the shadow of stack variables on +* function entry, so stale tags left below the watermark are +* harmless. +*/ +if (!IS_ENABLED (CONFIG_KASAN_GENERIC )) +return ; +/* * Calculate the task stack base address. Avoid using 'current' * because this function is called by early resume code which hasn't * yet set up the percpu register (%gs). */ -void *base = (void *)((unsigned long )watermark & ~(THREAD_SIZE -1 )); + base = (void *)((unsigned long )watermark & ~(THREAD_SIZE -1 ));kasan_unpoison (base, watermark - base, false); }
Greg Kroah-Hartman
maintainerPATCH 29/428 kprobes: Skip disarmed probes when checking optkprobe overlap
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Hwang <[email protected]>
commit 7a39c732a22ec4a369af9e19fbe3d666ec83eec4 upstream.
On x86, an optkprobe at A replaces five bytes with a jump. If a disabled probe B is at A+2, get_optimized_kprobe() stops at B when arming a new probe C at A+4. It leaves A optimized:
A A+1 A+2 A+3 A+4 A's jump | e9 | d0 | d1 | d2 | d3 | after C | e9 | d0 | d1 | d2 | cc |
The INT3 for C overwrites the last byte of A's jump displacement, so execution can jump to the wrong address. B can have prepared optinsns while disarmed, but has no jump to unoptimize.
Continue past disarmed and unprepared probes to find the active optimized probe before arming a probe in its jump.
--- kernel/kprobes.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
kernel/kprobes.c +5 -3
@@ -496,14 +496,16 @@ static bool kprobe_queued(struct kprobestatic struct kprobe *get_optimized_kprobe (kprobe_opcode_t *addr) {int i; -struct kprobe *p =NULL ; +struct kprobe *p;struct optimized_kprobe *op;/* Don't check i == 0, since that is a breakpoint case. */ -for (i =1 ; !p && i <MAX_OPTIMIZED_LENGTH /sizeof (kprobe_opcode_t); i++) +for (i =1 ; i <MAX_OPTIMIZED_LENGTH /sizeof (kprobe_opcode_t); i++) { p =get_kprobe (addr - i); +/* A disabled probe can have prepared, but inactive, optinsns. */ +if (!p || !kprobe_optready (p) ||kprobe_disarmed (p)) +continue ; -if (p &&kprobe_optready (p)) { op = container_of(p, struct optimized_kprobe, kp);if (arch_within_optimized_kprobe (op, addr))return p;
Greg Kroah-Hartman
maintainerPATCH 30/428 octeontx2-pf: Fix RSS indirection table size
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jari Seppälä <[email protected]>
commit 9e792901418d814295674d1f53d6b615fb5c15c8 upstream.
The conversion to the dedicated RSS context operations replaced the pointer to struct otx2_rss_ctx with an inline u32 ind_tbl[] array. However, otx2_rss_init() still uses sizeof(*rss->ind_tbl) to set rss_size. This now yields the size of one u32 (4), rather than the 256 entries in the indirection table.
The RSS initialization and hardware programming loops use rss_size, so only four entries are initialized and programmed despite the NIX LF being allocated a 256-entry table. On an OCTEON CN102 with eight RX queues, the table contained 0, 1, 2, 3 followed by zeros. Traffic was concentrated on queue 0 and ethtool -X equal 8 did not correct the table.
Use ARRAY_SIZE() to count the indirection table entries. On the same hardware, this restores the full table repeating queue numbers 0 through 7, and bidirectional multi-flow traffic increments multiple RX queues.
Runtime testing on an Asterfusion ET2500 (OCTEON CN102 A0).
--- drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +1 -1
@@ -394,7 +394,7 @@ int otx2_rss_init(struct otx2_nic *pfvf)struct otx2_rss_info *rss = &pfvf->hw.rss_info;int idx, ret =0 ; - rss->rss_size =sizeof (*rss->ind_tbl); + rss->rss_size =ARRAY_SIZE (rss->ind_tbl);/* Init RSS key if it is not setup already */ if (!rss->enable)
Greg Kroah-Hartman
maintainerPATCH 31/428 of/irq: Fix remaining refcount leaks in of_irq_init()
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wentao Liang <[email protected]>
commit 30724547b221e0e670ddfef140fc7d816b2aaec6 upstream.
Successfully initialized controllers are moved to intc_parent_list, but the final cleanup only frees the descriptors. The device node references taken with of_node_get() and the interrupt parent references are therefore leaked on the normal return path. Drop both before kfree(), as the intc_desc_list cleanup already does.
--- drivers/of/irq.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/of/irq.c +2 -0
@@ -754,6 +754,8 @@ void __init of_irq_init(const struct of_list_for_each_entry_safe (desc, temp_desc, &intc_parent_list, list) {list_del (&desc->list); +of_node_put (desc->interrupt_parent); +of_node_put (desc->dev);kfree (desc); } err:
Greg Kroah-Hartman
maintainerPATCH 32/428 of/overlay: put property on deadprops only after changeset add succeeds
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdurrahman Hussain <[email protected]>
commit 814f2da6995772c07a7c9c2cc6028b6e3f3ecc9c upstream.
add_changeset_property() links a new property of a not-yet-live target node into the node's deadprops list before handing it to of_changeset_add_property(). If that fails, the error path frees the property but leaves the freed pointer linked in deadprops, and of_node_release() frees it a second time when the aborted overlay's node is released.
Record the changeset entry first and link the property into deadprops only on success. of_changeset_add_property() never looks at the node's property lists, so the order of the two steps is otherwise immaterial, and the error path frees a property that nothing references.
--- drivers/of/overlay.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/of/overlay.c +4 -3
@@ -358,12 +358,13 @@ static int add_changeset_property(structreturn -ENOMEM ;if (!prop) { -if (!target->in_livetree) { + ret =of_changeset_add_property (&ovcs->cset, target->np, + new_prop); +/* the detached node owns the property until the apply */ +if (!ret && !target->in_livetree) { new_prop->next = target->np->deadprops; target->np->deadprops = new_prop; } - ret =of_changeset_add_property (&ovcs->cset, target->np, - new_prop); }else { ret =of_changeset_update_property (&ovcs->cset, target->np, new_prop);
Greg Kroah-Hartman
maintainerPATCH 33/428 of/overlay: only treat a positive changeset id as registered
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdurrahman Hussain <[email protected]>
commit 44081d708b5b885487bac792db78324b7b4c267d upstream.
of_overlay_fdt_apply() stores the idr_alloc() return value in ovcs->id before checking it. On failure the stored id is negative, free_overlay_changeset()'s "if (ovcs->id)" check passes, idr_remove() is called with a negative id and list_del() runs on ovcs->ovcs_list, which is not initialized until after the id allocation. An allocation failure at that point dereferences NULL.
Make free_overlay_changeset() treat only a strict-positive id as registered. The rest of the function already copes with a partially-initialized ovcs, so the error path stays a plain goto err_free_ovcs.
--- drivers/of/overlay.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/of/overlay.c +2 -1
@@ -864,7 +864,8 @@ static void free_overlay_changeset(strucif (ovcs->cset.entries.next)of_changeset_destroy (&ovcs->cset); -if (ovcs->id) { +/* a failed idr_alloc() leaves its negative error in ovcs->id */ +if (ovcs->id >0 ) {idr_remove (&ovcs_idr, ovcs->id);list_del (&ovcs->ovcs_list); ovcs->id =0 ;
Greg Kroah-Hartman
maintainerPATCH 34/428 net: gso: limit recursive IP-in-IP segmentation
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zihan Xi <[email protected]>
commit 006c8b834aed8b02bd8fb9fb05e9e7ead37d1763 upstream.
IP-in-IP GSO can re-enter inet_gso_segment() or ipv6_gso_segment() for each nested IP header. encap_level tracks header bytes, not callback depth, so a deep chain can exhaust the kernel stack. Making inet_gso_segment() stackable introduced unbounded IPv4 nesting; IPIP GSO/TSO later made the path reachable. The IPv6 stackable path was introduced separately and uses the same guard.
Count IPv4 and IPv6 GSO handler entries in skb_gso_cb, initialized once per top-level GSO operation and preserved across GRE/UDP context changes. Use the existing IP_TUNNEL_RECURSION_LIMIT for both handlers. The first five entries pass, and the sixth returns -EINVAL before dispatching another GSO callback.
--- include/net/gso.h | 8 ++++++++ net/core/gso.c | 1 + net/ipv4/af_inet.c | 3 +++ net/ipv6/ip6_offload.c | 4 ++++ 4 files changed, 16 insertions(+)
include/net/gso.h +8 -0
@@ -19,10 +19,18 @@ struct skb_gso_cb {int encap_level;__wsum csum;__u16 csum_start; +/* Number of IPv4/IPv6 GSO handler entries for this packet. */ +u8 recursion_counter; };#define SKB_GSO_CB_OFFSET 32#define SKB_GSO_CB (skb) ((struct skb_gso_cb *)((skb)->cb + SKB_GSO_CB_OFFSET)) +static inline bool gso_recursion_inc_test (struct sk_buff *skb, +unsigned int limit) +{ +return ++SKB_GSO_CB (skb)->recursion_counter > limit; +} +static inline int skb_tnl_header_len (const struct sk_buff *inner_skb) { return (skb_mac_header(inner_skb) - inner_skb->head) -
net/core/gso.c +1 -0
@@ -117,6 +117,7 @@ struct sk_buff *__skb_gso_segment(structSKB_GSO_CB (skb)->mac_offset =skb_headroom (skb);SKB_GSO_CB (skb)->encap_level =0 ; +SKB_GSO_CB (skb)->recursion_counter =0 ;skb_reset_mac_header (skb);skb_reset_mac_len (skb);
net/ipv4/af_inet.c +3 -0
@@ -1375,6 +1375,9 @@ struct sk_buff *inet_gso_segment(structint id;skb_reset_network_header (skb); +if (unlikely (gso_recursion_inc_test (skb, +IP_TUNNEL_RECURSION_LIMIT ))) + goto out; nhoff =skb_network_header (skb) -skb_mac_header (skb);if (unlikely (!pskb_may_pull (skb,sizeof (*iph)))) goto out;
net/ipv6/ip6_offload.c +4 -0
@@ -17,6 +17,7 @@#include <net/udp.h> #include <net/gro.h> #include <net/gso.h> +#include <net/ip_tunnels.h> #include "ip6_offload.h" #include "tcpv6_offload.c"
@@ -104,6 +105,9 @@ static struct sk_buff *ipv6_gso_segment(bool gso_partial;skb_reset_network_header (skb); +if (unlikely (gso_recursion_inc_test (skb, +IP_TUNNEL_RECURSION_LIMIT ))) + goto out; nhoff =skb_network_header (skb) -skb_mac_header (skb);if (unlikely (!pskb_may_pull (skb,sizeof (*ipv6h)))) goto out;
Greg Kroah-Hartman
maintainerPATCH 35/428 net: extend IPv6 exthdr detection of tunneled packets
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Willem de Bruijn <[email protected]>
commit 5f0764cb1c81a9712bce605d38efe6d844a70b29 upstream.
Commit c4336a07eb6b ("net: correctly handle tunneled traffic on IPV6_CSUM GSO fallback") split skb_gso_has_extension_hdr() into mutually exclusive branches on skb->encapsulation. This did not yet address all paths:
1. With skb->encapsulation set, the outer header is not checked. IPv6 tunnels such as ip6_gre and ip6_tunnel add an outer Destination Options header by default (encap_limit). Their GSO packets skip software GSO, then skb_csum_hwoffload_help() sees the outer extension header and calls skb_checksum_help() on the GSO skb, which warns and drops it.
2. Tunnels over IPv6 without an outer transport header, such as ip6_tunnel, leave skb->transport_header at the inner transport header. skb_network_header_len() then spans the outer IPv6, tunnel and inner IP headers, a false positive.
3. UDP tunnels without an inner network header, such as SCTP-in-UDP or PSP, have no inner IPv6 header to check. Decide on the outer header alone.
4. Directly dereferencing inner_ip_hdr(skb)->version without skb_header_pointer() is unsafe.
Instead, check ipv6_ext_hdr(nexthdr) on the outer IPv6 header and, if set, on the inner IPv6 header. Read the headers with skb_header_pointer(). Keep the skb_network_header_len() check when !skb->encapsulation to also catch encapsulated packets without skb->encapsulation (e.g., virtio).
Use the same helper in skb_csum_hwoffload_help(). Its open coded test has the false positive of (2) and ignores the inner header.
Background: checksum offload of tunneled packets invariants:
Non-GSO skb:
- If the inner packet is CHECKSUM_PARTIAL, Local Checksum Offload computes the outer checksum in software and the device offloads only the inner L4 checksum.
- If the inner packet is CHECKSUM_NONE (e.g., SCTP-in-UDP, ESP-in-UDP, Remote Checksum Offload), the device offloads the outer UDP or GRE checksum instead.
GSO skb:
- A device with NETIF_F_GSO_UDP_TUNNEL_CSUM or NETIF_F_GSO_GRE_CSUM computes both inner and outer checksums per segment. The outer checksum is seeded with only the pseudo-header checksum.
A NETIF_F_IPV6_CSUM device must parse through the outer headers to reach the inner ones.
--- net/core/dev.c | 47 +++++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 16 deletions(-)
net/core/dev.c +31 -16
@@ -3812,20 +3812,36 @@ static netdev_features_t dflt_features_creturn vlan_features_check (skb, features); } -static bool skb_gso_has_extension_hdr (const struct sk_buff *skb) +static bool __skb_has_ipv6_ext_hdr (const struct sk_buff *skb,int nhoff) { -if (!skb->encapsulation) -return ((skb_shinfo (skb)->gso_type &SKB_GSO_TCPV6 || - (skb_shinfo (skb)->gso_type &SKB_GSO_UDP_L4 && -vlan_get_protocol (skb) ==htons (ETH_P_IPV6 ))) && -skb_transport_header_was_set (skb) && -skb_network_header_len (skb) !=sizeof (struct ipv6hdr )); -else -return (!skb_inner_network_header_was_set (skb) || - ((skb_shinfo (skb)->gso_type &SKB_GSO_TCPV6 || - (skb_shinfo (skb)->gso_type &SKB_GSO_UDP_L4 && -inner_ip_hdr (skb)->version ==6 )) && -skb_inner_network_header_len (skb) !=sizeof (struct ipv6hdr ))); +const struct ipv6hdr *ip6h; +struct ipv6hdr _ip6h; + + ip6h =skb_header_pointer (skb, nhoff,sizeof (_ip6h), &_ip6h); +return ip6h && ip6h->version ==6 &&ipv6_ext_hdr (ip6h->nexthdr); +} + +static bool skb_has_ipv6_extension_hdr (const struct sk_buff *skb) +{ +if (vlan_get_protocol (skb) ==htons (ETH_P_IPV6 )) { +if (__skb_has_ipv6_ext_hdr (skb,skb_network_offset (skb))) +return true; + +/* Catch tunnels without skb->encapsulation (e.g., virtio). */ +if (!skb->encapsulation && +skb_transport_header_was_set (skb) && +skb_network_header_len (skb) !=sizeof (struct ipv6hdr )) +return true; + } + +/* Tunnels without an inner network header, such as SCTP-in-UDP or +* PSP, have no inner IP header and thus no inner extension header. +*/ +if (skb->encapsulation &&skb_inner_network_header_was_set (skb) && +__skb_has_ipv6_ext_hdr (skb,skb_inner_network_offset (skb))) +return true; + +return false; } static netdev_features_t gso_features_check(const struct sk_buff *skb,
@@ -3880,7 +3896,7 @@ static netdev_features_t gso_features_ch* so neither does TSO that depends on it. */ if (features &NETIF_F_IPV6_CSUM && -skb_gso_has_extension_hdr (skb)) +skb_has_ipv6_extension_hdr (skb)) features &= ~(NETIF_F_IPV6_CSUM |NETIF_F_TSO6 |NETIF_F_GSO_UDP_L4 );return features;
@@ -3982,8 +3998,7 @@ int skb_csum_hwoffload_help(struct sk_bureturn 0 ;if (features & (NETIF_F_IP_CSUM |NETIF_F_IPV6_CSUM )) { -if (vlan_get_protocol (skb) ==htons (ETH_P_IPV6 ) && -skb_network_header_len (skb) !=sizeof (struct ipv6hdr )) +if (skb_has_ipv6_extension_hdr (skb)) goto sw_checksum;switch (skb->csum_offset) {
Greg Kroah-Hartman
maintainerPATCH 36/428 net: fix checksum offsets in skb_splice_from_iter()
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alireza Asgari <[email protected]>
commit febec6a7076499d16b37f556724a942633a270a6 upstream.
skb_splice_from_iter() appends multiple page fragments before updating skb->len. However, skb_splice_csum_page() uses that unchanged length as the offset for every fragment checksum. If bytes already appended during the call have an odd total length, a later fragment's checksum is combined with the wrong parity.
For example, prime a UDP socket with sendto(MSG_MORE) and splice two distinct pipe buffers containing "abc" and "DEFGH". Uncorking reports success, but the receiver discards the packet for a bad checksum. This also affects IPv6 and fragments beginning near a page boundary.
Pass the initial skb length plus the bytes already spliced to the checksum helper. Keep the existing final length update and partial-progress error handling unchanged. CHECKSUM_PARTIAL does not use this helper and remains unaffected.
--- net/core/skbuff.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
net/core/skbuff.c +5 -3
@@ -7397,7 +7397,8 @@ nodefer: kfree_skb_napi_cache(skb); }static void skb_splice_csum_page (struct sk_buff *skb,struct page *page, -size_t offset,size_t len) +size_t offset,size_t len, +unsigned int csum_offset) {const char *kaddr;__wsum csum;
@@ -7405,7 +7406,7 @@ static void skb_splice_csum_page(struct kaddr =kmap_local_page (page); csum =csum_partial (kaddr + offset, len,0 );kunmap_local (kaddr); - skb->csum =csum_block_add (skb->csum, csum, skb->len); + skb->csum =csum_block_add (skb->csum, csum, csum_offset); }/**
@@ -7465,7 +7466,8 @@ ssize_t skb_splice_from_iter(struct sk_b }if (skb->ip_summed ==CHECKSUM_NONE ) -skb_splice_csum_page (skb, page, off, part); +skb_splice_csum_page (skb, page, off, part, + skb->len + spliced); off =0 ; spliced += part;
Greg Kroah-Hartman
maintainerPATCH 37/428 net: phy: aquantia: fix system interface type not updated in forced mode
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bartosz Golaszewski <[email protected]>
commit 6e0022b5ae3dc5b833af0fcc1578dc20a1d6bc71 upstream.
aqr_gen1_read_status() decodes the MDIO_PHYXS_VEND_IF_STATUS register to determine which SerDes interface the PHY is currently using on its system side and stores the result in phydev->interface. phylink relies on this value to configure the MAC.
The autoneg == AUTONEG_DISABLE check is not correct:MDIO_PHYXS_VEND_IF_STATUS is set by the PHY firmware based on the negotiated link speed, not based on whether autoneg was used to reach it. When the link comes up at 1G in forced mode, the register correctly reads SGMII, but the early return prevents phydev->interface from being updated. It stays at whatever value it held before (typically 2500BASE-X from the initial autoneg run), so phylink configures the MAC for the wrong interface and the link cannot come up.
Remove the autoneg guard so that the system interface type is always decoded when the link is up.
--- drivers/net/phy/aquantia/aquantia_main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/net/phy/aquantia/aquantia_main.c +4 -1
@@ -544,7 +544,7 @@ static int aqr_gen1_read_status(struct pif (ret)return ret; -if (!phydev->link || phydev->autoneg ==AUTONEG_DISABLE ) +if (!phydev->link)return 0 ;/* The status register is not immediately correct on line side link up.
@@ -594,6 +594,9 @@ static int aqr_gen1_read_status(struct p phydev->interface =aqr_translate_interface (phydev, interface); +if (phydev->autoneg ==AUTONEG_DISABLE ) +return 0 ; +/* Read rate from vendor register */ return aqr_gen1_read_rate (phydev); }
Greg Kroah-Hartman
maintainerPATCH 38/428 netfilter: nft_flow_offload: drop flowtable reference on init error path
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aohan Mei <[email protected]>
commit 747928b5d4ff8c8de55138a54c13980e4bb88578 upstream.
nft_flow_offload_init() bumps the flowtable use count with nft_use_inc() before calling nf_ct_netns_get(). When the latter fails, the error is returned as-is and the reference is leaked.
The upper layers do not balance it either: nf_tables_newexpr() clears expr->ops when the expression init callback fails, so the nft_expr_more() iteration in nft_rule_expr_deactivate() and nf_tables_rule_destroy() stops right before the failed expression and its ->destroy callback, which would drop the reference, never runs.
Each failed rule addition therefore leaks one flowtable reference and the flowtable can no longer be removed: NFT_MSG_DELFLOWTABLE keeps reporting -EBUSY even though no rule references it.
Save the nf_ct_netns_get() return value and undo the nft_use_inc() when it fails, restoring the inc/dec pairing within nft_flow_offload_init() itself.
--- net/netfilter/nft_flow_offload.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
net/netfilter/nft_flow_offload.c +6 -1
@@ -160,6 +160,7 @@ static int nft_flow_offload_init(const sstruct nft_flow_offload *priv =nft_expr_priv (expr);u8 genmask =nft_genmask_next (ctx->net);struct nft_flowtable *flowtable; +int err;if (!tb[NFTA_FLOW_TABLE_NAME ])return -EINVAL ;
@@ -174,7 +175,11 @@ static int nft_flow_offload_init(const s priv->flowtable = flowtable; -return nf_ct_netns_get (ctx->net, ctx->family); + err =nf_ct_netns_get (ctx->net, ctx->family); +if (err <0 ) +nft_use_dec (&flowtable->use); + +return err; } static void nft_flow_offload_deactivate(const struct nft_ctx *ctx,
Greg Kroah-Hartman
maintainerPATCH 39/428 net/packet: prevent TX_RING byte count overflow
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ilkka Lappeteläinen <[email protected]>
commit 2cf81fc9505b148b1b70068303ea6ea4b1212403 upstream.
tpacket_snd() drains every SEND_REQUEST frame in a TX ring and adds each valid packet length to the signed int len_sum. Userspace can recycle completed frames concurrently, so a single blocking send call is not bounded by the ring size.
After enough successful transmissions len_sum wraps into the negative range. In particular, 65536 65535-byte frames followed by a 65007-byte frame produce 0xfffffdef, or -EIOCBQUEUED. sock_sendmsg_nosec() treats that as an impossible return and triggers a BUG. On systems configured to panic on oops, a CAP_NET_RAW holder can panic the host kernel.
Stop before the next frame would make the byte count exceed INT_MAX. The positive short count leaves that frame pending for a later send call.
A two-thread TPACKET_V2 reproducer triggered the BUG on an arm64 build of Linux 7.3-rc4. With this change, the same reproducer returned the expected positive short count without an oops.
--- net/packet/af_packet.c | 3 +++ 1 file changed, 3 insertions(+)
net/packet/af_packet.c +3 -0
@@ -2874,6 +2874,9 @@ static int tpacket_snd(struct packet_soc vnet_hdr.hdr_len); has_vnet_hdr = true; } +/* Prevent the byte count from wrapping into a negative errno */ +if (unlikely (tp_len >INT_MAX - len_sum)) +break ; copylen =max_t (int, copylen, hard_header_len); skb = sock_alloc_send_skb(&po->sk, hlen + tlen + sizeof(struct sockaddr_ll) +
Greg Kroah-Hartman
maintainerPATCH 40/428 pfcp: fix socket lifetime on netdevice registration failure
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xuanqiang Luo <[email protected]>
commit 0f17d2e3dd9cda3ee6d94033d5e5489af168920d upstream.
pfcp_newlink() creates the UDP socket before register_netdevice(). If registration fails after pfcp_dev_init() succeeds, the core calls pfcp_dev_uninit(), which releases the socket and clears pfcp->sk. The newlink error path then releases it again, causing a NULL pointer dereference. This was observed with failslab fault injection:
FAULT_INJECTION: forcing a failure.
kobject: kobject_add_internal failed for pfcp0 (error: -12 parent: net)
BUG: KASAN: null-ptr-deref in udp_tunnel_sock_release+0x1c/0x50 Read of size 8 at addr 0000000000000120 by task ip/1037 Call trace: show_stack+0x18/0x24 (C) dump_stack_lvl+0x78/0x90 print_report+0x468/0x5cc kasan_report+0xa4/0xf0 __asan_load8+0x7c/0xd0 udp_tunnel_sock_release+0x1c/0x50 pfcp_newlink+0x128/0x184 rtnl_newlink+0x848/0xe44 rtnetlink_rcv_msg+0x468/0x514 netlink_rcv_skb+0xc0/0x1f0 rtnetlink_rcv+0x18/0x24 netlink_unicast+0x4b8/0x558 netlink_sendmsg+0x2b8/0x584 ...
Return from pfcp_del_sock() if pfcp->sk is NULL.
--- drivers/net/pfcp.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/pfcp.c +3 -0
@@ -104,6 +104,9 @@ drop:static void pfcp_del_sock (struct pfcp_dev *pfcp) { +if (!pfcp->sk) +return ; +udp_tunnel_sock_release (pfcp->sk); pfcp->sk =NULL ; }
Greg Kroah-Hartman
maintainerPATCH 41/428 r8169: disable EEE on RTL8168h/8111h
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oleksij Rempel <[email protected]>
commit 3cdeaef1754ab8155cdd828c958ada3d36e9ad9a upstream.
Force EEE off on the RTL8168h/8111h (RTL_GIGA_MAC_VER_46) at PHY connect with phy_disable_eee().
Commit 202fef9bbbf5 ("net: phy: realtek: fix EEE advertisement write on the internal PHY MMD path") made EEE actually advertise on the generic Realtek PHY; the write had been a no-op before. On the RTL8168h that un-masks a latent defect: once EEE negotiates, RX silently stalls after ~7-20 minutes. The carrier stays up, no counter or dmesg moves, and only "ip link set down/up" recovers it; disabling EEE keeps the link stable.
Root-causing the RTL8168h LPI/RX path needs hardware not available now, so disable EEE for this version. Use phy_disable_eee() rather than dropping the version from rtl_supports_eee(): the latter also skips rtl_enable_tx_lpi(), whose disable branch clears the MAC TX-LPI bits (ERI 0x1b0[1:0]) on link up. rtl_hw_start_8168h_1() does not clear them (the RTL8402/RTL8106e init does), so a warm reboot from an EEE-active state could otherwise leave TX-LPI asserted while the PHY no longer negotiates EEE. Keeping the version EEE-capable preserves that clear path. This also covers the RTL8168M, which shares RTL_GIGA_MAC_VER_46.
--- drivers/net/ethernet/realtek/r8169_main.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/net/ethernet/realtek/r8169_main.c +6 -0
@@ -5484,6 +5484,12 @@ static int r8169_mdio_register(struct rtphy_disable_eee_mode (tp->phydev, ETHTOOL_LINK_MODE_2500baseT_Full_BIT); +/* Keep EEE off but the version stays EEE-capable so that link-up +* still clears the MAC TX-LPI bits. +*/ +if (tp->mac_version ==RTL_GIGA_MAC_VER_46 ) +phy_disable_eee (tp->phydev); +/* PHY will be woken up in rtl_open() */ phy_suspend (tp->phydev);
Greg Kroah-Hartman
maintainerPATCH 42/428 random: vDSO: avoid call to memset() when zeroing reserved parameter
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nathan Chancellor <[email protected]>
commit eb13a1ff271b0d180687eebb30611b0b276d5193 upstream.
After a recent change in LLVM [1], builds with the random vDSO implementation, such as PowerPC and RISC-V, fail when checking the vDSO:
arch/powerpc/kernel/vdso/vdso32.so.dbg: dynamic relocations are not supported arch/riscv/kernel/vdso/vdso.so.dbg: dynamic relocations are not supported
memset() is now generated when zeroing params->reserved for some builds because LLVM has an optimization (now run in more instances) that can recognize at compile time when it is assigning a static value to a contiguous area of memory and turn that into a call to memset(). Both clang and GCC assume memset() is always available [2].
Clang has an internal fiddly hook, -max-store-memset, which we can set to a high number, to disable generating out of line memset calls [3]. Similarly, GCC has -finline-stringops=memset to do the same [4], should this issue ever hit future version of GCC. While these options wouldn't make sense for normal kernel code, it is fine for the extremely limited and intentionally compact vDSO code.
--- arch/arm64/kernel/vdso/Makefile | 2 +- arch/loongarch/vdso/Makefile | 1 + arch/powerpc/kernel/vdso/Makefile | 1 + arch/riscv/kernel/vdso/Makefile | 1 + arch/s390/kernel/vdso/Makefile | 1 + arch/x86/entry/vdso/vdso64/Makefile | 2 +- init/Kconfig | 5 +++++ 7 files changed, 11 insertions(+), 2 deletions(-)
arch/arm64/kernel/vdso/Makefile +1 -1
@@ -41,7 +41,7 @@ CC_FLAGS_REMOVE_VDSO := $(CC_FLAGS_FTRAC $(CC_FLAGS_LTO) $(CC_FLAGS_CFI) \ -Wmissing-prototypes -Wmissing-declarations -CC_FLAGS_ADD_VDSO := -O2 -mcmodel=tiny -fasynchronous-unwind-tables +CC_FLAGS_ADD_VDSO := -O2 -mcmodel=tiny -fasynchronous-unwind-tables $(CONFIG_CC_OPT_INLINE_MEMSET) CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_REMOVE_VDSO) CFLAGS_REMOVE_vgetrandom.o = $(CC_FLAGS_REMOVE_VDSO)
arch/loongarch/vdso/Makefile +1 -0
@@ -16,6 +16,7 @@ ccflags-vdso := \ $(filter -m64,$(KBUILD_CFLAGS)) \ $(filter -march=%,$(KBUILD_CFLAGS)) \ $(filter -m%-float,$(KBUILD_CFLAGS)) \ + $(CONFIG_CC_OPT_INLINE_MEMSET) \ $(CLANG_FLAGS) \ -D__VDSO__
arch/powerpc/kernel/vdso/Makefile +1 -0
@@ -43,6 +43,7 @@ ccflags-y := -fno-common -fno-builtin -D ccflags-y += $(DISABLE_LATENT_ENTROPY_PLUGIN) ccflags-y += $(call cc-option, -fno-stack-protector) ccflags-y += -DDISABLE_BRANCH_PROFILING +ccflags-y += $(CONFIG_CC_OPT_INLINE_MEMSET) ccflags-y += -ffreestanding -fasynchronous-unwind-tables ccflags-remove-y := $(CC_FLAGS_FTRACE) ldflags-y := -Wl,--hash-style=both -nostdlib -shared -z noexecstack $(CLANG_FLAGS)
arch/riscv/kernel/vdso/Makefile +1 -0
@@ -36,6 +36,7 @@ endif ccflags-y := -fno-stack-protector ccflags-y += -DDISABLE_BRANCH_PROFILING ccflags-y += -fno-builtin +ccflags-y += $(CONFIG_CC_OPT_INLINE_MEMSET) ccflags-y += $(KBUILD_BASE_ISA)$(CFI_MARCH) ccflags-y += $(CFI_FULL) asflags-y += $(KBUILD_BASE_ISA)$(CFI_MARCH)
arch/s390/kernel/vdso/Makefile +1 -0
@@ -29,6 +29,7 @@ KBUILD_CFLAGS_VDSO := $(filter-out -muna KBUILD_CFLAGS_VDSO := $(filter-out -fno-asynchronous-unwind-tables,$(KBUILD_CFLAGS_VDSO)) KBUILD_CFLAGS_VDSO += -fPIC -fno-common -fno-builtin -fasynchronous-unwind-tables KBUILD_CFLAGS_VDSO += -fno-stack-protector $(DISABLE_KSTACK_ERASE) +KBUILD_CFLAGS_VDSO += $(CONFIG_CC_OPT_INLINE_MEMSET) ldflags-y := -shared -soname=linux-vdso.so.1 \ --hash-style=both --build-id=sha1 \ $(call ld-option, --eh-frame-hdr) -T
arch/x86/entry/vdso/vdso64/Makefile +1 -1
@@ -14,7 +14,7 @@ vobjs-$(CONFIG_X86_SGX) += vsgx.o vobjs-$(CONFIG_FUTEX_ROBUST_UNLOCK) += vfutex.o # Compilation flags -flags-y := -DBUILD_VDSO64 -m64 -mcmodel=small +flags-y := -DBUILD_VDSO64 -m64 -mcmodel=small $(CONFIG_CC_OPT_INLINE_MEMSET) # The location of this include matters! include $(src)/../common/Makefile.include
init/Kconfig +5 -0
@@ -173,6 +173,11 @@ config CC_HAS_ALLOC_TOKEN config CC_HAS_MULTIDIMENSIONAL_NONSTRING def_bool $(success,echo 'char tag[][4] __attribute__((__nonstring__)) = { };' | $(CC) $(CLANG_FLAGS) -x c - -c -o /dev/null -Werror) +config CC_OPT_INLINE_MEMSET + string + default "-finline-stringops=memset" if $(cc-option,-finline-stringops=memset) + default "-mllvm -max-store-memset=4294967294" if $(cc-option,-mllvm -max-store-memset=4294967294) + config LD_CAN_USE_KEEP_IN_OVERLAY # ld.lld prior to 21.0.0 did not support KEEP within an overlay description # https://github.com/llvm/llvm-project/pull/130661
Greg Kroah-Hartman
maintainerPATCH 43/428 rtc: ac100: Assign .num before accessing .hws
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aamir Ahmed <[email protected]>
commit 6a4117eee82dd85f11bf898bf66026764011eeb6 upstream.
Commit f316cdff8d67 ("clk: Annotate struct clk_hw_onecell_data with __counted_by") annotated the hws member of 'struct clk_hw_onecell_data' with __counted_by, which informs the bounds sanitizer (UBSAN_BOUNDS) about the number of elements in .hws[], so that it can warn when .hws[] is accessed out of bounds. As noted in that change, the __counted_by member must be initialized with the number of elements before the first array access happens, otherwise there will be a warning from each access prior to the initialization because the number of elements is zero. This occurs in ac100_rtc_register_clks() due to .num being assigned only after every clkout clock has been stored in .hws[]. With CONFIG_UBSAN_BOUNDS and a compiler that implements __counted_by (GCC 15.1+ or Clang 20.1+), this triggers an array-index-out-of-bounds report during probe, and with CONFIG_UBSAN_TRAP the first store traps.
Initialize .num with AC100_CLKOUT_NUM, the number of elements .hws[] was allocated with, right after the allocation. That is the value the loop counter ends up at on the success path anyway, so the provider's behaviour is unchanged.
--- drivers/rtc/rtc-ac100.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/rtc/rtc-ac100.c +2 -1
@@ -317,6 +317,8 @@ static int ac100_rtc_register_clks(strucif (!chip->clk_data)return -ENOMEM ; + chip->clk_data->num =AC100_CLKOUT_NUM ; + chip->rtc_32k_clk = clk_hw_register_fixed_rate(chip->dev, AC100_RTC_32K_NAME, NULL, 0,
@@ -360,7 +362,6 @@ static int ac100_rtc_register_clks(struc chip->clk_data->hws[i] = &clk->hw; } - chip->clk_data->num = i; ret =of_clk_add_hw_provider (np, of_clk_hw_onecell_get, chip->clk_data);if (ret) goto err_unregister_rtc_32k;
Greg Kroah-Hartman
maintainerPATCH 44/428 rtc: spear: initialize IRQ state before requesting alarm IRQ
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Runyu Xiao <[email protected]>
commit 055ef5ce9f67a6a3a1363fa663007f8196cc0fb8 upstream.
devm_request_irq() enables the interrupt before it returns, so the handler may run while probe is still initializing the device. Initialize the MMIO address and spinlock before requesting the alarm IRQ.
--- drivers/rtc/rtc-spear.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
drivers/rtc/rtc-spear.c +6 -5
@@ -363,6 +363,12 @@ static int spear_rtc_probe(struct platfoif (irq <0 )return irq; + config->ioaddr =devm_platform_ioremap_resource (pdev,0 ); +if (IS_ERR (config->ioaddr)) +return PTR_ERR (config->ioaddr); + +spin_lock_init (&config->lock); + status =devm_request_irq (&pdev->dev, irq, spear_rtc_irq,0 , pdev->name, config);if (status) {
@@ -371,10 +377,6 @@ static int spear_rtc_probe(struct platforeturn status; } - config->ioaddr =devm_platform_ioremap_resource (pdev,0 ); -if (IS_ERR (config->ioaddr)) -return PTR_ERR (config->ioaddr); - config->clk =devm_clk_get (&pdev->dev,NULL );if (IS_ERR (config->clk))return PTR_ERR (config->clk);
@@ -383,7 +385,6 @@ static int spear_rtc_probe(struct platfoif (status <0 )return status; -spin_lock_init (&config->lock);platform_set_drvdata (pdev, config); config->rtc->ops = &spear_rtc_ops;
Greg Kroah-Hartman
maintainerPATCH 45/428 sctp: check RCV_SHUTDOWN after the sendmsg connect wait
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jun Yang <[email protected]>
commit 4f1da630d13de0370e2f6361f961f1c8b384af1c upstream.
sctp_wait_for_connect() drops the socket lock while it sleeps. An out-of-the-blue ABORT can then be processed from the socket backlog and unlink the association. If a concurrent shutdown(fd, SHUT_RD) sets RCV_SHUTDOWN, the waiter breaks with err == 0 before checking asoc->base.dead. Its final sctp_association_put() can then free the association, leaving sctp_sendmsg_to_asoc() to continue with a dangling pointer.
Check RCV_SHUTDOWN along with the wait error in sctp_sendmsg_to_asoc() before using the association again. The check only accesses the socket, so it needs no additional association reference. Return the existing -ESRCH so that sctp_sendmsg() skips freeing a new association that may already have been destroyed.
Keep sctp_wait_for_connect() unchanged to preserve its behavior for the connect() caller.
--- net/sctp/socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/sctp/socket.c +1 -1
@@ -1844,7 +1844,7 @@ static int sctp_sendmsg_to_asoc(struct sif (asoc->ep->intl_enable) { timeo =sock_sndtimeo (sk,0 ); err =sctp_wait_for_connect (asoc, &timeo); -if (err) { +if (err || sk->sk_shutdown &RCV_SHUTDOWN ) { err = -ESRCH ; goto err; }
Greg Kroah-Hartman
maintainerPATCH 46/428 sysctl: Negate before converting in the int read path
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhan Xusheng <[email protected]>
commit e955f14fa8467d70aaeea5830b4d1773d5b25500 upstream.
proc_int_k2u_conv_kop() reports the sign through *negp and the magnitude through *u_ptr, but for a negative value it hands the sign-extended int to the converter and negates the result:
*u_ptr = k_ptr_op ? -k_ptr_op((ulong)val) : -(ulong)val;
With div_hz() and CONFIG_HZ=1000 a stored -1000 becomes (ulong)-1000 / 1000 == 18446744073709550, and negating that wraps:
# echo -1 > /proc/sys/net/ipv4/tcp_fin_timeout # cat /proc/sys/net/ipv4/tcp_fin_timeout -18428297329635842066
The magnitude is HZ dependent but the wrap is not: the negation happens after the division at every CONFIG_HZ.
Take the magnitude first and convert that, which is what the open-coded version did before commit 2dc164a48e6f ("sysctl: Create converter functions with two new macros") folded it into a macro. The k_ptr_op == NULL branch was already correct.
All three int converters that pass a k_ptr_op are affected:proc_dointvec_jiffies(), proc_dointvec_userhz_jiffies() and proc_dointvec_ms_jiffies().
--- kernel/sysctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/sysctl.c +1 -1
@@ -478,7 +478,7 @@ int proc_int_k2u_conv_kop(ulong *u_ptr,if (val <0 ) { *negp = true; - *u_ptr = k_ptr_op ? -k_ptr_op ((ulong )val) : -(ulong )val; + *u_ptr = k_ptr_op ?k_ptr_op (-(ulong )val) : -(ulong )val; }else { *negp = false; *u_ptr = k_ptr_op ?k_ptr_op ((ulong )val) : (ulong ) val;
Greg Kroah-Hartman
maintainerPATCH 47/428 time/jiffies: Saturate in mult_hz() instead of wrapping
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhan Xusheng <[email protected]>
commit fdd6553e1e53b0421d89c7469c8a36d2eadb1115 upstream.
Return ULONG_MAX for values that don't fit an unsigned long. proc_int_u2k_conv_uop() now correctly rejects a result above INT_MAX.
This is the erroneous behaviour that is being fixed. The input has to exceed ULONG_MAX / HZ for the product to wrap, so the value below is specific to CONFIG_HZ=1000:
# echo 18446744073709552 > /proc/sys/net/ipv4/tcp_keepalive_time # cat /proc/sys/net/ipv4/tcp_keepalive_time 0
That value is now rejected with an error.
The original bound ("*u_ptr > INT_MAX / HZ") was removed in commit 2dc164a48e6f ("sysctl: Create converter functions with two new macros").
--- kernel/time/jiffies.c | 2 ++ 1 file changed, 2 insertions(+)
kernel/time/jiffies.c +2 -0
@@ -101,6 +101,8 @@ void __init register_refined_jiffies(lon#ifdef CONFIG_PROC_SYSCTL static ulong mult_hz (const ulong val) { +if (val >=ULONG_MAX /HZ ) +return ULONG_MAX ;return val *HZ ; }
Greg Kroah-Hartman
maintainerPATCH 48/428 tpm: Disable TPM on null key name mismatch
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Surendran Kanagaraj <[email protected]>
commit 015fb29a748342a186f37b602ac70017098c8251 upstream.
The null key name check exists to protect against TPM reset attacks, so a mismatch should stop the device from serving further requests. Currently it does not disable the chip when it finds a mismatch.
The mismatch is logged:
tpm tpm0: null key integrity check failed
but the chip keeps serving commands:
/ # tpm2_getcap -c properties-fixed
TPM_PT_FAMILY_INDICATOR:
as UINT32: 0x08322e3000
as string: "2.0"
...
tpm2_load_null() where the null key name check is run sets the chip as disabled only if the rc is non zero. When the mismatch is seen, rc is zero at that point and it returns success. The other issue is that the caller expects the null key handle to be populated when the function returns 0 which it does here without writing the handle and proceeds assuming the null key handle is valid.
During the test, I noticed that tpm2_start_auth_session() uses the uninitialized stack value as the key handle since tpm2_load_null() returns 0 despite the integrity failure and proceeds with TPM2_CC_START_AUTH_SESS with this value as salt key handle.
Set rc to -ENODEV on the mismatch. The error path then disables the chip and returns the correct code to the caller.
Tested in QEMU with swtpm and CONFIG_TCG_TPM2_HMAC=y by making TPM2_CC_CONTEXT_LOAD fail with TPM2_RC_INTEGRITY and changing the name of the re-created null key. The chip is now disabled on the mismatch.
--- drivers/char/tpm/tpm2-sessions.c | 1 + 1 file changed, 1 insertion(+)
drivers/char/tpm/tpm2-sessions.c +1 -0
@@ -985,6 +985,7 @@ static int tpm2_load_null(struct tpm_chi/* Deduce from the name change TPM interference: */ dev_err (&chip->dev,"null key integrity check failed\n" );tpm2_flush_context (chip, tmp_null_key); + rc = -ENODEV ; err:if (rc) {
Greg Kroah-Hartman
maintainerPATCH 49/428 netfs: clear post-EOF pagecache when extending a file via write
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paulo Alcantara <[email protected]>
commit 69bf14300b50631e7c2271289d347bbd1b19a06c upstream.
Fix netfs to erase the contents of a hole created after the EOF by an ordinary write if dirty data has been previously left there by writes through an mmapped region. Neither the buffered nor the unbuffered/DIO write path clears that stale pagecache.
Zero the tail of the folio straddling the EOF before an extending write. That is the only folio that can hold data written past the EOF through an mmap, as pages wholly beyond the EOF can't be faulted in. The folio is zeroed rather than dropped so a concurrent extending write can't lose data.
Both write paths downgrade the i_rwsem to shared, so extending writes can run concurrently and the i_size read by the caller may be stale by the time the folio is locked. Re-read i_size under the folio lock and clamp the zeroed range up to it, so a racing write that already put data into the folio isn't clobbered.
Wait for any writeback on the folio to finish before zeroing it so that the pagecache isn't modified while it may still be read by the transport during transmission. Honour IOCB_NOWAIT by returning -EAGAIN rather than blocking on the folio lock, on writeback, or in folio_mkclean()'s rmap walk when the folio is mapped.
truncate_pagecache() can't be used here: it must be called with the i_rwsem held exclusively, but these write paths only hold it shared, and it would block unconditionally, breaking IOCB_NOWAIT.
Callers that hold i_rwsem exclusively for the whole resize (truncate, setattr, fallocate, clone) exclude any genuine concurrent buffered writer, so staleness can instead be decided from the folio's dirty state, as pagecache_isize_extended() already does for filesystems that serialise writes against truncate/setattr via a single i_rwsem. Export netfs_clear_stale_post_isize() helper to handle such case.
The helper is required by the CIFS client to fix generic/363.
--- Documentation/filesystems/netfs_library.rst | 26 +++++++ fs/netfs/buffered_write.c | 9 ++ fs/netfs/direct_write.c | 9 ++ fs/netfs/internal.h | 2 fs/netfs/misc.c | 99 ++++++++++++++++++++++++++++ include/linux/netfs.h | 2 6 files changed, 147 insertions(+)
Documentation/filesystems/netfs_library.rst +26 -0
@@ -451,6 +451,32 @@ one. The inode should be marked ``NETFS_ICTX_SINGLE_NO_UPLOAD`` if this API is to be used. The writeback function requires the buffer to be of ITER_FOLIOQ type. +Clearing Stale Post-EOF Pagecache +--------------------------------- + +When a file is extended, data left in the pagecache past the old EOF by a write +through an mmap must not be exposed as file content. Netfslib clears this on +its own write paths, and exports a helper so a filesystem can do the same from +a resize path (truncate, setattr, fallocate and the like) that holds the +inode's ``i_rwsem`` exclusively across the whole resize:: + + void netfs_clear_stale_post_isize(struct inode *inode, uoff_t from, + uoff_t to); + +This zeroes any such data within the ``[from, to)`` hole to be made, where +@from is the old EOF and @to is the new one, and the caller must have already +updated ``i_size`` to @to before calling it. Only the folio straddling @from +can hold data written past the EOF through an mmap, as pages wholly beyond the +EOF can't be faulted in, so the zeroing is limited to that folio. The folio is +zeroed rather than dropped so that a concurrent extending write can't lose +data. + +This overlaps with ``pagecache_isize_extended()`` but can't reuse it: that +helper is keyed on a sub-page block size and is a no-op when the block size is +``>= PAGE_SIZE`` (as on network filesystems), and it doesn't wait for +writeback. As both address the same problem, a change to one should probably +be reflected in the other to keep them in sync. + High-Level VM API ==================
fs/netfs/buffered_write.c +9 -0
@@ -469,6 +469,7 @@ ssize_t netfs_buffered_write_iter_locked struct netfs_group *netfs_group) {struct file *file = iocb->ki_filp; +struct inode *inode =file_inode (file);ssize_t ret;trace_netfs_write_iter (iocb, from);
@@ -481,6 +482,14 @@ ssize_t netfs_buffered_write_iter_lockedif (ret)return ret; +if (iocb->ki_pos >i_size_read (inode)) { + ret =netfs_clear_stale_pre_isize (inode,i_size_read (inode), + iocb->ki_pos, + iocb->ki_flags &IOCB_NOWAIT ); +if (ret) +return ret; + } +return netfs_perform_write (iocb, from, netfs_group); }EXPORT_SYMBOL (netfs_buffered_write_iter_locked);
fs/netfs/direct_write.c +9 -0
@@ -359,6 +359,15 @@ ssize_t netfs_unbuffered_write_iter(stru ret =file_update_time (file);if (ret <0 ) goto out; + +if (iocb->ki_pos >i_size_read (inode)) { + ret =netfs_clear_stale_pre_isize (inode,i_size_read (inode), + iocb->ki_pos, + iocb->ki_flags &IOCB_NOWAIT ); +if (ret <0 ) + goto out; + } +if (iocb->ki_flags &IOCB_NOWAIT ) {/* We could block if there are any pages in the range. */ ret = -EAGAIN ;
fs/netfs/internal.h +2 -0
@@ -80,6 +80,8 @@ ssize_t netfs_wait_for_write(struct netfvoid netfs_wait_for_paused_read (struct netfs_io_request *rreq);void netfs_wait_for_paused_write (struct netfs_io_request *rreq);void netfs_wait_for_put_ra_refs (struct netfs_io_request *rreq); +int netfs_clear_stale_pre_isize (struct inode *inode,uoff_t from, +uoff_t to,bool nowait);/* * objects.c
fs/netfs/misc.c +99 -0
108 lines not on this page · raw message
include/linux/netfs.h +2 -0
@@ -406,6 +406,8 @@ ssize_t netfs_unbuffered_write_iter(strussize_t netfs_unbuffered_write_iter_locked (struct kiocb *iocb,struct iov_iter *iter,struct netfs_group *netfs_group);ssize_t netfs_file_write_iter (struct kiocb *iocb,struct iov_iter *from); +void netfs_clear_stale_post_isize (struct inode *inode,uoff_t from, +uoff_t to);/* Single, monolithic object read/write API. */ void netfs_single_mark_inode_dirty (struct inode *inode);
Greg Kroah-Hartman
maintainerPATCH 50/428 netfs: zero gaps in read-gaps folio to avoid writing back stale data
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paulo Alcantara <[email protected]>
commit 8db55c5cd831a786a1a2a2d391aa80354535a353 upstream.
netfs_read_gaps() leaves gaps around a streaming write's dirty region unread on the server side, so a short/EOF response there left stale folio content that later got written back.
Zero it after the read completes, not before: netfs_wait_for_read() returns rreq->transferred once ret >= 0, so build an iterator over the same bvec array the read used, advance past ret, and zero the rest. The dirty region already maps to sink pages in that array rather than the real folio, so this can't touch it, and only the actual shortfall gets zeroed instead of the whole gap upfront.
--- fs/netfs/buffered_read.c | 7 +++++++ 1 file changed, 7 insertions(+)
fs/netfs/buffered_read.c +7 -0
@@ -541,6 +541,13 @@ static int netfs_read_gaps(struct file * ret =netfs_wait_for_read (rreq);if (ret >=0 ) { +if (ret < flen) { +struct iov_iter iter; + +iov_iter_bvec (&iter,ITER_DEST , bvec, i, flen); +iov_iter_advance (&iter, ret); +iov_iter_zero (flen - ret, &iter); + }if (group)folio_change_private (folio, group);else
Greg Kroah-Hartman
maintainerPATCH 51/428 netfs: zero the tail of a short DIO/unbuffered read
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paulo Alcantara <[email protected]>
commit dd05add7b2b6004c5fa3a1f276f56d8668f86b65 upstream.
The buffered read collector zero-fills the tail of a short read that stops below the inode's i_size (netfs_clear_unread()), so a read that races an extending write still returns the expected number of bytes. The non-buffered collector path does no such thing: it just records how much was transferred.
Add the same zero-fill for the non-buffered case, gated onNETFS_SREQ_CLEAR_TAIL: a subreq's source sets that flag when a short result from it is known to be safe to treat as a hole, as opposed to NETFS_SREQ_HIT_EOF, which means the read genuinely ran off the end of the file and should be reported short as-is. Only CLEAR_TAIL should zero-fill here; a real EOF must stay a real short read.
No source currently sets CLEAR_TAIL on an unbuffered/DIO subrequest, so this is inert on its own -- a following change teaches cifs to set it in the one case that needs it.
--- fs/netfs/read_collect.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+)
fs/netfs/read_collect.c +24 -0
@@ -33,6 +33,22 @@ static void netfs_clear_unread(struct ne__set_bit (NETFS_SREQ_HIT_EOF , &subreq->flags); } +static void netfs_clear_unread_dio (struct netfs_io_subrequest *subreq) +{ +uoff_t pos = subreq->start + subreq->transferred; +struct netfs_io_request *rreq = subreq->rreq; +size_t fill; + +if (pos >= rreq->i_size) +return ; + + fill =min_t (uoff_t, rreq->i_size - pos, + subreq->len - subreq->transferred); + +netfs_reset_iter (subreq); + subreq->transferred +=iov_iter_zero (fill, &subreq->io_iter); +} +/* * Cancel the copy-to-cache mark on a folio. */
@@ -311,6 +327,14 @@ reassess: test_bit(NETFS_SREQ_HIT_EOF, &front->flags))netfs_read_unlock_folios (rreq, ¬es); }else { +if (!(notes &HIT_PENDING ) && + front->error ==0 && + transferred < front->len && +test_bit (NETFS_SREQ_CLEAR_TAIL , &front->flags)) { +netfs_clear_unread_dio (front); + transferred = front->transferred; +trace_netfs_sreq (front, netfs_sreq_trace_clear); + } stream->collected_to = front->start + transferred; rreq->collected_to = stream->collected_to; }
Greg Kroah-Hartman
maintainerPATCH 52/428 module: fix lost error code from codetag_load_module()
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hao Ge <[email protected]>
commit c79cf15eb35a4c703bf18f8c33c47e80dd660f8e upstream.
If codetag_load_module() fails, err is not set to reflect the failure and load_module() returns 0 after the module has been torn down.
Also, if the module is a livepatch, mod->klp_info allocated by copy_module_elf() leaks on this error path. Free it via a new livepatch_cleanup label.
--- kernel/module/main.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
kernel/module/main.c +6 -2
@@ -3580,8 +3580,9 @@ static int load_module(struct load_info goto sysfs_cleanup; } -if (codetag_load_module (mod)) - goto sysfs_cleanup; + err =codetag_load_module (mod); +if (err) + goto livepatch_cleanup;/* Get rid of temporary copy. */ free_copy (info, flags);
@@ -3591,6 +3592,9 @@ static int load_module(struct load_inforeturn do_init_module (mod); + livepatch_cleanup: +if (is_livepatch_module (mod)) +free_module_elf (mod); sysfs_cleanup:mod_sysfs_teardown (mod); coming_cleanup:
Greg Kroah-Hartman
maintainerPATCH 53/428 virt: vmgenid: remap memory as decrypted
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vitaly Kuznetsov <[email protected]>
commit 1b48c13075829ee4961feeabd816dac1c9111959 upstream.
It was found that AWS SEV-SNP enabled instances are not able to boot with commit 81256a50aa0f ("x86/mm: Make memremap(MEMREMAP_WB) map memory as encrypted by default") applied and the reason seems to be the vmgenid device which requires unencrypted writeable memory.
A similar problem was previously fixed in DRM with commit 7dfede7d7edd ("drm/vmwgfx: Fix guests running with TDX/SEV").
Note, trusting vmgenid device in a Confidential VM is questionable: the malicious host may intentionally avoid notifying the guest when a copy is created.
--- drivers/virt/vmgenid.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/virt/vmgenid.c +2 -1
@@ -75,7 +75,8 @@ static int vmgenid_add_acpi(struct devic phys_addr = (obj->package.elements[0 ].integer.value <<0 ) | (obj->package.elements[1 ].integer.value <<32 ); - virt_addr =devm_memremap (&device->dev, phys_addr,VMGENID_SIZE ,MEMREMAP_WB ); + virt_addr =devm_memremap (&device->dev, phys_addr,VMGENID_SIZE , +MEMREMAP_WB |MEMREMAP_DEC );if (IS_ERR (virt_addr)) { ret =PTR_ERR (virt_addr); goto out;
Greg Kroah-Hartman
maintainerPATCH 54/428 virt: vmgenid: set driver_data before registering notification handlers
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhichen Wang <[email protected]>
commit 9f8139c6145cf17d690d6c414d43b4c0bef632fb upstream.
Both probe paths register their notification handler before assigning driver_data, which the handler dereferences.
In the devicetree path, the notification IRQ can fire as soon as devm_request_irq() registers the handler: the interrupt may already be pending at probe time, for example when a VMM injects the generation-changed notification while restoring a guest from a snapshot that was taken before the driver had probed (Firecracker does exactly this on snapshot restore). The IRQ is also requested with IRQF_SHARED, so another device sharing the line can trigger the handler just as early. The handler then calls vmgenid_notify(), which dereferences the still-NULL driver_data and panics:
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000010 CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted 6.18.38+ #1 PREEMPT(none) Hardware name: linux,dummy-virt (DT) pc : vmgenid_notify.isra.0+0x24/0x8c lr : vmgenid_of_irq_handler+0x14/0x34 Call trace: vmgenid_notify.isra.0+0x24/0x8c (P) vmgenid_of_irq_handler+0x14/0x34 __handle_irq_event_percpu+0x44/0x1bc handle_irq_event+0x4c/0xb4 handle_fasteoi_irq+0xf8/0x1f8
The ACPI path has the same ordering problem: the handler is installed with acpi_install_notify_handler() before driver_data is assigned. ACPI notifications are dispatched asynchronously from a workqueue, so the window is narrow, but a notification arriving between the two calls hits the same NULL dereference.
Assign driver_data before registering the handlers. The state is fully initialized at that point, so the handlers are safe to run. Should registration fail, the probe error path leaves no dangling pointer
behind: the driver core clears driver_data in device_unbind_cleanup().
--- drivers/virt/vmgenid.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/virt/vmgenid.c +4 -2
@@ -83,6 +83,8 @@ static int vmgenid_add_acpi(struct devic }setup_vmgenid_state (state, virt_addr); + dev->driver_data = state; + status =acpi_install_notify_handler (device->handle,ACPI_DEVICE_NOTIFY , vmgenid_acpi_handler, dev);if (ACPI_FAILURE (status)) {
@@ -90,7 +92,6 @@ static int vmgenid_add_acpi(struct devic goto out; } - dev->driver_data = state; out:ACPI_FREE (parsed.pointer);return ret;
@@ -124,12 +125,13 @@ static int vmgenid_add_of(struct platforif (ret <0 )return ret; + pdev->dev.driver_data = state; + ret =devm_request_irq (&pdev->dev, ret, vmgenid_of_irq_handler,IRQF_SHARED ,"vmgenid" , &pdev->dev);if (ret <0 )return ret; - pdev->dev.driver_data = state;return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 55/428 mm/damon/core: dont skip damos_adjust_quota() while esz is not zero
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: SJ Park <[email protected]>
commit 52ae167ce16609c7e6fffef588b3c2c26de2db19 upstream.
DAMOS could unexpectedly stop working when a user disables quota using the online parameters commit feature. Fix it by correcting a wrong quota unset check in damos_adjust_quota().
DAMON users could disable all quotas by unsetting time and size quotas, and removing all quota goals. The intention of disabling quotas would be making DAMOS run at full speed. When such quota disabled setup is detected, damos_adjust_quota() skips all its work. The skipped works include effective size quota (damos_quota->esz) updates and charged quota amount (damos_quota->charged_sz) resets. The intention is to avoid doing unnecessary work when quotas are disabled.
However, users could do the setup while effective size quota is non-zero, by doing the disabling with the online DAMON parameters commit feature. In this case, because the effective size quota exists, DAMOS will keep working with the quota until it is fully charged. After the effective quota is fully charged, the charged quota amount (damos_quota->charged_sz) cannot be reset because damos_adjust_quota() skips it. Then, DAMOS stops working until the quota is newly set or DAMON is entirely restarted.
The problem happens because damos_adjust_quota() assumes the user setup for disabling quota immediately disabled it. In reality, the quota is still working until the effective size quota is also updated to zero. Other logic for catching that uses damos_quota_is_set(), which understands the fact and therefore checks the effective size quota in addition to the user setup. Fix the issue by using damos_quota_is_set() in damos_adjust_quota() to determine if its works should be skipped.
The user impact is a non-deterministic and unexpected DAMOS stop behavior. That is, users would disable quotas using the online parameters commit feature, expecting DAMOS will run at full speed. However, depending on the timing, the setup can be updated while the effective size quota is non-zero. Due to the above mentioned internal mechanism, DAMOS stops working instead of running at full speed. It is unexpected behavior. It is also non-deterministic because sometimes the setup is done when the effective size quota is zero, depending on the timing. It doesn't cause critical issues like crashes or leaks. Users can simply set a reasonable quota again, or restart DAMON. But definitely it is an unexpected and non-deterministic behavior that makes it difficult to reliably use. Also investigating the root cause of the behavior would be quite difficult.
--- mm/damon/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
mm/damon/core.c +1 -1
@@ -2949,7 +2949,7 @@ static void damos_adjust_quota(struct daunsigned long cumulated_sz, cached_esz;unsigned int score, max_score =0 ; -if (!quota->ms && !quota->sz &&list_empty ("a->goals)) +if (!damos_quota_is_set (quota))return ;/* First charge window */
Greg Kroah-Hartman
maintainerPATCH 56/428 mm/vma: predicate setting mmap_prepare VMA fields on new vma alloc
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Stoakes (ARM) <[email protected]>
commit 976d5e0ddac885b0219252f004f6c561c344df9d upstream.
It only makes sense to manipulate VMA fields if a new VMA was allocated, rather than merged.
VMA merging does not compare vm_ops or vm_private_data, so a merged VMA keeps its own, which is also what the legacy f_op->mmap path does since it never touches an existing VMA.
Currently, these fields will get overwritten by whatever state is established in the mmap_prepare hook, and if the VMA was merged, vm_ops->mapped will not have been called, so this could destructively clear existing state without replacing it with anything valid.
There is an implicit requirement that vm_private_data and vm_ops are fungible across VMAs which means that losing the 'new' state is fine.
However in this case the 'old' state is being overwritten by potentially invalid 'new' state, so this must be rectified.
Additionally constify have_mmap_prepare while here.
All existing in-tree users either derive state from the file or are unmergeable due to VMA flags, so this has no direct impact.
--- mm/vma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
mm/vma.c +2 -2
@@ -2745,7 +2745,7 @@ static unsigned long __mmap_region(struc {struct mm_struct *mm = current->mm;struct vm_area_struct *vma =NULL ; -bool have_mmap_prepare = file && file->f_op->mmap_prepare; +const bool have_mmap_prepare = file && file->f_op->mmap_prepare;VMA_ITERATOR (vmi, mm, addr);MMAP_STATE (map, mm, &vmi, addr, len, pgoff, vma_flags, file);struct vm_area_desc desc = {
@@ -2787,7 +2787,7 @@ static unsigned long __mmap_region(struc allocated_new = true; } -if (have_mmap_prepare) +if (have_mmap_prepare && allocated_new)set_vma_user_defined_fields (vma, &map);__mmap_complete (&map, vma);
Greg Kroah-Hartman
maintainerPATCH 57/428 mm: shmem: ignore sysfs configs for shmem forced collapse
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baolin Wang <[email protected]>
commit 72c3d682c165b836b54a3d07a01f72e39c47022c upstream.
According to Documentation/mm/transhuge.rst, MADV_COLLAPSE is expected to ignore any THP or mTHP interface settings.
However, after commit 26c7d8413aaf ("mm: thp: support "THPeligible" semantics for mTHP with anonymous shmem"), performing MADV_COLLAPSE on shmem will depend on /sys/.../hugepages-2048kB/shmem_enabled being set to "inherit" (although that is the default), which can cause MADV_COLLAPSE to fail unexpectedly.
This could cause a userspace-visible performance regression.
Fix this by returning the result of shmem_huge_global_enabled() directly when MADV_COLLAPSE is requested, allowing PMD-order collapse while ignoring shmem THP/mTHP settings.
--- mm/shmem.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
mm/shmem.c +5 -2
@@ -1831,8 +1831,11 @@ unsigned long shmem_allowable_huge_order global_orders =shmem_huge_global_enabled (inode, index, write_end, shmem_huge_force, vma, vm_flags); -/* Tmpfs huge pages allocation */ -if (!vma || !vma_is_anon_shmem (vma)) +/* +* Tmpfs huge pages allocation or forced collapse ignores +* sysfs configs. +*/ +if (!vma || !vma_is_anon_shmem (vma) || shmem_huge_force)return global_orders;/*
Greg Kroah-Hartman
maintainerPATCH 58/428 vc_screen: reload vc pointer before if (ret) in vcs_write() to avoid UAF
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yi Yang <[email protected]>
commit 226bd5603371cd9f6642cbb9e9a677f445de3530 upstream.
The reload of 'vc' added by commit 8fb9ea65c9d1 ("vc_screen: reload load of struct vc_data pointer in vcs_write() to avoid UAF") sits after the 'if (ret)' block, so the copy-failure break path exits the loop without reloading vc. If the vc was kfree()'d via vc_port_destruct during the unlocked copy_from_user() window, the post-loop
'if (written && vc) vcs_scr_updated(vc)' is reached with a stale non-NULL vc. The '&& vc' guard from commit a287620312dc ("vc_screen:
fix null-ptr-deref in vcs_notifier() during concurrent vcs_write") only handles the NULL case, not this stale-non-NULL case; vcs_notifier() then reads param->vc->vc_num from freed memory:
BUG: KASAN: slab-use-after-free in vcs_notifier+0x7c/0xd0 Read of size 2 at addr ffff888007149190 Call Trace: vcs_notifier+0x7c/0xd0 atomic_notifier_call_chain+0x70/0xa0 vcs_scr_updated+0x77/0xa0 vcs_write+0x71b/0x7e0 Allocated by task: vc_allocate -> con_install -> tty_open Freed by task: kfree <- vt_ioctl (VT_DISALLOCATE -> vc_port_destruct)
Move the reload to immediately after console_lock(), before 'if (ret)', so every break path below passes a fresh vc to the post-loop vcs_scr_updated().
--- drivers/tty/vt/vc_screen.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-)
drivers/tty/vt/vc_screen.c +12 -11
@@ -633,6 +633,18 @@ vcs_write(struct file *file, const char ret =copy_from_user (con_buf, buf, this_round);console_lock (); +/* The vc might have been freed or vcs_size might have changed +* while we slept to grab the user buffer; recheck here, before +* if (ret), so every break path below passes a fresh vc to the +* post-loop vcs_scr_updated(). Return data written so far. +*/ + vc =vcs_vc (inode, &viewed); +if (!vc) { +if (written) +break ; +return -ENXIO ; + } +if (ret) { this_round -= ret;if (!this_round) {
@@ -644,17 +656,6 @@ vcs_write(struct file *file, const charreturn -EFAULT ; } } - -/* The vc might have been freed or vcs_size might have changed -* while we slept to grab the user buffer, so recheck. -* Return data written up to now on failure. -*/ - vc =vcs_vc (inode, &viewed); -if (!vc) { -if (written) -break ; -return -ENXIO ; - } size =vcs_size (vc, attr, false);if (size <0 ) {if (written)
Greg Kroah-Hartman
maintainerPATCH 59/428 vt: selection: Fix unsigned underflow and slab-out-of-bounds read in paste_selection()
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hui Peng <[email protected]>
commit 39495ef5d6f8019e62d65807f217a7ca8232727a upstream.
In paste_selection(), the loop copies min_t(unsigned int, vc_sel.buf_len - pasted,tty->receive_room) bytes per iteration into tty_ldisc_receive_buf() and increments pasted += count.
Because the selection mutex (vc_sel.lock) is dropped inside the loop Whenever the line discipline buffer fills up and paste_selection() sleeps on tty->write_wait, a concurrent TIOCLINUX (TIOCL_SETSEL) ioctl can replace vc_sel.buffer with a shorter selection and reduce vc_sel.buf_len below pasted.
When paste_selection() resumes, vc_sel.buf_len - pasted underflows as an unsigned integer to a large positive value, causing tty_ldisc_receive_buf(ld, vc_sel.buffer + pasted, NULL, count) to read up to 4094 bytes out-of-bounds past the newly allocated vc_sel.buffer.
Fix this by terminating the loop when pasted >= vc_sel.buf_len.
Kernel stack trace (Linux 7.3.0-rc3):
==================================================================
BUG: KASAN: slab-out-of-bounds in n_tty_receive_buf_common+0xa01/0x1650 Read of size 4094 at addr ffff888101c58010 by task kworker/u17:1/65 Workqueue: events_unbound flush_to_ldisc Call Trace: <TASK> dump_stack_lvl+0x70/0xa0 print_report+0x153/0x4c6 kasan_report+0xf1/0x120 kasan_check_range+0x11c/0x200 __asan_memcpy+0x29/0x70 n_tty_receive_buf_common+0xa01/0x1650 tty_ldisc_receive_buf+0x66/0x110 tty_port_default_receive_buf+0x6b/0xb0 flush_to_ldisc+0x1b4/0x410 process_one_work+0x6ff/0x1110 worker_thread+0x4a8/0xb70 kthread+0x307/0x3e0 ret_from_fork+0x3ed/0x680 </TASK> ==================================================================
--- drivers/tty/vt/selection.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/tty/vt/selection.c +2 -2
@@ -434,8 +434,8 @@ int paste_selection(struct tty_struct *t bps =NULL ; } - count = vc_sel.buf_len - pasted; -if (count) { +if (vc_sel.buf_len > pasted) { + count = vc_sel.buf_len - pasted; pasted +=tty_ldisc_receive_buf (ld, vc_sel.buffer + pasted,NULL , count);if (vc_sel.buf_len > pasted)
Greg Kroah-Hartman
maintainerPATCH 60/428 vt: skip screen update for DEC alignment test on backgroup consoles
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zizhi Wo <[email protected]>
commit 0928ed9bd7946baee911efa401088697836e3b1e upstream.
[BUG]
Recently, we encountered a KASAN warning as follows:
BUG: KASAN: slab-out-of-bounds in fb_pad_aligned_buffer+0x11f/0x140 Read of size 1 at addr ff1100015fd9f6a4 by task tty_fbcon_oob/1239 CPU: 7 UID: 0 PID: 1239 Comm: tty_fbcon_oob Not tainted 7.3.0-rc1 #100 PREEMPT(full) Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-4.fc41 04/01/2014 Call Trace: <TASK> ... kasan_report+0xf0/0x120 fb_pad_aligned_buffer+0x11f/0x140 ccw_putcs+0x86c/0xa80 fbcon_putcs+0x338/0x410 do_update_region+0x21d/0x450 do_con_write+0x1e0e/0x4880 con_write+0x13/0x80 n_tty_write+0x374/0x1010 file_tty_write.isra.0+0x404/0x7a0 ...
reproduce:
1) open /dev/tty0, set a KDFONTOP ioctl with op.op = KD_FONT_OP_SET, op.width = 8 and op.height = 16 (visible VC1)
2) open /dev/tty1, set a KDFONTOP ioctl with op.op = KD_FONT_OP_SET, op.width = 28 and op.height = 24 (invisible VC2)
3) echo 3 > /sys/devices/virtual/graphics/fbcon/rotate_all
4) write EShash8(esc hash8) to tty1
[CAUSE]
All VCs render to the framebuffer. setfont only modifies the target VC's font without resizing the framebuffer backing buffer (par->rotated.buf); the buffer is only resized for the visible VC (fbcon_do_set_font -> ... -> vc_do_resize -> update_screen). This relies on the con_should_update() check performed before every update_region().
However, the ESC # 8 path (do_con_trol -> do_update_region) omits the con_should_update() check. After changing the font size of an invisible VC, do_update_region() fills using the new font size against a buffer that was never resized, causing an out-of-bounds access.
[FIX]
Only push the update when the console is visible and not blanked, add the con_should_update() check in the do_con_trol() like every other call site of do_update_region() (update_region(), invert_screen(), ...).
--- drivers/tty/vt/vt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/tty/vt/vt.c +2 -1
@@ -2860,7 +2860,8 @@ static void do_con_trol(struct tty_struccsi_J (vc,CSI_J_VISIBLE ); vc->vc_video_erase_char = (vc->vc_video_erase_char &0xff00 ) |' ' ; -do_update_region (vc, vc->vc_origin, vc->vc_screenbuf_size /2 ); +if (con_should_update (vc)) +do_update_region (vc, vc->vc_origin, vc->vc_screenbuf_size /2 ); }return ;case ESsetG0:/* ESC ( */
Greg Kroah-Hartman
maintainerPATCH 61/428 wifi: wlcore: Fix runtime PM leak in wlcore_remove()
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wentao Liang <[email protected]>
commit a8b8881d0c1aff544fae190469d86db7b07f43a9 upstream.
pm_runtime_get_sync() keeps the runtime PM usage counter elevated even when it returns an error, so the reference taken at the beginning of wlcore_remove() has to be dropped on every exit path. When the device was not initialized the function returned early without doing so, leaking the reference.
Release it with pm_runtime_put_noidle() as done on the other early error paths of this driver.
--- drivers/net/wireless/ti/wlcore/main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/net/wireless/ti/wlcore/main.c +3 -1
@@ -6811,8 +6811,10 @@ void wlcore_remove(struct platform_devicif (pdev_data->family && pdev_data->family->nvs_name)wait_for_completion (&wl->nvs_loading_complete); -if (!wl->initialized) +if (!wl->initialized) { +pm_runtime_put_noidle (wl->dev);return ; + }if (wl->wakeirq >=0 ) {dev_pm_clear_wake_irq (wl->dev);
Greg Kroah-Hartman
maintainerPATCH 62/428 ALSA: caiaq: unregister the input device when probe fails
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nguyen Ngoc Thang <[email protected]>
commit 0b7bd20f6379bc5e431fd74d866390f5b5b63f3c upstream.
setup_card() registers the input device, whose name and phys point into struct snd_usb_caiaqdev, and then goes on to snd_card_register() and snd_usb_caiaq_control_init(). If either fails, snd_probe() calls snd_card_free(), which frees the device state but leaves the input device registered: card_free() only clears the pointer, and the input device is unregistered from snd_disconnect() alone. Reading its "uevent" attribute afterwards dereferences freed memory:
BUG: KASAN: slab-use-after-free in string+0x4a9/0x4f0 Read of size 1 at addr ffff8880208f5043 by task caiaq/4967 add_uevent_var+0x183/0x3a0 input_dev_uevent+0x162/0x900 dev_uevent+0x2f1/0x870 uevent_show+0x1ca/0x3a0 ...
Unregister the input device on the probe error path, as snd_disconnect() does. snd_usb_caiaq_input_disconnect() is a no-op when no input device was registered.
Reproduced with a raw-gadget Audio Kontrol 1 and a temporary hack that makes snd_usb_caiaq_control_init() fail.
--- sound/usb/caiaq/device.c | 3 +++ 1 file changed, 3 insertions(+)
sound/usb/caiaq/device.c +3 -0
@@ -562,6 +562,9 @@ static int snd_probe(struct usb_interfac ret =init_card (caiaqdev (card));if (ret <0 ) {dev_err (&usb_dev->dev,"unable to init card! (ret=%d)\n" , ret); +#ifdef CONFIG_SND_USB_CAIAQ_INPUT +snd_usb_caiaq_input_disconnect (caiaqdev (card)); +#endif snd_card_free (card);return ret; }
Greg Kroah-Hartman
maintainerPATCH 63/428 ALSA: ctxfi: Fix silent playback on Titanium HD (SB1270)
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Harin Lee <[email protected]>
commit 4fa0c91c2c4c604e6080690a698d4c6405ba96ca upstream.
Commit 4b490e0d103c ("ALSA: ctxfi: Add ADC helper functions for GPIO") moved the GPIO_DATA read into hw_adc_stop(), but the Titanium HD (SB1270) setup in hw_adc_init() uses the local data variable holding the GPIO_CTRL value.
Writing this value to GPIO_DATA sets the output mute bits. Playback runs without errors, but the outputs stay muted.
Re-read GPIO_DATA before setting the speed mode bits. Also, add the delay after writing the mode bits, as in the original sequence.
On affected kernels, switching the output selection was reported to restore clean playback.
--- sound/pci/ctxfi/cthw20k2.c | 2 ++ 1 file changed, 2 insertions(+)
sound/pci/ctxfi/cthw20k2.c +2 -0
@@ -1895,6 +1895,7 @@ static int hw_adc_init(struct hw *hw, coif (hw->model ==CTSB1270 ) {/* Set up the PCM4220 ADC on Titanium HD */ + data =hw_read_20kx (hw,GPIO_DATA ); data &= ~0x0C ;if (1 == info->msr) data |=0x00 ;/* Single Speed Mode 32-50kHz */
@@ -1903,6 +1904,7 @@ static int hw_adc_init(struct hw *hw, coelse data |=0x04 ;/* Quad Speed Mode 108kHz-216kHz */ hw_write_20kx (hw,GPIO_DATA , data); +usleep_range (10000 ,11000 ); }hw_adc_start (hw);
Greg Kroah-Hartman
maintainerPATCH 64/428 ALSA: line6: reject oversized playback packets
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei <[email protected]>
commit 61b0a5a114fa4552892da5c0ff2f42e63bf08c6b upstream.
Each playback URB is handed a slice of out.buffer that is exactly LINE6_ISO_PACKETS * max_packet_size_out bytes, sized from the OUT endpoint, but the number of bytes written into that slice is never compared against it.
submit_audio_out_urb() takes the frame count from prev_fsize, which audio_in_callback() derived from the *IN* endpoint's received packet length, and rescales it with the playback frame size; when prev_fsize is still zero it synthesizes a length from the sample rate instead. On a device declaring a large IN wMaxPacketSize and a small OUT wMaxPacketSize, the resulting memcpy(), or the memset() when the playback stream is idle, runs past its slice and, as the reproducer below shows, beyond the allocation.
usb_submit_urb() is not a backstop. max_packet_size_out comes from usb_maxpacket(), which returns only the low 11 bits of wMaxPacketSize, while USB core validates a high-speed isochronous length against that base scaled by usb_endpoint_maxp_mult(). A length of up to three times the allocated slice is therefore accepted, and even a rejected URB is only rejected after the write.
Reject a packet that does not fit the slice the driver allocated for it. Clamping it instead would silently shorten the capture-derived rate feedback and desynchronize the two streams.
BUG: KASAN: slab-out-of-bounds in submit_audio_out_urb (sound/usb/line6/playback.c:229) Write of size 1024 at addr ffff888100bbd400 by task kworker/1:2/5002 Workqueue: events line6_startup_work Call Trace: __asan_memcpy (mm/kasan/shadow.c:106) submit_audio_out_urb (sound/usb/line6/playback.c:229) line6_submit_audio_out_all_urbs (sound/usb/line6/playback.c:291) line6_stream_start (sound/usb/line6/pcm.c:194) line6_pcm_acquire (sound/usb/line6/pcm.c:337) line6_startup_work (sound/usb/line6/driver.c:728) process_one_work (kernel/workqueue.c:3396) worker_thread (kernel/workqueue.c:3479 kernel/workqueue.c:3560) kthread (kernel/kthread.c:436) ret_from_fork (arch/x86/kernel/process.c:158) ret_from_fork_asm (arch/x86/entry/entry_64.S:245) The buggy address belongs to the object at ffff888100bbd400 which belongs to the cache kmalloc-256 of size 256 The buggy address is located 0 bytes inside of allocated 256-byte region [ffff888100bbd400, ffff888100bbd500)
--- sound/usb/line6/playback.c | 7 +++++++ 1 file changed, 7 insertions(+)
sound/usb/line6/playback.c +7 -0
@@ -182,6 +182,13 @@ static int submit_audio_out_urb(struct s fsize *= bytes_per_frame; +if (fsize > line6pcm->max_packet_size_out) { +dev_err (line6pcm->line6->ifcdev, +"playback packet too large: %d > %d\n" , + fsize, line6pcm->max_packet_size_out); +return -EMSGSIZE ; + } + fout->offset = urb_size; fout->length = fsize; urb_size += fsize;
Greg Kroah-Hartman
maintainerPATCH 65/428 ext4: dont enable large folios on encrypted inodes
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alberto Garcia <[email protected]>
Commit 709f0f1f1bf5 ("ext4: add checks for large folio incompatibilities when BS > PS") disables large folios at mount time if the "encrypt" feature is set. However, enabling that feature on a mounted filesystem circumvents that check, and writing encrypted data results in a crash:
BUG: kernel NULL pointer dereference, address: 0000000000000028 Workqueue: ext4-rsv-conversion ext4_end_io_rsv_work RIP: 0010:ext4_finish_bio+0xf7/0x3e0 Call Trace: ext4_release_io_end+0x51/0x110 ext4_end_io_end+0x4c/0xe0 ext4_end_io_rsv_work+0xb3/0x100
Fix this by disabling large folios on encrypted inodes, as is already done for inodes that use data journaling.
This affects all kernels between v6.19 and v7.2, but it is not needed in v7.3, where the code was significantly refactored.
--- fs/ext4/inode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/ext4/inode.c +2 -1
@@ -5287,7 +5287,8 @@ void ext4_set_inode_mapping_order(struct inode *inode)if (!min_order && !S_ISREG (inode->i_mode))return ; -if (ext4_test_inode_flag (inode,EXT4_INODE_JOURNAL_DATA )) +if (ext4_test_inode_flag (inode,EXT4_INODE_JOURNAL_DATA ) || +ext4_test_inode_flag (inode,EXT4_INODE_ENCRYPT )) max_order = min_order;mapping_set_folio_order_range (inode->i_mapping, min_order, max_order);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 66/428 iio: dac: rohm-bd79703: Do not allow writing SCALE
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matti Vaittinen <[email protected]>
[ Upstream commit 55671fbc3d12ae1f381842433567fcb7ff96a298 ]
The BD79703 has adds IIO_CHAN_INFO_SCALE in the info_mask_shared_by_type so users can read the scale, which depends on the used reference voltage. This, however, enables users to try writing the scale as well. This isn't really supported but the bd79703_write_raw() does not check the mask, and if written scale values pass the validation, the driver will proceed writing the DAC value when users writes the scale.
Prevent the unsupported scale setting and return an error.
--- drivers/iio/dac/rohm-bd79703.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/iio/dac/rohm-bd79703.c +3 -0
@@ -73,6 +73,9 @@ static int bd79703_write_raw(struct iio_dev *idev, {struct bd79703_data *data =iio_priv (idev); +if (mask !=IIO_CHAN_INFO_RAW ) +return -EINVAL ; +if (val <0 || val >=1 <<BD79703_DAC_BITS )return -EINVAL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 67/428 iio: light: rohm-bu27034: Fix error return
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matti Vaittinen <[email protected]>
[ Upstream commit 4e5b0b7c5d95814b6d76911a91572a0691925ca7 ]
When BU27034 fails to read gain value at integration-time setting, it returns 0. This leaves caller unaware of the fact that setting the integration time failed.
Fix this by returning the relevant error instead of zero.
--- drivers/iio/light/rohm-bu27034.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iio/light/rohm-bu27034.c +1 -1
@@ -415,7 +415,7 @@ static int bu27034_try_set_int_time(struct bu27034_data *data, int time_us)for (i =0 ; i < numg; i++) { ret =bu27034_get_gain (data, gains[i].chan, &gains[i].old_gain);if (ret) -return 0 ; +return ret; ret = iio_gts_find_new_gain_by_old_gain_time(&data->gts, gains[i].old_gain,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 68/428 iio: accel: kionix-kx022a: Fix array boundary check
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matti Vaittinen <[email protected]>
[ Upstream commit 0e65412aee4f651d2c9785f542a13e4b44002a75 ]
The driver performs a sanity check for an array size, when converting a register value to an array index. The check incorrectly accepts the sizeof(array) as a last index, when last valid index should be sizeof(array) - 1.
Fix the check by bailing out when index >= sizeof(array).
--- drivers/iio/accel/kionix-kx022a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iio/accel/kionix-kx022a.c +1 -1
@@ -649,7 +649,7 @@ static int kx022a_read_raw(struct iio_dev *idev,if (ret)return ret; -if ((regval &KX022A_MASK_ODR ) > +if ((regval &KX022A_MASK_ODR ) >=ARRAY_SIZE (kx022a_accel_samp_freq_table)) {dev_err (data->dev,"Invalid ODR\n" );return -EINVAL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 69/428 mtd: core: avoid double-free of OTP NVMEM device
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Karl Mehltretter <[email protected]>
[ Upstream commit 26300879cd8e4612dce66bb8f6ff7cd35fcf3e59 ]
If factory OTP setup fails after the user OTP NVMEM device has been registered, mtd_otp_nvmem_add() unregisters the user device but leaves mtd->otp_user_nvmem set. On an error, the caller unregisters it again. For -EOPNOTSUPP, registration continues and normal teardown unregisters it again.
Clear mtd->otp_user_nvmem after unregistering it.
--- drivers/mtd/mtdcore.c | 1 + 1 file changed, 1 insertion(+)
drivers/mtd/mtdcore.c +1 -0
@@ -1083,6 +1083,7 @@ static int mtd_otp_nvmem_add(struct mtd_info *mtd) err:nvmem_unregister (mtd->otp_user_nvmem); + mtd->otp_user_nvmem =NULL ;/* Don't report error if OTP is not supported. */ if (err == -EOPNOTSUPP )return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 70/428 mtd: core: call _get_device() with the master MTD
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Karl Mehltretter <[email protected]>
[ Upstream commit 12b31d1acd20b3185bb5f0748db0cf6874c8e9d1 ]
__get_mtd_device() calls the master's _get_device() callback with mtd, which may be a partition. __put_mtd_device() passes the master.
This breaks gluebi partitions because gluebi_get_device() uses container_of() and therefore requires the master MTD. Pass the master to _get_device(), matching _put_device().
--- drivers/mtd/mtdcore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/mtd/mtdcore.c +1 -1
@@ -1333,7 +1333,7 @@ int __get_mtd_device(struct mtd_info *mtd)int err;if (master->_get_device) { - err = master->_get_device (mtd); + err = master->_get_device (master);if (err)return err; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 71/428 nvmet: preserve device path on allocation failure
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Julian Sun <[email protected]>
[ Upstream commit 2f271b812170d4cad578bae1f91db72f3c2e36e7 ]
nvmet_ns_device_path_store() frees the old path before allocating its replacement, losing the existing configuration if allocation fails. Allocate the new path before freeing the old one.
--- drivers/nvme/target/configfs.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
drivers/nvme/target/configfs.c +6 -3
@@ -534,6 +534,7 @@ static ssize_t nvmet_ns_device_path_store(struct config_item *item,struct nvmet_subsys *subsys = ns->subsys;size_t len;int ret; +char *new_path =NULL ;mutex_lock (&subsys->lock); ret = -EBUSY ;
@@ -545,12 +546,14 @@ static ssize_t nvmet_ns_device_path_store(struct config_item *item,if (!len) goto out_unlock; -kfree (ns->device_path); ret = -ENOMEM ; - ns->device_path =kmemdup_nul (page, len,GFP_KERNEL ); -if (!ns->device_path) + new_path =kmemdup_nul (page, len,GFP_KERNEL ); +if (!new_path) goto out_unlock; +kfree (ns->device_path); + ns->device_path = new_path; +mutex_unlock (&subsys->lock);return count;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 72/428 blk-cgroup: save IRQ state in blkg_tryget_closest()
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hao Zhang <[email protected]>
[ Upstream commit 327c428ba79b13e4cc5253333a9d5c0aa5579bdf ]
bio_set_dev() associates the bio with a blkg through bio_associate_blkg(). If the blkg lookup misses, blkg_tryget_closest() takes q->queue_lock with spin_lock_irq() and releases it with spin_unlock_irq(), which unconditionally enables local interrupts.
Callers may call bio_set_dev() with interrupts already disabled, e.g. dm-thin's pool_map() does so while holding pool->lock taken with spin_lock_irq(). The nested spin_unlock_irq() then enables interrupts while pool->lock is still held, so an I/O completion softirq can run on the same CPU, re-acquire pool->lock (thin_endio(), or overwrite_endio() -> complete_mapping_preparation()) and deadlock. lockdep reports this as inconsistent SOFTIRQ-ON-W to IN-SOFTIRQ-W usage.
Commit 3a762de55b4e ("block: save irq state in blkg_lookup_create()") fixed the same problem while the lock lived in blkg_lookup_create(), but commit 9327a865e395 ("blk-cgroup: don't nest queue_lock under rcu in blkg_lookup_create()") moved the locking into blkg_tryget_closest() and reverted it to spin_lock_irq().
Save and restore the caller's IRQ state instead.
--- block/blk-cgroup.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
block/blk-cgroup.c +3 -2
@@ -2078,6 +2078,7 @@ static inline struct blkcg_gq *blkg_tryget_closest(struct bio *bio,struct request_queue *q = bio->bi_bdev->bd_queue;struct blkcg *blkcg =css_to_blkcg (css);struct blkcg_gq *blkg; +unsigned long flags;rcu_read_lock (); blkg =blkg_lookup (blkcg, q);
@@ -2092,11 +2093,11 @@ static inline struct blkcg_gq *blkg_tryget_closest(struct bio *bio,* Fast path failed, we're probably issuing IO in this cgroup the first * time, hold lock to create new blkg. */ -spin_lock_irq (&q->queue_lock); +spin_lock_irqsave (&q->queue_lock, flags); blkg =blkg_lookup_create (blkcg, bio->bi_bdev->bd_disk);if (blkg) blkg =blkg_lookup_tryget (blkg); -spin_unlock_irq (&q->queue_lock); +spin_unlock_irqrestore (&q->queue_lock, flags);return blkg; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 73/428 random: fix vgetrandom_opaque_params kernel-doc
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Karl Mehltretter <[email protected]>
[ Upstream commit 703749b069d53b55f92499e088b30b031e47b8f9 ]
struct vgetrandom_opaque_params contains size_of_opaque_state, but its kernel-doc describes size_per_opaque_state. This leaves the real member undescribed and adds a nonexistent member to the generated documentation.
Use the member's actual name.
--- include/uapi/linux/random.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/uapi/linux/random.h +1 -1
@@ -58,7 +58,7 @@ struct rand_pool_info {/** * struct vgetrandom_opaque_params - arguments for allocating memory for vgetrandom * -* @size_per_opaque_state: Size of each state that is to be passed to vgetrandom(). +* @size_of_opaque_state: Size of each state passed to vgetrandom(). * @mmap_prot: Value of the prot argument in mmap(2). * @mmap_flags: Value of the flags argument in mmap(2). * @reserved: Reserved for future use.
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 74/428 of/overlay: dont leak fragment references when changeset init fails
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdurrahman Hussain <[email protected]>
[ Upstream commit 1d62f0f2bc7edb12ed09f71203df0e47fa4efca4 ]
init_overlay_changeset() stores the number of initialized fragments in ovcs->count only on full success. When find_target() or the __symbols__ lookup fails partway through, the target and overlay references taken for the fragments initialized so far are never
dropped: free_overlay_changeset() bounds its cleanup loop by ovcs->count, which is still 0.
Store the running count on the error path so free_overlay_changeset() puts whatever was set up. The store is guarded by ovcs->fragments because on the allocation-failure path cnt still holds the counting pass total while there is no fragments array; everywhere else cnt only counts fully-initialized fragments.
--- drivers/of/overlay.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/of/overlay.c +4 -0
@@ -854,6 +854,10 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs, err_out:pr_err ("%s() failed, ret = %d\n" , __func__, ret); +/* let free_overlay_changeset() put the fragments set up so far */ +if (ovcs->fragments) + ovcs->count = cnt; +return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 75/428 of/overlay: dont create "//" paths for fragments targeting the root
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdurrahman Hussain <[email protected]>
[ Upstream commit 21c89ff1fc86ffa517f3a9ca1ba5c48e9e37c1ba ]
dup_and_fixup_symbol_prop() rewrites a symbol value by replacing its "/fragment/__overlay__" prefix with the fragment's target path. When the fragment targets the root node the target path is "/" and the result starts with "//", which __of_find_node_by_full_path() cannot
resolve: symbols pointing into such fragments silently stop resolving.
Drop the target path when it is the root and the tail is non-empty. A value naming the fragment root itself (empty tail) keeps the "/".
--- drivers/of/overlay.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/of/overlay.c +3 -0
@@ -256,6 +256,9 @@ static struct property *dup_and_fixup_symbol_prop(if (!target_path)return NULL ; target_path_len =strlen (target_path); +/* a root target renders as "/"; drop it to avoid "//" results */ +if (target_path_len ==1 && target_path[0 ] =='/' && path_tail_len) + target_path_len =0 ; new_prop =kzalloc_obj (*new_prop);if (!new_prop)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 76/428 ASoC: wm8903: Move the DRC QR threshold to the register that holds it
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: HyeongJun An <[email protected]>
[ Upstream commit e31ae4aeb049983fe3be0cf1e12c8074811a7685 ]
The DRC_THRESH_QR field is bits 7 and 6 of DRC_1, but the control sits on DRC_0. Its shift and max are right for the field, only the register is wrong.
Those bits of DRC_0 belong to DRC_STARTUP_GAIN, which "DRC Startup Volume" claims as bits 10 to 6. So the two controls share bits 7 and 6. Writing either one moves the other, and the quick release threshold is never reached at all.
The six fields of DRC_1 tile it exactly, so there is nowhere else the threshold could live. Point the control at DRC_1.
Found by a sweep for two controls claiming the same bits of one register. No board with this codec was to hand, the register map is the driver's own wm8903.h.
--- sound/soc/codecs/wm8903.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/codecs/wm8903.c +1 -1
@@ -677,7 +677,7 @@ SOC_ENUM("DRC Decay Rate", drc_decay),SOC_ENUM ("DRC FF Delay" , drc_ff_delay),SOC_SINGLE ("DRC Anticlip Switch" ,WM8903_DRC_0 ,1 ,1 ,0 ),SOC_SINGLE ("DRC QR Switch" ,WM8903_DRC_0 ,2 ,1 ,0 ), -SOC_SINGLE_TLV ("DRC QR Threshold Volume" ,WM8903_DRC_0 ,6 ,3 ,0 , drc_tlv_max), +SOC_SINGLE_TLV ("DRC QR Threshold Volume" ,WM8903_DRC_1 ,6 ,3 ,0 , drc_tlv_max),SOC_ENUM ("DRC QR Decay Rate" , drc_qr_decay),SOC_SINGLE ("DRC Smoothing Switch" ,WM8903_DRC_0 ,3 ,1 ,0 ), SOC_SINGLE("DRC Smoothing Hysteresis Switch", WM8903_DRC_0, 0, 1, 0),
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 77/428 wifi: wfx: validate MIB read length before copying to caller
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aamir Ahmed <[email protected]>
[ Upstream commit ce67ebe9d8629776ce38e6995ae72fb903c828db ]
wfx_hif_read_mib() copies reply->length bytes from the firmware response into the caller-provided buffer without checking that reply->length does not exceed val_len. A firmware response with a length field larger than expected overruns the caller buffer and reads past the end of the reply allocation.
Replace the dead -ENOMEM check with an active validation that reply->length fits within val_len before the memcpy.
--- drivers/net/wireless/silabs/wfx/hif_tx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/net/wireless/silabs/wfx/hif_tx.c +3 -1
@@ -207,9 +207,11 @@ int wfx_hif_read_mib(struct wfx_dev *wdev, int vif_id, u16 mib_id, void *val, sidev_warn (wdev->dev,"%s: confirmation mismatch request\n" , __func__); ret = -EIO ; } -if (ret == -ENOMEM ) +if (!ret &&le16_to_cpu (reply->length) > val_len) {dev_err (wdev->dev,"buffer is too small to receive %s (%zu < %d)\n" ,wfx_get_mib_name (mib_id), val_len,le16_to_cpu (reply->length)); + ret = -EIO ; + }if (!ret)memcpy (val, &reply->mib_data,le16_to_cpu (reply->length));else
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 78/428 ASoC: tegra: Fix ASRC Stream6 input threshold control
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sheetal <[email protected]>
[ Upstream commit 75fc8a3ee5aee72f2fea3b6436170fae175f7f19 ]
The Stream6 Input Threshold control points at stream index 4, which is already used by Stream5. The threshold get and put callbacks derive the lane ID from the register offset, so the duplicate index makes Stream6 operate on lane 4 and leaves lane 5 inaccessible from userspace.
Use stream index 5 for Stream6.
--- sound/soc/tegra/tegra186_asrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/tegra/tegra186_asrc.c +1 -1
@@ -828,7 +828,7 @@ static const struct snd_kcontrol_new tegra186_asrc_controls[] = { tegra186_asrc_put_input_threshold),SOC_SINGLE_EXT ("Stream6 Input Threshold" , -ASRC_STREAM_REG (TEGRA186_ASRC_RX_THRESHOLD ,4 ),0 ,3 ,0 , +ASRC_STREAM_REG (TEGRA186_ASRC_RX_THRESHOLD ,5 ),0 ,3 ,0 , tegra186_asrc_get_input_threshold, tegra186_asrc_put_input_threshold),
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 79/428 wifi: mac80211: drop oversized fragments to avoid extra_len overflow
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuchao Zhang <[email protected]>
[ Upstream commit 5e4f3509793b4db2c0835340224743db680e861f ]
In ieee80211_rx_h_defragment(), fragment payloads are accumulated into entry->extra_len as subsequent fragments arrive:
entry->extra_len += rx->skb->len;
When the final fragment arrives, the head fragment is dequeued, and pskb_expand_head() is called with entry->extra_len to ensure sufficient tailroom for all queued fragments before copying:
if (skb_tailroom(rx->skb) < entry->extra_len) {
if (unlikely(pskb_expand_head(rx->skb, 0, entry->extra_len,
GFP_ATOMIC))) {
...
}
}
while ((skb = __skb_dequeue(&entry->skb_list))) {
skb_put_data(rx->skb, skb->data, skb->len);
dev_kfree_skb(skb);
}In commit 69f132236827 ("mac80211: shrink struct ieee80211_fragment_entry"), entry->extra_len was narrowed from unsigned int to u16 in order to reduce structure memory footprint.
However, an IEEE 802.11 frame sequence can contain up to 16 fragments (frag numbers 0..15). If a sequence of large fragments arrives (e.g. from a malicious peer or rogue AP), the sum of fragment lengths can exceed 65535 bytes (for example, 15 fragments of 4400 bytes total 66000 bytes). Because extra_len is a u16, this addition overflows and wraps around modulo 65536 (e.g. 66000 wraps to 464).
Consequently, pskb_expand_head() allocates only the truncated amount of tailroom (or is skipped entirely if the head fragment already has >= 464 bytes of tailroom). When skb_put_data() subsequently iterates through the queued skb list, it appends the full payload into the undersized buffer, causing skb_put() to trigger skb_over_panic() and crash the kernel in softirq context.
A legitimate MSDU in IEEE 802.11 is at most 2304 bytes (or up to 7935/11454 bytes for A-MSDU, which is not fragmented), well below U16_MAX.
Fix this without increasing the size of struct ieee80211_fragment_entry by checking whether adding the incoming fragment length would exceed U16_MAX. If so, purge the queued fragments and drop the frame.
--- net/mac80211/drop.h | 1 + net/mac80211/rx.c | 6 ++++++ 2 files changed, 7 insertions(+)
net/mac80211/drop.h +1 -0
@@ -108,6 +108,7 @@ typedef unsigned int __bitwise ieee80211_rx_result; R(RX_DROP_U_UNHANDLED_PREQ) \ R(RX_DROP_U_UNHANDLED_MGMT_STYPE) \ R(RX_DROP_U_NO_LINK) \ + R(RX_DROP_U_DEFRAG_OVERFLOW) \ /* this line for the trailing \ - add before this */ /* having two enums allows for checking ieee80211_rx_result use with sparse */
net/mac80211/rx.c +6 -0
@@ -2499,6 +2499,12 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) }skb_pull (rx->skb,ieee80211_hdrlen (fc)); +if (unlikely ((u32 )entry->extra_len + rx->skb->len >U16_MAX )) { +I802_DEBUG_INC (rx->local->rx_handlers_drop_defrag); +__skb_queue_purge (&entry->skb_list); +return RX_DROP_U_DEFRAG_OVERFLOW ; + } +__skb_queue_tail (&entry->skb_list, rx->skb); entry->last_frag = frag; entry->extra_len += rx->skb->len;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 80/428 wifi: ath11k: reset ar->num_stations on hardware start
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolas Escande <[email protected]>
[ Upstream commit 7e0ad05ebc72fffba2bdf2400400902d94ed7272 ]
When (multiple) hw restart occurs, we end up in a situation where we cannot accept new stations / mesh peers. This seems to be the 'num_stations' in 'struct ath11k' that did not get reset properly in this case. In ath11k_mac_op_start(), it was indeed the only accounting var that did not get reset so let's clear it too.
This avoids problems like those:
[1248828.088023] WARNING: CPU: 0 PID: 12281 at net/mac80211/util.c:1682 ieee80211_reconfig_stations+0x98/0xc0 [1248828.088115] Call trace: [1248828.088116] ieee80211_reconfig_stations+0x98/0xc0 (P) [1248828.088119] ieee80211_reconfig+0x774/0x1438 [1248828.088123] ieee80211_restart_work+0x10c/0x178 [1248828.088127] process_one_work+0x178/0x3c0 [1248828.088130] worker_thread+0x280/0x440 [1248828.088133] kthread+0xe0/0xf8 [1248828.088137] ret_from_fork+0x10/0x20 [1248828.088141] ---[ end trace 0000000000000000 ]--- [1248836.686604] ath11k_pci 0000:04:00.0: refusing to associate station: too many connected already (128) [1248836.686609] ath11k_pci 0000:04:00.0: Failed to add station: xx:xx:xx:xx:xx:xx for VDEV: 1
Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.9.0.1-01977-QCAHKSWPL_SILICONZ-1
--- drivers/net/wireless/ath/ath11k/mac.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/wireless/ath/ath11k/mac.c +1 -0
@@ -6716,6 +6716,7 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw) ar->num_started_vdevs =0 ; ar->num_created_vdevs =0 ; ar->num_peers =0 ; + ar->num_stations =0 ; ar->allocated_vdev_map =0 ;/* Configure monitor status ring with default rx_filter to get rx status
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 81/428 wifi: ath9k: Clean up device initialisation guards
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Toke Høiland-Jørgensen <[email protected]>
[ Upstream commit 1af8dc9ca726cf53767f9c0661171396f95c146a ]
The ath9k driver has a couple of guards against the RX path running until device initialisation has completed. However, they are problematic for several reasons:
- They use smp_wmb() paired with a data_race() annotation, instead of the idiomatic smp_store_release()/smp_load_acquire() pair.
- The guard in ath9k_wmi_event_tasklet() is weirdly late in the function.
- There are two of them when there's really no reason the rx init gets to run before the whole initialisation is complete.
Consolidate the guards on the single ath9k_htc_priv->initialized variable and use smp_store_release()/smp_load_acquire() to access it. Move the store into ath9k_init_device() to make sure it's set in all paths in the driver.
--- drivers/net/wireless/ath/ath9k/htc.h | 1 - drivers/net/wireless/ath/ath9k/htc_drv_init.c | 7 +++---- drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 8 ++------ drivers/net/wireless/ath/ath9k/wmi.c | 12 ++++++------ 4 files changed, 11 insertions(+), 17 deletions(-)
drivers/net/wireless/ath/ath9k/htc.h +0 -1
@@ -281,7 +281,6 @@ struct ath9k_htc_rxbuf {struct ath9k_htc_rx {struct list_head rxbuf;spinlock_t rxbuflock; -bool initialized; };#define ATH9K_HTC_TX_CLEANUP_INTERVAL 50/* ms */
drivers/net/wireless/ath/ath9k/htc_drv_init.c +3 -4
@@ -910,6 +910,9 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv,ath9k_init_leds (priv);ath9k_start_rfkill_poll (priv); +/* signal completion to ath9k_htc_rxep() and ath9k_wmi_event_tasklet() */ +smp_store_release (&priv->initialized, true); +return 0 ; err_world:
@@ -966,10 +969,6 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, htc_handle->drv_priv = priv; -/* Allow ath9k_wmi_event_tasklet() to operate. */ -smp_wmb (); - priv->initialized = true; -return 0 ; err_init:
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +2 -6
@@ -1141,8 +1141,8 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb,struct ath9k_htc_rxbuf *rxbuf =NULL , *tmp_buf =NULL ;unsigned long flags; -/* Check if ath9k_rx_init() completed. */ -if (!data_race (priv->rx.initialized)) +/* Check if ath9k_init_device() completed. */ +if (!smp_load_acquire (&priv->initialized)) goto err;spin_lock_irqsave (&priv->rx.rxbuflock, flags);
@@ -1200,10 +1200,6 @@ int ath9k_rx_init(struct ath9k_htc_priv *priv)list_add_tail (&rxbuf->list, &priv->rx.rxbuf); } -/* Allow ath9k_htc_rxep() to operate. */ -smp_wmb (); - priv->rx.initialized = true; -return 0 ; err:
drivers/net/wireless/ath/ath9k/wmi.c +6 -6
@@ -146,6 +146,12 @@ void ath9k_wmi_event_tasklet(struct tasklet_struct *t)unsigned long flags;u16 cmd_id; +/* Check if ath9k_init_device() completed. */ +if (!smp_load_acquire (&priv->initialized)) { +tasklet_schedule (t); +return ; + } + do { spin_lock_irqsave(&wmi->wmi_lock, flags); skb = __skb_dequeue(&wmi->wmi_event_queue);
@@ -155,12 +161,6 @@ void ath9k_wmi_event_tasklet(struct tasklet_struct *t) }spin_unlock_irqrestore (&wmi->wmi_lock, flags); -/* Check if ath9k_htc_probe_device() completed. */ -if (!data_race (priv->initialized)) { -kfree_skb (skb); -continue ; - } - hdr = (struct wmi_cmd_hdr *) skb->data; cmd_id =be16_to_cpu (hdr->command_id); wmi_event =skb_pull (skb,sizeof (struct wmi_cmd_hdr ));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 82/428 wifi: ath9k: reject short WMI command responses
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
[ Upstream commit 93ce8ea70451e800601bc9444aa33043de15d67b ]
ath9k_wmi_rsp_callback() removes the validated WMI header and copies the number of bytes expected by the waiting command into its response buffer. A device response shorter than that expectation can therefore be read beyond the skb payload.
Record -EMSGSIZE for a short response, complete the waiter, and return the stored status from the command path. This also prevents callers from consuming stale response bytes as a successful reply.
--- drivers/net/wireless/ath/ath9k/wmi.c | 16 ++++++++++++++-- drivers/net/wireless/ath/ath9k/wmi.h | 1 + 2 files changed, 15 insertions(+), 2 deletions(-)
drivers/net/wireless/ath/ath9k/wmi.c +14 -2
@@ -206,9 +206,16 @@ static void ath9k_wmi_rsp_callback(struct wmi *wmi, struct sk_buff *skb) {skb_pull (skb,sizeof (struct wmi_cmd_hdr )); -if (wmi->cmd_rsp_buf !=NULL && wmi->cmd_rsp_len !=0 ) +if (wmi->cmd_rsp_buf && wmi->cmd_rsp_len) { +if (skb->len < wmi->cmd_rsp_len) { + wmi->cmd_rsp_status = -EMSGSIZE ; + goto complete; + }memcpy (wmi->cmd_rsp_buf, skb->data, wmi->cmd_rsp_len); + } + wmi->cmd_rsp_status =0 ; +complete:complete (&wmi->cmd_wait); }
@@ -300,6 +307,7 @@ static int ath9k_wmi_cmd_issue(struct wmi *wmi,/* record the rsp buffer and length */ wmi->cmd_rsp_buf = rsp_buf; wmi->cmd_rsp_len = rsp_len; + wmi->cmd_rsp_status =0 ; wmi->last_seq_id = wmi->tx_seq_id;spin_unlock_irqrestore (&wmi->wmi_lock, flags);
@@ -356,9 +364,13 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,return -ETIMEDOUT ; } +spin_lock_irqsave (&wmi->wmi_lock, flags); + ret = wmi->cmd_rsp_status; +spin_unlock_irqrestore (&wmi->wmi_lock, flags); +mutex_unlock (&wmi->op_mutex); -return 0 ; +return ret; out:ath_dbg (common,WMI ,"WMI failure for: %s\n" ,wmi_cmd_to_name (cmd_id));
drivers/net/wireless/ath/ath9k/wmi.h +1 -0
@@ -157,6 +157,7 @@ struct wmi {u16 tx_seq_id;u8 *cmd_rsp_buf;u32 cmd_rsp_len; +int cmd_rsp_status;bool stopped;struct list_head pending_tx_events;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 83/428 wifi: ath9k_htc: bound TX aggregation to MAX_TX_BUF_SIZE
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Georgios Karantzas <[email protected]>
[ Upstream commit aeaca27c1db3106967ffbb2b517d98c835f6d500 ]
__hif_usb_tx() dequeues up to MAX_TX_AGGR_NUM (20) frames into a single tx_buf of MAX_TX_BUF_SIZE (32768) bytes, limiting the batch by record count but never by cumulative byte length.
With large frames (MTU 2304), 20 aggregated frames of 2292 bytes each exceed the allocation (20 * 2296 = 45920 bytes), so the memcpy() in the loop writes up to 13152 bytes past tx_buf->buf before usb_submit_urb().
Peek the queue head and stop before copying any record that would cross MAX_TX_BUF_SIZE, then dispatch the current batch. Leftover skbs remain queued and are drained on the next URB completion.
The byte bound changes the loop's exit semantics: it can now exit before i == tx_skb_cnt - 1. Stock only finalized tx_buf->len on that last index (len += offset), so an early break would submit a URB holding only the last record's length while every dequeued skb is freed on completion, silently dropping frames. Make tx_buf->len a running total and advance tx_buf->offset per record instead; the stride round_up(nskb->len + 4, 4) is identical to the stock stride when the loop runs to completion.
Tested on hardware with an MTU 2304 flood: the loop stops at record 15 (len = 32144, offset = 32144, within 32768), no oversized URB is submitted, and MTU 1500 pings pass 20/20.
--- drivers/net/wireless/ath/ath9k/hif_usb.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-)
drivers/net/wireless/ath/ath9k/hif_usb.c +9 -10
@@ -14,6 +14,7 @@* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <linux/math.h> #include <linux/unaligned.h> #include "htc.h"
@@ -328,11 +329,14 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev) tx_skb_cnt =min_t (u16, hif_dev->tx.tx_skb_cnt,MAX_TX_AGGR_NUM );for (i =0 ; i < tx_skb_cnt; i++) { - nskb =__skb_dequeue (&hif_dev->tx.tx_skb_queue); + nskb =skb_peek (&hif_dev->tx.tx_skb_queue); +if (!nskb) +break ; -/* Should never be NULL */ -BUG_ON (!nskb); +if (tx_buf->offset + nskb->len +4 >MAX_TX_BUF_SIZE ) +break ; + nskb =__skb_dequeue (&hif_dev->tx.tx_skb_queue); hif_dev->tx.tx_skb_cnt--; buf = tx_buf->buf;
@@ -342,13 +346,8 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev) *hdr++ =cpu_to_le16 (ATH_USB_TX_STREAM_MODE_TAG ); buf +=4 ;memcpy (buf, nskb->data, nskb->len); - tx_buf->len = nskb->len +4 ; - -if (i < (tx_skb_cnt -1 )) - tx_buf->offset += (((tx_buf->len -1 ) /4 ) +1 ) *4 ; - -if (i == (tx_skb_cnt -1 )) - tx_buf->len += tx_buf->offset; + tx_buf->len = tx_buf->offset + nskb->len +4 ; + tx_buf->offset +=round_up (nskb->len +4 ,4 );__skb_queue_tail (&tx_buf->skb_queue, nskb);TX_STAT_INC (hif_dev, skb_queued);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 84/428 rtc: dev: zero-initialize struct rtc_wkalrm to prevent information leak
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Liu Dalin <[email protected]>
[ Upstream commit 0ee5c5d804d592a8328a425b9274487d393d3a05 ]
The struct rtc_wkalrm has padding holes after the 'pending' member. When returned to userspace via the RTC_WKALRM_RD ioctl, uninitialized kernel stack data residing in these holes may be leaked.
Zero-initialize the struct at declaration to eliminate this information leak risk.
Fixes smatch warnings:
- drivers/rtc/dev.c:392 rtc_dev_ioctl() warn: check that 'alarm' doesn't leak information (struct has a hole after 'pending')
--- drivers/rtc/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/rtc/dev.c +1 -1
@@ -216,7 +216,7 @@ static long rtc_dev_ioctl(struct file *file,struct rtc_device *rtc = file->private_data;const struct rtc_class_ops *ops = rtc->ops;struct rtc_time tm; -struct rtc_wkalrm alarm; +struct rtc_wkalrm alarm = {0 };struct rtc_param param;void __user *uarg = (void __user *)arg;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 85/428 rtc: ac100: Fix clock provider use-after-free on probe failure
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aamir Ahmed <[email protected]>
[ Upstream commit fcf0b58e976e83adf246b014518e49c662b96f5e ]
ac100_rtc_register_clks() registers the RTC-32k clock with clk_hw_register_fixed_rate() and the clock provider with of_clk_add_hw_provider(). Neither is device managed, and both are released only from ac100_rtc_remove(). The driver core does not call remove() when probe() fails: really_probe() reaches probe_failed below the device_remove() call and goes straight to releasing the device's managed resources.
ac100_rtc_probe() ends with
return devm_rtc_register_device(chip->rtc);
so if that fails after the clocks have been registered, the provider is left on the global of_clk_providers list holding chip->clk_data, which was allocated with devm_kzalloc() and is freed while probe() unwinds. A later lookup on this device tree node then reads freed memory in of_clk_hw_onecell_get(). Consumers that do exactly that exist in tree:
the wifi power sequence nodes on sun8i-a83t-bananapi-m3 and sun8i-a83t-cubietruck-plus take <&ac100_rtc 1>, and the sun9i-a80 boards route osc32k through <&ac100_rtc 0>. The window is narrow, as devm_rtc_register_device() can only fail with -ENOMEM here, but the provider is left dangling whenever it does.
The RTC-32k clock is leaked on the same path. Since clk_core_lookup() searches a global list that is not scoped per device, __clk_register() rejects the duplicate name with -EEXIST, so the leak also makes a later probe of the same device fail.
The error path that returns -EINVAL when the ADDA 4M parent clock cannot be found leaks the RTC-32k clock in the same way. No provider has been registered at that point, so that one is a leak rather than a use-after-free.
Register both with devm_clk_hw_register_fixed_rate() and devm_of_clk_add_hw_provider() so that they are released whenever the device goes away, on a failed probe as well as on unbind. Devres releases in reverse order of acquisition, so the provider is removed before chip->clk_data is freed, and the clkout children are now unregistered before their parent rather than after it. ac100_rtc_unregister_clks() and the remove callback then have nothing left to do and are removed.
--- drivers/rtc/rtc-ac100.c | 36 +++++++----------------------------- 1 file changed, 7 insertions(+), 29 deletions(-)
drivers/rtc/rtc-ac100.c +7 -29
@@ -319,10 +319,10 @@ static int ac100_rtc_register_clks(struct ac100_rtc_dev *chip) chip->clk_data->num =AC100_CLKOUT_NUM ; - chip->rtc_32k_clk =clk_hw_register_fixed_rate (chip->dev, -AC100_RTC_32K_NAME , -NULL ,0 , -AC100_RTC_32K_RATE ); + chip->rtc_32k_clk =devm_clk_hw_register_fixed_rate (chip->dev, +AC100_RTC_32K_NAME , +NULL ,0 , +AC100_RTC_32K_RATE );if (IS_ERR (chip->rtc_32k_clk)) { ret =PTR_ERR (chip->rtc_32k_clk); dev_err(chip->dev, "Failed to register RTC-32k clock: %d\n",
@@ -356,28 +356,14 @@ static int ac100_rtc_register_clks(struct ac100_rtc_dev *chip)if (ret) {dev_err (chip->dev,"Failed to register clk '%s': %d\n" , init.name, ret); - goto err_unregister_rtc_32k; +return ret; } chip->clk_data->hws[i] = &clk->hw; } - ret =of_clk_add_hw_provider (np, of_clk_hw_onecell_get, chip->clk_data); -if (ret) - goto err_unregister_rtc_32k; - -return 0 ; - -err_unregister_rtc_32k: -clk_unregister_fixed_rate (chip->rtc_32k_clk->clk); - -return ret; -} - -static void ac100_rtc_unregister_clks (struct ac100_rtc_dev *chip) -{ -of_clk_del_provider (chip->dev->of_node); -clk_unregister_fixed_rate (chip->rtc_32k_clk->clk); +return devm_of_clk_add_hw_provider (chip->dev, of_clk_hw_onecell_get, + chip->clk_data); }/*
@@ -615,13 +601,6 @@ static int ac100_rtc_probe(struct platform_device *pdev)return devm_rtc_register_device (chip->rtc); } -static void ac100_rtc_remove (struct platform_device *pdev) -{ -struct ac100_rtc_dev *chip =platform_get_drvdata (pdev); - -ac100_rtc_unregister_clks (chip); -} -static const struct of_device_id ac100_rtc_match[] = { { .compatible ="x-powers,ac100-rtc" }, { },
@@ -630,7 +609,6 @@ MODULE_DEVICE_TABLE(of, ac100_rtc_match);static struct platform_driver ac100_rtc_driver = { .probe = ac100_rtc_probe, - .remove = ac100_rtc_remove, .driver = { .name ="ac100-rtc" , .of_match_table =of_match_ptr (ac100_rtc_match),
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 86/428 rtc: mpfs: fix unchecked devm_clk_get() error pointer in probe()
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Manush Prajwal <[email protected]>
[ Upstream commit ac41b05d15db3134e839148290d67415ee0bdb58 ]
devm_clk_get(&pdev->dev, "rtcref")'s return value was passed straight into clk_get_rate() without checking it for an error first, unlike the "rtc" clock a few lines above which is correctly checked with IS_ERR(). clk_get_rate() only guards against a NULL clk, not an error pointer:
if (!clk) return 0; ... rate = clk_core_get_rate_recalc(clk->core);
so if devm_clk_get() ever returns an error pointer here (for example ERR_PTR(-EPROBE_DEFER), which is the normal, expected outcome if the clkcfg clock-provider this RTC depends on has not registered its clocks yet by the time this driver probes), clk_get_rate() dereferences that error pointer instead of returning 0, crashing instead of letting probe defer.
Capture the clock in the existing 'clk' local and check it with IS_ERR() before calling clk_get_rate(), matching the handling already used for the "rtc" clock in this same function.
--- drivers/rtc/rtc-mpfs.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/rtc/rtc-mpfs.c +5 -1
@@ -256,8 +256,12 @@ static int mpfs_rtc_probe(struct platform_device *pdev)return ret; } + clk =devm_clk_get (&pdev->dev,"rtcref" ); +if (IS_ERR (clk)) +return PTR_ERR (clk); +/* prescaler hardware adds 1 to reg value */ - prescaler =clk_get_rate (devm_clk_get (&pdev->dev,"rtcref" )) -1 ; + prescaler =clk_get_rate (clk) -1 ;if (prescaler >MAX_PRESCALER_COUNT ) {dev_dbg (&pdev->dev,"invalid prescaler %lu\n" , prescaler);return -EINVAL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 87/428 wifi: mac80211: validate TX status rate metadata
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuqi Xu <[email protected]>
[ Upstream commit 6bdcdb31318c10e6369cff8e5b32c37397e98091 ]
minstrel_ht_tx_status() converts the HT/VHT rate reported in a TX status into a group and rate index and uses those to index the minstrel_ht rate tables. The existing validation only checked that an entry was present and had tries recorded; it did not check that the reported MCS, spatial stream count and bandwidth are representable by the tables, so malformed metadata passed to minstrel_ht_get_stats() or minstrel_ht_ri_get_stats() could be used as an out-of-bounds index.
Validate the rate metadata in the common TX status path instead of only in minstrel_ht, since the values are used by more than rate control. The legacy ieee80211_tx_rate array and the rate_info based entries are sanitized in ieee80211_tx_status_ext() and ieee80211_tx_rate_update() before any consumer runs: an entry that does not describe a valid rate for its encoding is dropped. minstrel_ht keeps the checks that depend on its own tables, i.e. the supported number of spatial streams, the MCS group size and the supported bandwidths.
This does not take away the driver's responsibility to report sane values, it only prevents a single bad report from corrupting mac80211 state. No WARN_ON() is added: with panic_on_warn a driver bug would otherwise turn into a denial of service.
--- net/mac80211/rc80211_minstrel_ht.c | 59 ++++++++++++++++++++++--- net/mac80211/status.c | 70 ++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+), 6 deletions(-)
net/mac80211/rc80211_minstrel_ht.c +53 -6
@@ -1193,6 +1193,54 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) mi->sample_time = jiffies; } +/* +* Check whether an HT/VHT rate from a TX status entry maps to an entry +* in the minstrel_ht rate tables. Values that cannot be represented +* there must not be used for indexing mi->groups[] and the MCS groups. +*/ +static bool +minstrel_ht_txstat_rate_valid (struct ieee80211_tx_rate *rate) +{ +unsigned int bw; + +if (!(rate->flags & (IEEE80211_TX_RC_MCS |IEEE80211_TX_RC_VHT_MCS ))) +return true; + +if (rate->flags &IEEE80211_TX_RC_MCS ) { +/* minstrel_ht supports up to MINSTREL_MAX_STREAMS streams */ +return rate->idx <MINSTREL_MAX_STREAMS *8 ; + } + +/* minstrel_ht has no VHT groups for 160 MHz and wider */ + bw = !!(rate->flags &IEEE80211_TX_RC_40_MHZ_WIDTH ) + +2 * !!(rate->flags &IEEE80211_TX_RC_80_MHZ_WIDTH ); +if ((rate->flags &IEEE80211_TX_RC_160_MHZ_WIDTH ) || bw >BW_80 ) +return false; + +return ieee80211_rate_get_vht_nss (rate) <=MINSTREL_MAX_STREAMS && +ieee80211_rate_get_vht_mcs (rate) <MCS_GROUP_RATES ; +} + +static bool +minstrel_ht_ri_txstat_rate_valid (struct rate_info *rate) +{ +if (!(rate->flags & (RATE_INFO_FLAGS_MCS |RATE_INFO_FLAGS_VHT_MCS ))) +return true; + +if (rate->flags &RATE_INFO_FLAGS_MCS ) { +/* minstrel_ht supports up to MINSTREL_MAX_STREAMS streams */ +return rate->mcs <MINSTREL_MAX_STREAMS *8 ; + } + +/* minstrel_ht has VHT groups only for 20/40/80 MHz */ +if (rate->bw !=RATE_INFO_BW_20 && rate->bw !=RATE_INFO_BW_40 && + rate->bw !=RATE_INFO_BW_80 ) +return false; + +return rate->nss <=MINSTREL_MAX_STREAMS && + rate->mcs <MCS_GROUP_RATES ; +} +static bool minstrel_ht_txstat_valid (struct minstrel_priv *mp,struct minstrel_ht_sta *mi,struct ieee80211_tx_rate *rate)
@@ -1205,9 +1253,8 @@ minstrel_ht_txstat_valid(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,if (!rate->count)return false; -if (rate->flags &IEEE80211_TX_RC_MCS || - rate->flags &IEEE80211_TX_RC_VHT_MCS ) -return true; +if (rate->flags & (IEEE80211_TX_RC_MCS |IEEE80211_TX_RC_VHT_MCS )) +return minstrel_ht_txstat_rate_valid (rate);for (i =0 ; i <ARRAY_SIZE (mp->cck_rates); i++)if (rate->idx == mp->cck_rates[i])
@@ -1235,9 +1282,9 @@ minstrel_ht_ri_txstat_valid(struct minstrel_priv *mp,if (!rate_status->try_count)return false; -if (rate_status->rate_idx.flags &RATE_INFO_FLAGS_MCS || - rate_status->rate_idx.flags &RATE_INFO_FLAGS_VHT_MCS ) -return true; +if (rate_status->rate_idx.flags & + (RATE_INFO_FLAGS_MCS |RATE_INFO_FLAGS_VHT_MCS )) +return minstrel_ht_ri_txstat_rate_valid (&rate_status->rate_idx);for (i =0 ; i <ARRAY_SIZE (mp->cck_rates); i++) { if (rate_status->rate_idx.legacy ==
net/mac80211/status.c +70 -0
88 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 88/428 wifi: cfg80211: preserve hidden-group beacon IE ownership
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhao Li <[email protected]>
[ Upstream commit cc45f313d85533d647ce619326302aad6f797c14 ]
A hidden-group probe-response entry borrows its beacon IEs from the group's beacon entry. cfg80211_update_assoc_bss_entry() can pass such an entry to cfg80211_update_known_bss() when merging scan entries after a channel switch.
Copying the borrowed beacon_ies into the associated entry gives the same allocation two owners. Releasing the group's beacon entry can then leave the associated entry pointing to freed IEs, which are freed again when that entry is released.
Skip beacon IE replacement when the source entry belongs to a hidden group. Preserve probe-response processing, the subsequent metadata updates, and the existing rejection path for conflicting hidden beacon updates.
--- net/wireless/scan.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-)
net/wireless/scan.c +12 -10
@@ -1964,20 +1964,22 @@ cfg80211_update_known_bss(struct cfg80211_registered_device *rdev,return false; } - old =rcu_access_pointer (known->pub.beacon_ies); +if (!new->pub.hidden_beacon_bss) { + old =rcu_access_pointer (known->pub.beacon_ies); -rcu_assign_pointer (known->pub.beacon_ies, new->pub.beacon_ies); +rcu_assign_pointer (known->pub.beacon_ies, new->pub.beacon_ies); -/* Override IEs if they were from a beacon before */ -if (old ==rcu_access_pointer (known->pub.ies)) -rcu_assign_pointer (known->pub.ies, new->pub.beacon_ies); +/* Override IEs if they were from a beacon before */ +if (old ==rcu_access_pointer (known->pub.ies)) +rcu_assign_pointer (known->pub.ies, new->pub.beacon_ies); -cfg80211_update_hidden_bsses (known, -rcu_access_pointer (new->pub.beacon_ies), - old); +cfg80211_update_hidden_bsses (known, +rcu_access_pointer (new->pub.beacon_ies), + old); -if (old) -kfree_rcu ((struct cfg80211_bss_ies *)old, rcu_head); +if (old) +kfree_rcu ((struct cfg80211_bss_ies *)old, rcu_head); + } } known->pub.beacon_interval = new->pub.beacon_interval;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 89/428 wifi: mac80211: prevent AP VLAN tx from other interfaces
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Fietkau <[email protected]>
[ Upstream commit 7f93ca31f7fd9b42e7d692f59514436d448ac908 ]
Since the station lookup was factored out of ieee80211_build_hdr(), ieee80211_lookup_ra_sta() uses sta_info_get_bss() for all AP and AP VLAN frames, not only for control port frames. A unicast frame sent on one interface thus matches a station of a different VLAN of the same BSS and is transmitted to it.
Only match stations of the interface the frame is sent on, except for control port frames, since those may be sent for VLAN stations directly on the BSS interface.
--- net/mac80211/ieee80211_i.h | 2 +- net/mac80211/tx.c | 24 +++++++++++++++--------- 2 files changed, 16 insertions(+), 10 deletions(-)
net/mac80211/ieee80211_i.h +1 -1
@@ -2478,7 +2478,7 @@ static inline bool ieee80211_require_encrypted_assoc(__le16 fc,/* sta_out needs to be checked for ERR_PTR() before using */ int ieee80211_lookup_ra_sta (struct ieee80211_sub_if_data *sdata,struct sk_buff *skb, -struct sta_info **sta_out); +struct sta_info **sta_out,bool bss); static inline void ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
net/mac80211/tx.c +15 -9
@@ -2523,7 +2523,7 @@ static inline bool ieee80211_is_tdls_setup(struct sk_buff *skb)int ieee80211_lookup_ra_sta (struct ieee80211_sub_if_data *sdata,struct sk_buff *skb, -struct sta_info **sta_out) +struct sta_info **sta_out,bool bss) {struct sta_info *sta;
@@ -2544,7 +2544,10 @@ int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata, *sta_out =ERR_PTR (-ENOENT );return 0 ; } - sta =sta_info_get_bss (sdata, skb->data); +if (bss) + sta =sta_info_get_bss (sdata, skb->data); +else + sta =sta_info_get (sdata, skb->data);break ;#ifdef CONFIG_MAC80211_MESH case NL80211_IFTYPE_MESH_POINT :
@@ -4390,7 +4393,8 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb, ieee80211_mesh_xmit_fast(sdata, skb, ctrl_flags)) goto out; -if (ieee80211_lookup_ra_sta (sdata, skb, &sta)) +if (ieee80211_lookup_ra_sta (sdata, skb, &sta, + skb->protocol == sdata->control_port_protocol)) goto out_free;if (IS_ERR (sta))
@@ -4820,7 +4824,10 @@ static void __ieee80211_subif_start_xmit_8023(struct sk_buff *skb,rcu_read_lock (); -if (ieee80211_lookup_ra_sta (sdata, skb, &sta)) { +if (unlikely (sdata->control_port_protocol == ehdr->h_proto)) + goto skip_offload; + +if (ieee80211_lookup_ra_sta (sdata, skb, &sta, false)) {kfree_skb (skb); goto out; }
@@ -4841,8 +4848,7 @@ static void __ieee80211_subif_start_xmit_8023(struct sk_buff *skb, link = &sdata->deflink; key =rcu_dereference (link->default_multicast_key); }else if (unlikely (IS_ERR_OR_NULL (sta) || !sta->uploaded || - !test_sta_flag (sta,WLAN_STA_AUTHORIZED ) || - sdata->control_port_protocol == ehdr->h_proto)) { + !test_sta_flag (sta,WLAN_STA_AUTHORIZED ))) { goto skip_offload; }else { key =rcu_dereference (sta->ptk[sta->ptk_idx]);
@@ -4903,7 +4909,7 @@ ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,rcu_read_lock (); -if (ieee80211_lookup_ra_sta (sdata, skb, &sta)) { +if (ieee80211_lookup_ra_sta (sdata, skb, &sta, false)) {kfree_skb (skb); skb =ERR_PTR (-EINVAL ); goto out;
@@ -4974,7 +4980,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, } result =ieee80211_tx (sdata,NULL , skb, true); }else if (info->flags &IEEE80211_TX_CTL_HW_80211_ENCAP ) { -if (ieee80211_lookup_ra_sta (sdata, skb, &sta)) { +if (ieee80211_lookup_ra_sta (sdata, skb, &sta, true)) {dev_kfree_skb (skb);return true; }
@@ -6611,7 +6617,7 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,* AF_PACKET */ rcu_read_lock (); - err =ieee80211_lookup_ra_sta (sdata, skb, &sta); + err =ieee80211_lookup_ra_sta (sdata, skb, &sta, true);if (err) {dev_kfree_skb (skb);rcu_read_unlock ();
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 90/428 ASoC: codecs: rt286: Revert delay value for jack setup
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cezary Rojewski <[email protected]>
[ Upstream commit d30fba93ebfc11e4604a7fcc73fdf28684191dde ]
Fat fingered the change when reorganizing the jack-detect initialization. Equivalent changes for rt274 and rt298:
Commit a43b4394bb35 ("ASoC: codecs: rt274: Always init jack_detect_work") Commit 1eb73102da28 ("ASoC: codecs: rt298: Reorganize jack detect handling")
carry no update to the delay value.
Quoted 1 line
From user perspective, no difference has been observed between 1250 and
50 values on Intel's SkyLake, KabyLake and AmberLake configurations.
--- sound/soc/codecs/rt286.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/codecs/rt286.c +1 -1
@@ -953,7 +953,7 @@ static int rt286_probe(struct snd_soc_component *component)if (rt286->i2c->irq)schedule_delayed_work (&rt286->jack_detect_work, -msecs_to_jiffies (50 )); +msecs_to_jiffies (1250 ));return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 91/428 ASoC: codecs: rt274: Fix format setting for 44100 rate
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cezary Rojewski <[email protected]>
[ Upstream commit 6eda8938a790f65bd24fcfaae7b40ad4613fb7a2 ]
As per specification, Sample Base Rate (bit 14) shall be set to 1 for 44.1 kHz.
--- sound/soc/codecs/rt274.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
sound/soc/codecs/rt274.c +3 -1
@@ -619,9 +619,11 @@ static int rt274_hw_params(struct snd_pcm_substream *substream,unsigned int val =0 ;int d_len_code =0 , c_len_code =0 ; +/* bit 14 Sample Rate Base, 0: 48kHz 1: 44.1kHz */ switch (params_rate (params)) { -/* bit 14 0:48K 1:44.1K */ case 44100 : + val |=BIT (14 ); +break ;case 48000 :break ;default :
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 92/428 block: reject polled dio with user integrity metadata
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yang Xiuwei <[email protected]>
[ Upstream commit 2a42e6fe1293f2e2d579c9fe5bbab056dd8b880e ]
IOCB_HAS_METADATA leaves iocb->private as a uio_meta, while iocb_bio_iopoll() expects a bio. Since 2729a60bbfb9, metadata I/O always uses __blkdev_direct_IO(), which never publishes the bio for polling, so IOPOLL calls bio_poll() on the uio_meta.
Reproducer: io_uring IOPOLL plus a PI attribute on an integrity device (scsi_debug dif=1 dix=1). KASAN reports:
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000004 KASAN: null-ptr-deref in range [0x0000000000000020-0x0000000000000027] RIP: 0010:bio_poll+0x9d/0x4b0 Call Trace: iocb_bio_iopoll+0x5b/0x80 io_uring_classic_poll+0xf3/0x140 io_do_iopoll+0x4e3/0xc00 io_iopoll_check+0x275/0x560 __do_sys_io_uring_enter+0x2e5/0x720
Return -EOPNOTSUPP when HIPRI is combined with user metadata.
--- block/fops.c | 5 +++++ 1 file changed, 5 insertions(+)
block/fops.c +5 -0
@@ -404,6 +404,11 @@ static ssize_t blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter)if (blkdev_dio_invalid (bdev, iocb, iter))return -EINVAL ; +/* HIPRI needs private as bio; HAS_METADATA keeps it as uio_meta */ +if ((iocb->ki_flags &IOCB_HIPRI ) && + (iocb->ki_flags &IOCB_HAS_METADATA )) +return -EOPNOTSUPP ; +if (iov_iter_rw (iter) ==WRITE ) {u16 max_write_streams =bdev_max_write_streams (bdev);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 93/428 blk-mq: set RQF_USE_SCHED when the operation is known
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Keith Busch <[email protected]>
[ Upstream commit ab6c756f28c741d704a7c3e04814bfc3adf6f818 ]
The cached requests are allocated for one operation but can be handed out for another. A passthrough command has RQF_USE_SCHED cleared, so using those flags for a subsequent read/write bio will insert it into the scheduler without ->prepare_request() and frees it without ->finish_request(). For kyber, this leaks the domain token acquired at dispatch and stalls the queue.
Don't set RQF_USE_SCHED based on the first operation the batch happened to be allocated for. Instead, set it after the request is claimed by an operation. Introduce a helper function, blk_mq_rq_late_init() for this, and absorb blk_mq_rq_time_init() since the two run together.
--- block/blk-mq.c | 59 ++++++++++++++++++++++++++++----------------- block/mq-deadline.c | 2 +- 2 files changed, 38 insertions(+), 23 deletions(-)
block/blk-mq.c +37 -22
@@ -447,16 +447,6 @@ static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data,WRITE_ONCE (rq->deadline,0 );req_ref_set (rq,1 ); -if (rq->rq_flags &RQF_USE_SCHED ) { -struct elevator_queue *e = data->q->elevator; - -INIT_HLIST_NODE (&rq->hash); -RB_CLEAR_NODE (&rq->rb_node); - -if (e->type->ops.prepare_request) - e->type->ops.prepare_request (rq); - } -return rq; }
@@ -498,6 +488,12 @@ __blk_mq_alloc_requests_batch(struct blk_mq_alloc_data *data)return rq_list_pop (data->cached_rqs); } +static bool blk_op_bypass_sched (blk_opf_t opf) +{ +return (opf &REQ_OP_MASK ) ==REQ_OP_FLUSH || +blk_op_is_passthrough (opf); +} +static void blk_mq_limit_depth (struct blk_mq_alloc_data *data) {struct elevator_mq_ops *ops;
@@ -518,12 +514,10 @@ static void blk_mq_limit_depth(struct blk_mq_alloc_data *data)* Flush/passthrough requests are special and go directly to the * dispatch list, they are not subject to the async_depth limit. */ -if ((data->cmd_flags &REQ_OP_MASK ) ==REQ_OP_FLUSH || -blk_op_is_passthrough (data->cmd_flags)) +if (blk_op_bypass_sched (data->cmd_flags))return ;WARN_ON_ONCE (data->flags &BLK_MQ_REQ_RESERVED ); - data->rq_flags |=RQF_USE_SCHED ;/* * By default, sync requests have no limit, and async requests are
@@ -534,6 +528,29 @@ static void blk_mq_limit_depth(struct blk_mq_alloc_data *data) ops->limit_depth (data->cmd_flags, data); } +/* +* Finish initializing a request once it has been claimed for an operation. +* Cached requests are allocated before that operation is known. +*/ +static void blk_mq_rq_late_init (struct request *rq,u64 alloc_time_ns) +{ +struct elevator_queue *e; + +blk_mq_rq_time_init (rq, alloc_time_ns); + +if (!(rq->rq_flags &RQF_SCHED_TAGS ) || (rq->rq_flags &RQF_RESV ) || +blk_op_bypass_sched (rq->cmd_flags)) +return ; + + rq->rq_flags |=RQF_USE_SCHED ; +INIT_HLIST_NODE (&rq->hash); +RB_CLEAR_NODE (&rq->rb_node); + + e = rq->q->elevator; +if (e->type->ops.prepare_request) + e->type->ops.prepare_request (rq); +} +static struct request *__blk_mq_alloc_requests (struct blk_mq_alloc_data *data) {struct request_queue *q = data->q;
@@ -562,7 +579,7 @@ static struct request *__blk_mq_alloc_requests(struct blk_mq_alloc_data *data)if (data->nr_tags >1 ) { rq =__blk_mq_alloc_requests_batch (data);if (rq) { -blk_mq_rq_time_init (rq, alloc_time_ns); +blk_mq_rq_late_init (rq, alloc_time_ns);return rq; } data->nr_tags =1 ;
@@ -590,7 +607,7 @@ static struct request *__blk_mq_alloc_requests(struct blk_mq_alloc_data *data)if (!(data->rq_flags &RQF_SCHED_TAGS ))blk_mq_inc_active_requests (data->hctx); rq =blk_mq_rq_ctx_init (data,blk_mq_tags_from_data (data), tag); -blk_mq_rq_time_init (rq, alloc_time_ns); +blk_mq_rq_late_init (rq, alloc_time_ns);return rq; }
@@ -637,8 +654,6 @@ static struct request *blk_mq_alloc_cached_request(struct request_queue *q,if (plug->nr_ios ==1 )return NULL ; rq =blk_mq_rq_cache_fill (q, plug, opf, flags); -if (!rq) -return NULL ; }else { rq =rq_list_peek (&plug->cached_rqs);if (!rq || rq->q != q)
@@ -650,11 +665,11 @@ static struct request *blk_mq_alloc_cached_request(struct request_queue *q,return NULL ;rq_list_pop (&plug->cached_rqs); -blk_mq_rq_time_init (rq,blk_time_get_ns ()); + rq->cmd_flags = opf; +INIT_LIST_HEAD (&rq->queuelist); +blk_mq_rq_late_init (rq,blk_time_get_ns ()); } - rq->cmd_flags = opf; -INIT_LIST_HEAD (&rq->queuelist);return rq; }
@@ -766,7 +781,7 @@ struct request *blk_mq_alloc_request_hctx(struct request_queue *q,if (!(data.rq_flags &RQF_SCHED_TAGS ))blk_mq_inc_active_requests (data.hctx); rq =blk_mq_rq_ctx_init (&data,blk_mq_tags_from_data (&data), tag); -blk_mq_rq_time_init (rq, alloc_time_ns); +blk_mq_rq_late_init (rq, alloc_time_ns); rq->__data_len =0 ; rq->phys_gap_bit =0 ; rq->__sector = (sector_t) -1 ;
@@ -3163,9 +3178,9 @@ void blk_mq_submit_bio(struct bio *bio) new_request:if (rq) {rq_qos_throttle (rq->q, bio); -blk_mq_rq_time_init (rq,blk_time_get_ns ()); rq->cmd_flags = bio->bi_opf;INIT_LIST_HEAD (&rq->queuelist); +blk_mq_rq_late_init (rq,blk_time_get_ns ()); }else { rq =blk_mq_get_new_requests (q, plug, bio);if (unlikely (!rq)) {
block/mq-deadline.c +1 -1
@@ -688,7 +688,7 @@ static void dd_insert_requests(struct blk_mq_hw_ctx *hctx,blk_mq_free_requests (&free); } -/* Callback from inside blk_mq_rq_ctx_init(). */ +/* Callback from inside blk_mq_rq_late_init(). */ static void dd_prepare_request (struct request *rq) { rq->elv.priv[0 ] =NULL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 94/428 Bluetooth: hci_core: free the HCI ID if naming fails
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sang-Hoon Choi <[email protected]>
[ Upstream commit d1ac915fb4184faad1b62148be50f317de7c24b5 ]
hci_register_dev() allocates an ID before calling dev_set_name(). If naming fails, it returns without releasing that ID. The device has not been registered and hdev->id has not been assigned, so the normal unregister path cannot release it.
Free the allocated ID before returning the naming error.
--- net/bluetooth/hci_core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
net/bluetooth/hci_core.c +3 -1
@@ -2554,8 +2554,10 @@ int hci_register_dev(struct hci_dev *hdev)return id; error =dev_set_name (&hdev->dev,"hci%u" , id); -if (error) +if (error) { +ida_free (&hci_index_ida, id);return error; + } hdev->name =dev_name (&hdev->dev); hdev->id = id;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 95/428 Bluetooth: btintel: validate DDC record lengths
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sai Teja Aluvala <[email protected]>
[ Upstream commit c9c15d4d8956df8c564f7c210e4dc5b9b820d97a ]
Parse DDC record lengths in unsigned storage so 0xFF does not wrap. Reject records smaller than the mandatory three-byte header, records exceeding U8_MAX, and records exceeding remaining firmware bytes before issuing Intel_Write_DDC.
This issue was reported by Claude Mythos.
--- drivers/bluetooth/btintel.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
drivers/bluetooth/btintel.c +10 -2
@@ -407,8 +407,16 @@ int btintel_load_ddc_config(struct hci_dev *hdev, const char *ddc_name)/* DDC file contains one or more DDC structure which has * Length (1 byte), DDC ID (2 bytes), and DDC value (Length - 2). */ -while (fw->size > fw_ptr - fw->data) { -u8 cmd_plen = fw_ptr[0 ] +sizeof (u8); +while (fw->size > (size_t )(fw_ptr - fw->data)) { +size_t remaining = fw->size - (fw_ptr - fw->data); +unsigned int cmd_plen = fw_ptr[0 ] +1U ; + +if (cmd_plen <3 || cmd_plen >U8_MAX || cmd_plen > remaining) { +bt_dev_err (hdev,"Malformed DDC record (plen=%u, remaining=%zu)" , + cmd_plen, remaining); +release_firmware (fw); +return -EINVAL ; + } skb =__hci_cmd_sync (hdev,0xfc8b , cmd_plen, fw_ptr,HCI_INIT_TIMEOUT );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 96/428 mm/slab: handle the !allow_spin case in kfree_rcu_sheaf()
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Harry Yoo (Oracle) <[email protected]>
[ Upstream commit f3521fbec2b2839698eba2b7013ed20119416e6d ]
Teach kfree_rcu_sheaf() how to handle the !allow_spin case. Try to get an empty sheaf from pcs->spare or the barn even when spinning is not allowed. Unlike __pcs_replace_full_main(), try harder to allocate an empty sheaf because the fallback path will be more expensive than kfree_nolock().
Now that slab has internal alloc_flags to describe context, introduce free_flags analogously and convert free_flags to alloc_flags when allocating memory in the free path.
When trylock fails or the kernel observes non-NULL pcs->rcu_free after lock acquisition, free the sheaf instead of putting it to the barn. This is rare and not worth complicating the code.
Since call_rcu() cannot be called in an unknown context, kfree_rcu_sheaf() fails when the rcu sheaf becomes full.
Stable-dep-of: af2fb3ee6679 ("mm/slab: do not wake up kswapd in __kfree_rcu_sheaf()")
--- mm/slab.h | 18 +++++++++++++++++- mm/slab_common.c | 2 +- mm/slub.c | 34 ++++++++++++++++++++++++++-------- 3 files changed, 44 insertions(+), 10 deletions(-)
mm/slab.h +17 -1
@@ -24,11 +24,27 @@#define SLAB_ALLOC_NO_RECURSE 0x04/* prevent kmalloc() recursion */ #define SLAB_ALLOC_NO_OBJ_EXT 0x08/* prevent obj_exts array allocation */ +#define SLAB_FREE_DEFAULT 0x00/* no flags */ +#define SLAB_FREE_NOLOCK 0x01/* spinning not allowed */ + +static inline unsigned int to_alloc_flags (unsigned int free_flags) +{ +if (free_flags &SLAB_FREE_NOLOCK ) +return SLAB_ALLOC_NOLOCK ; +else +return SLAB_ALLOC_DEFAULT ; +} +static inline bool alloc_flags_allow_spinning (const unsigned int alloc_flags) {return !(alloc_flags &SLAB_ALLOC_NOLOCK ); } +static inline bool free_flags_allow_spinning (const unsigned int free_flags) +{ +return !(free_flags &SLAB_FREE_NOLOCK ); +} +void *__kmalloc_flags_noprof (DECL_TOKEN_PARAMS (size ,token ),gfp_t flags,unsigned int alloc_flags,int node) __assume_kmalloc_alignment__alloc_size(1) ;
@@ -436,7 +452,7 @@ static inline bool is_kmalloc_normal(struct kmem_cache *s)return !(s->flags & (SLAB_CACHE_DMA |SLAB_ACCOUNT |SLAB_RECLAIM_ACCOUNT |SLAB_NO_OBJ_EXT )); } -bool __kfree_rcu_sheaf (struct kmem_cache *s,void *obj); +bool __kfree_rcu_sheaf (struct kmem_cache *s,void *obj,unsigned int free_flags);void flush_all_rcu_sheaves (void );void flush_rcu_sheaves_on_cache (struct kmem_cache *s);
mm/slab_common.c +1 -1
@@ -1622,7 +1622,7 @@ static bool kfree_rcu_sheaf(void *obj) s = slab->slab_cache;if (likely (!IS_ENABLED (CONFIG_NUMA ) ||slab_nid (slab) ==numa_mem_id ())) -return __kfree_rcu_sheaf (s, obj); +return __kfree_rcu_sheaf (s, obj,SLAB_FREE_DEFAULT );return false; }
mm/slub.c +26 -8
@@ -2777,7 +2777,8 @@ static inline struct slab_sheaf *alloc_empty_sheaf(struct kmem_cache *s,return __alloc_empty_sheaf (s, gfp, alloc_flags, s->sheaf_capacity); } -static void free_empty_sheaf (struct kmem_cache *s,struct slab_sheaf *sheaf) +static void __free_empty_sheaf (struct kmem_cache *s,struct slab_sheaf *sheaf, +unsigned int free_flags) {/* * If the sheaf was created with SLAB_ALLOC_NO_RECURSE flag then its
@@ -2789,11 +2790,20 @@ static void free_empty_sheaf(struct kmem_cache *s, struct slab_sheaf *sheaf)mark_obj_codetag_empty (sheaf);VM_WARN_ON_ONCE (sheaf->size >0 ); -kfree (sheaf); + +if (unlikely (free_flags &SLAB_FREE_NOLOCK )) +kfree_nolock (sheaf); +else +kfree (sheaf);stat (s,SHEAF_FREE ); } +static void free_empty_sheaf (struct kmem_cache *s,struct slab_sheaf *sheaf) +{ +__free_empty_sheaf (s, sheaf,SLAB_FREE_DEFAULT ); +} +static unsigned int refill_objects (struct kmem_cache *s,void **p,gfp_t gfp,unsigned int min,unsigned int max);
@@ -6038,10 +6048,11 @@ static void rcu_free_sheaf(struct rcu_head *head)*/ static DEFINE_WAIT_OVERRIDE_MAP(kfree_rcu_sheaf_map, LD_WAIT_CONFIG); -bool __kfree_rcu_sheaf (struct kmem_cache *s,void *obj) +bool __kfree_rcu_sheaf (struct kmem_cache *s,void *obj,unsigned int free_flags) {struct slub_percpu_sheaves *pcs;struct slab_sheaf *rcu_sheaf; +bool allow_spin =free_flags_allow_spinning (free_flags);if (WARN_ON_ONCE (IS_ENABLED (CONFIG_PREEMPT_RT )))return false;
@@ -6054,9 +6065,10 @@ bool __kfree_rcu_sheaf(struct kmem_cache *s, void *obj) pcs =this_cpu_ptr (s->cpu_sheaves);if (unlikely (!pcs->rcu_free)) { -struct slab_sheaf *empty;struct node_barn *barn; +unsigned int alloc_flags =to_alloc_flags (free_flags); +gfp_t gfp = allow_spin ?GFP_NOWAIT : __GFP_NOWARN;/* Bootstrap or debug cache, fall back */ if (unlikely (!cache_has_sheaves (s))) {
@@ -6076,7 +6088,7 @@ bool __kfree_rcu_sheaf(struct kmem_cache *s, void *obj) goto fail; } - empty =barn_get_empty_sheaf (barn, true); + empty =barn_get_empty_sheaf (barn, allow_spin);if (empty) { pcs->rcu_free = empty;
@@ -6085,20 +6097,20 @@ bool __kfree_rcu_sheaf(struct kmem_cache *s, void *obj)local_unlock (&s->cpu_sheaves->lock); - empty =alloc_empty_sheaf (s,GFP_NOWAIT ,SLAB_ALLOC_DEFAULT ); + empty =alloc_empty_sheaf (s, gfp, alloc_flags);if (!empty) goto fail;if (!local_trylock (&s->cpu_sheaves->lock)) { -barn_put_empty_sheaf (barn, empty); +__free_empty_sheaf (s, empty, free_flags); goto fail; } pcs =this_cpu_ptr (s->cpu_sheaves);if (unlikely (pcs->rcu_free)) -barn_put_empty_sheaf (barn, empty); +__free_empty_sheaf (s, empty, free_flags);else pcs->rcu_free = empty; }
@@ -6116,6 +6128,12 @@ bool __kfree_rcu_sheaf(struct kmem_cache *s, void *obj)if (likely (rcu_sheaf->size < s->sheaf_capacity)) { rcu_sheaf =NULL ; }else { +if (unlikely (!allow_spin)) { +/* call_rcu() cannot be called in an unknown context */ + rcu_sheaf->size--; +local_unlock (&s->cpu_sheaves->lock); + goto fail; + } pcs->rcu_free =NULL ; rcu_sheaf->node =numa_node_id (); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 97/428 mm/slab: do not wake up kswapd in __kfree_rcu_sheaf()
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Harry Yoo (Meta) <[email protected]>
[ Upstream commit af2fb3ee6679b517e2fdbd3ba16ec276a8b74312 ]
Since kfree_rcu() can be called under pi_lock (a raw spinlock in the scheduler), kfree_rcu() itself should never allocate memory with __GFP_KSWAPD_RECLAIM as waking up kswapd ends up acquiring pi_lock, which leads to a deadlock.
Reproducing the issue even intentionally was not straightforward. The set_cpus_allowed_force() path that is called under pi_lock is exercised very rarely, and competing tasks that allocate memory will most likely wake kswapd up.
Therefore the existence of the deadlock was verified with a modified kernel that has a lockdep map for waking up kswapd:
======================================================
WARNING: possible circular locking dependency detected 7.2.0-rc1-slab-for-next+ #10 Not tainted
------------------------------------------------------
git/6660 is trying to acquire lock:
ffff8e524533c550 (&p->pi_lock){-.-.}-{2:2}, at: _raw_spin_lock_irqsave+0x12/0x20
but task is already holding lock:
ffff8e57bffff1a0 (&pgdat->kswapd_wait){....}-{3:3}, at: _raw_spin_lock_irqsave+0x12/0x20
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #2 (&pgdat->kswapd_wait){....}-{3:3}:
__lock_acquire+0x5a4/0xc50
lock_acquire.part.0+0xb7/0x240
lock_acquire+0x70/0x170
__raw_spin_lock_irqsave+0x44/0x80
_raw_spin_lock_irqsave+0x12/0x20
__wake_up_common_lock+0x31/0xa0
__wake_up+0x20/0x40
kswapd_wakeup_wake+0x7e/0x110
wakeup_kswapd+0x295/0x320
wake_all_kswapds+0xac/0x1a0
__alloc_pages_slowpath.constprop.0+0x282/0xf80
__alloc_frozen_pages_noprof+0x32a/0x360
alloc_slab_page+0x2e/0x160
allocate_slab+0x82/0x420
new_slab+0x52/0xb0
refill_objects+0x13d/0x190
refill_sheaf+0x5d/0xd0
__pcs_replace_empty_main+0x230/0xb10
[...]-> #1 (kswapd_wakeup){-.-.}-{0:0}:
__lock_acquire+0x5a4/0xc50
lock_sync.part.0+0x75/0x100
lock_sync+0x36/0x70
might_wakeup_kswapd+0x61/0xa0
__kfree_rcu_sheaf+0x33/0xd90
kvfree_call_rcu+0x1d4/0x3b0
set_cpus_allowed_force+0x163/0x220
cpuset_cpus_allowed_fallback+0x18b/0x240
select_fallback_rq+0x1e6/0x250
[...]-> #0 (&p->pi_lock){-.-.}-{2:2}:
check_prev_add+0xe6/0xe00
validate_chain+0x51e/0x6e0
__lock_acquire+0x5a4/0xc50
lock_acquire.part.0+0xb7/0x240
lock_acquire+0x70/0x170
__raw_spin_lock_irqsave+0x44/0x80
_raw_spin_lock_irqsave+0x12/0x20
try_to_wake_up+0x77/0xa90
default_wake_function+0x27/0x60
autoremove_wake_function+0x23/0xb0
__wake_up_common+0xb8/0x170
__wake_up_common_lock+0x51/0xa0
__wake_up+0x20/0x40
kswapd_wakeup_wake+0x7e/0x110
wakeup_kswapd+0x295/0x320
wake_all_kswapds+0xac/0x1a0
__alloc_pages_slowpath.constprop.0+0x282/0xf80
__alloc_frozen_pages_noprof+0x32a/0x360
alloc_slab_page+0x2e/0x160
allocate_slab+0x82/0x420
new_slab+0x52/0xb0
refill_objects+0x13d/0x190
refill_sheaf+0x5d/0xd0
__pcs_replace_empty_main+0x230/0xb10
[...]other info that might help us debug this:
Chain exists of:
&p->pi_lock --> kswapd_wakeup --> &pgdat->kswapd_wait
Possible unsafe locking scenario: CPU0 CPU1
---- ----
lock(&pgdat->kswapd_wait);
lock(kswapd_wakeup);
lock(&pgdat->kswapd_wait);
lock(&p->pi_lock);*** DEADLOCK ***
3 locks held by git/6660:
#0: ffff8e519f0e9e20 (&type->i_mutex_dir_key#6){++++}-{4:4}, at: lookup_slow+0x2d/0x60 #1: ffffffff8a31c460 (kswapd_wakeup){-.-.}-{0:0}, at: kswapd_wakeup_wake+0x4d/0x110 #2: ffff8e57bffff1a0 (&pgdat->kswapd_wait){....}-{3:3}, at: _raw_spin_lock_irqsave+0x12/0x20
[...]
Fix this by always avoiding waking up kswapd in __kfree_rcu_sheaf(). Note that there are two paths that might wake up kswapd:
1) __kfree_rcu_sheaf()
// __GFP_KSWAPD_RECLAIM might wake up kswapd
-> alloc_empty_sheaf(GFP_NOWAIT) 2) __kfree_rcu_sheaf()
// Let's say __kfree_rcu_sheaf() doesn't pass GFP_NOWAIT
-> alloc_empty_sheaf(__GFP_NOWARN)
-> kmalloc_flags()
-> slab_alloc_node()
-> alloc_from_pcs()
-> __pcs_replace_empty_main()
// Free a sheaf in an allocation path when the sheaf becomes empty
// and refilling the sheaf fails
-> free_empty_sheaf()
-> slab_free()
-> free_to_pcs()
-> __pcs_replace_full_main()
// However free path always assumes it's safe to wake up kswapd
-> alloc_empty_sheaf(GFP_NOWAIT)Drop __GFP_KSWAPD_RECLAIM in both cases. Note that the kfree_rcu() is not the only user of free_to_pcs() path, but it should be fixed as it can be invoked under pi_lock.
--- mm/slub.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
mm/slub.c +4 -3
@@ -5911,7 +5911,8 @@ __pcs_replace_full_main(struct kmem_cache *s, struct slub_percpu_sheaves *pcs,if (!allow_spin)return NULL ; - empty =alloc_empty_sheaf (s,GFP_NOWAIT ,SLAB_ALLOC_DEFAULT ); +/* Don't wake up kswapd, it will cause deadlock under pi_lock */ + empty =alloc_empty_sheaf (s, __GFP_NOWARN,SLAB_ALLOC_DEFAULT );if (empty) goto got_empty;
@@ -6068,7 +6069,6 @@ bool __kfree_rcu_sheaf(struct kmem_cache *s, void *obj, unsigned int free_flags)struct slab_sheaf *empty;struct node_barn *barn;unsigned int alloc_flags =to_alloc_flags (free_flags); -gfp_t gfp = allow_spin ?GFP_NOWAIT : __GFP_NOWARN;/* Bootstrap or debug cache, fall back */ if (unlikely (!cache_has_sheaves (s))) {
@@ -6097,7 +6097,8 @@ bool __kfree_rcu_sheaf(struct kmem_cache *s, void *obj, unsigned int free_flags)local_unlock (&s->cpu_sheaves->lock); - empty =alloc_empty_sheaf (s, gfp, alloc_flags); +/* Don't wake up kswapd, it will cause deadlock under pi_lock */ + empty =alloc_empty_sheaf (s, __GFP_NOWARN, alloc_flags);if (!empty) goto fail;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 98/428 arm64: topology: fix arch_freq_get_on_cpu() overflow above 4.19 GHz
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oleg Keri <[email protected]>
[ Upstream commit 3872cc6b92940af0f73c6f9a45d65300492d648d ]
arch_freq_get_on_cpu() computes the product of the frequency scale and the reference frequency as a u64, but assigns it to an unsigned int before shifting it back down:
freq = scale * arch_scale_freq_ref(cpu); freq >>= SCHED_CAPACITY_SHIFT;
The product is truncated to 32 bits before the shift, so the result wraps once arch_scale_freq_ref() exceeds 2^32 / SCHED_CAPACITY_SCALE, i.e. 4194304 kHz.
On a Snapdragon X2 Elite (Glymur) laptop, whose boost OPP is 4723200 kHz, cpuinfo_avg_freq reports 524283 kHz instead of ~4723200 kHz while the CPU demonstrably runs at the boost frequency: a fixed workload completes in 1.72 s at the 4723200 kHz OPP versus 2.01 s at 4032000 kHz, matching the 1.171 frequency ratio.
Shift the u64 product and narrow only at the return.
--- arch/arm64/kernel/topology.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
arch/arm64/kernel/topology.c +2 -4
@@ -186,7 +186,6 @@ int arch_freq_get_on_cpu(int cpu)struct amu_cntr_sample *amu_sample;unsigned int start_cpu = cpu;unsigned long last_update; -unsigned int freq =0 ;u64 scale;if (!amu_fie_cpu_supported (cpu) || !arch_scale_freq_ref (cpu))
@@ -245,9 +244,8 @@ int arch_freq_get_on_cpu(int cpu)* (see amu_scale_freq_tick for details) */ scale =arch_scale_freq_capacity (cpu); - freq = scale *arch_scale_freq_ref (cpu); - freq >>=SCHED_CAPACITY_SHIFT ; -return freq; + +return (scale *arch_scale_freq_ref (cpu)) >>SCHED_CAPACITY_SHIFT ; }static void amu_fie_setup (const struct cpumask *cpus)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 99/428 ASoC: SDCA: Set suspended flag after resuming within system suspend
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maciej Strozek <[email protected]>
[ Upstream commit b16610e3770ef22fc8fcce818db0cd955332abf4 ]
drv->suspended path was executed before system suspension instead of after, move it lower to correct it.
--- sound/soc/sdca/sdca_class_function.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
sound/soc/sdca/sdca_class_function.c +2 -2
@@ -490,8 +490,6 @@ static int class_function_suspend(struct device *dev)struct class_function_drv *drv =auxiliary_get_drvdata (auxdev);int ret; - drv->suspended = true; -/* Ensure runtime resume runs on resume */ ret =pm_runtime_resume_and_get (dev);if (ret) {
@@ -499,6 +497,8 @@ static int class_function_suspend(struct device *dev)return ret; } + drv->suspended = true; +sdca_irq_disable (drv->function, drv->core->irq_info); ret =pm_runtime_force_suspend (dev);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 100/428 ASoC: SDCA: Add better pm_runtime error handling in func probe
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maciej Strozek <[email protected]>
[ Upstream commit 91094f9c86216898ce92141c26c8fec7e97544c0 ]
Add a common error path in probe that balances the runtime PM reference.
--- sound/soc/sdca/sdca_class_function.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
sound/soc/sdca/sdca_class_function.c +11 -4
@@ -388,20 +388,27 @@ static int class_function_probe(struct auxiliary_device *auxdev, ret =devm_pm_runtime_enable (dev);if (ret) -return ret; + goto err_pm; ret =class_function_boot (drv);if (ret) -return ret; + goto err_pm; ret =devm_snd_soc_register_component (dev, cmp_drv, dais, num_dais); -if (ret) -return dev_err_probe (dev, ret,"failed to register component\n" ); +if (ret) { +dev_err_probe (dev, ret,"failed to register component\n" ); + goto err_pm; + }pm_runtime_mark_last_busy (dev);pm_runtime_put_autosuspend (dev);return 0 ; + +err_pm: +pm_runtime_put_sync (dev); + +return ret; }static void class_function_remove (struct auxiliary_device *auxdev)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 101/428 drbd: remove unused drbd_nl_mcgrps[] array
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnd Bergmann <[email protected]>
[ Upstream commit d431e03d831c043707e22311c4bdea1907166c34 ]
After the rework, two files have a copy of drbd_nl_mcgrps[], but one of them has no references:
drivers/block/drbd/drbd_nl_gen.c:641:42: error: 'drbd_nl_mcgrps' defined but not used [-Werror=unused-const-variable=]
641 | static const struct genl_multicast_group drbd_nl_mcgrps[] = {
| ^~~~~~~~~~~~~~At the default warning level, -Wunused-const-variables is turned off, so this has gone unnoticed.
Remove the extra variable.
--- drivers/block/drbd/drbd_nl_gen.c | 4 ---- 1 file changed, 4 deletions(-)
drivers/block/drbd/drbd_nl_gen.c +0 -4
@@ -638,10 +638,6 @@ const struct genl_split_ops drbd_nl_ops[32] = { }, }; -static const struct genl_multicast_group drbd_nl_mcgrps[] = { - [DRBD_NLGRP_EVENTS ] = {"events" , }, -}; -static int __drbd_cfg_context_from_attrs (struct drbd_cfg_context *s,struct nlattr ***ret_nested_attribute_table,struct genl_info *info)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 102/428 bpf: Fix overflow of jump offset in constant blinding
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexei Starovoitov <[email protected]>
[ Upstream commit ad139384ecddb6f3e7e3c3c12765aafae0e39670 ]
bpf_jit_blind_insn() rewrites 'if rX op imm goto off' into:
AX = imm ^ rnd
AX ^= rnd
if rX op AX goto off
and subtracts 2 from off when the jump is backward. off is s16, so -32767 and -32768 wrap and the jump goes 32767 insns forward, past the end of the prog. The jump is inside the patch, hence bpf_adj_branches() doesn't check it. The kernel crashes when such prog runs with bpf_jit_harden=2.
Return -ERANGE in such case. bpf_jit_blind_constants() fails the same way when blinding of other insns moves a jump out of range.
--- kernel/bpf/core.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
kernel/bpf/core.c +8 -2
@@ -1355,7 +1355,7 @@ static int bpf_jit_blind_insn(const struct bpf_insn *from, {struct bpf_insn *to = to_buff;u32 imm_rnd =get_random_u32 (); -s16 off; +int off;BUILD_BUG_ON (BPF_REG_PARAMS +2 !=MAX_BPF_JIT_REG );BUILD_BUG_ON (BPF_REG_AX +1 !=MAX_BPF_JIT_REG );
@@ -1431,6 +1431,8 @@ static int bpf_jit_blind_insn(const struct bpf_insn *from, off = from->off;if (off <0 ) off -=2 ; +if (off <S16_MIN ) +return -ERANGE ; *to++ =BPF_ALU64_IMM (BPF_MOV ,BPF_REG_AX , imm_rnd ^ from->imm); *to++ =BPF_ALU64_IMM (BPF_XOR ,BPF_REG_AX , imm_rnd); *to++ =BPF_JMP_REG (from->code, from->dst_reg,BPF_REG_AX , off);
@@ -1451,6 +1453,8 @@ static int bpf_jit_blind_insn(const struct bpf_insn *from, off = from->off;if (off <0 ) off -=2 ; +if (off <S16_MIN ) +return -ERANGE ; *to++ =BPF_ALU32_IMM (BPF_MOV ,BPF_REG_AX , imm_rnd ^ from->imm); *to++ =BPF_ALU32_IMM (BPF_XOR ,BPF_REG_AX , imm_rnd); *to++ = BPF_JMP32_REG(from->code, from->dst_reg, BPF_REG_AX,
@@ -1599,7 +1603,9 @@ struct bpf_prog *bpf_jit_blind_constants(struct bpf_verifier_env *env, struct bpif (!rewritten)continue ; -if (env) +if (rewritten <0 ) + tmp =ERR_PTR (rewritten); +else if (env) tmp =bpf_patch_insn_data (env, i, insn_buff, rewritten);else tmp =bpf_patch_insn_single (clone, i, insn_buff, rewritten);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 103/428 ARC: arch_cmpxchg_relaxed to use size of pointed type not pointer
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vineet Gupta <[email protected]>
[ Upstream commit f050c3e61d2a1aaece3170d459e4ce5fa2486c12 ]
Bradley spotted this snafu when working on two-byte cmpxchg emulation. He originally folded this fix into his series but the fix itself uncovered a pre-existing issue, missing arch_atomic64_cmpxchg_relaxed which just needed to be wired up.
--- arch/arc/include/asm/atomic64-arcv2.h | 6 ++++++ arch/arc/include/asm/cmpxchg.h | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-)
arch/arc/include/asm/atomic64-arcv2.h +6 -0
@@ -156,6 +156,12 @@ static inline u64 __arch_cmpxchg64_relaxed(volatile void *ptr, u64 old, u64 new) }#define arch_cmpxchg64_relaxed __arch_cmpxchg64_relaxed +static inline s64 arch_atomic64_cmpxchg_relaxed (atomic64_t *v,s64 old,s64 new) +{ +return arch_cmpxchg64_relaxed (&v->counter, old, new); +} +#define arch_atomic64_cmpxchg_relaxed arch_atomic64_cmpxchg_relaxed +static inline s64 arch_atomic64_xchg (atomic64_t *ptr,s64 new) {s64 prev;
arch/arc/include/asm/cmpxchg.h +2 -2
@@ -46,7 +46,7 @@ __typeof__(*(ptr)) _n_ = (new); \ __typeof__(*(ptr)) _prev_; \ \ -switch (sizeof ((_p_))) { \ +switch (sizeof (*(_p_))) { \case 1 : \ _prev_ = (__typeof__(*(ptr)))cmpxchg_emu_u8((volatile u8 *__force)_p_, (uintptr_t)_o_, (uintptr_t)_n_); \break ; \
@@ -102,7 +102,7 @@__typeof__ (ptr) _p_ = (ptr); \ __typeof__(*(ptr)) _val_ = (val); \ \ -switch (sizeof (*(_p_))) { \ +switch (sizeof (*(_p_))) { \case 4 : \ _val_ =__arch_xchg (_p_, _val_); \break ; \
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 104/428 nvme: add nvme_get_ns_head()
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Garry <[email protected]>
[ Upstream commit a11e0a4cb4189c468683a2f384f0c266c26a497f ]
Add a wrapper for getting a reference to the NS head.
This would be used in scenarios when we know that getting a reference would not fail.
Stable-dep-of: 6b8a5367e9e7 ("nvme: work around -Wformat-security warning")
--- drivers/nvme/host/core.c | 5 +++++ drivers/nvme/host/multipath.c | 2 +- drivers/nvme/host/nvme.h | 1 + 3 files changed, 7 insertions(+), 1 deletion(-)
drivers/nvme/host/core.c +5 -0
@@ -691,6 +691,11 @@ static void nvme_free_ns_head(struct krekfree (head); } +void nvme_get_ns_head (struct nvme_ns_head *head) +{ +kref_get (&head->ref); +} +bool nvme_tryget_ns_head (struct nvme_ns_head *head) {return kref_get_unless_zero (&head->ref);
drivers/nvme/host/multipath.c +1 -1
@@ -777,7 +777,7 @@ int nvme_mpath_alloc_disk(struct nvme_ctset_bit (GD_SUPPRESS_PART_SCAN , &head->disk->state);sprintf (head->disk->disk_name,"nvme%dn%d" , ctrl->subsys->instance, head->instance); -nvme_tryget_ns_head (head); +nvme_get_ns_head (head);return 0 ; }
drivers/nvme/host/nvme.h +1 -0
@@ -1005,6 +1005,7 @@ int nvme_delete_ctrl(struct nvme_ctrl *cvoid nvme_queue_scan (struct nvme_ctrl *ctrl);int nvme_get_log (struct nvme_ctrl *ctrl,u32 nsid,u8 log_page,u8 lsp,u8 csi,void *log,size_t size,u64 offset); +void nvme_get_ns_head (struct nvme_ns_head *head);bool nvme_tryget_ns_head (struct nvme_ns_head *head);void nvme_put_ns_head (struct nvme_ns_head *head); int nvme_cdev_add(const char *name, struct cdev *cdev,
Greg Kroah-Hartman
maintainerPATCH 105/428 nvme: fix cdev lifetime
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Garry <[email protected]>
[ Upstream commit 9952f3882ecba709092379b71e02b09762b26f96 ]
Sashiko bot reported a potential problem for the cdev lifetime in [0]
- the code there is heavily based on the NVMe code.
Currently the NS head .open and .release file_operations methods take and put a reference to the nvme_ns_head to ensure that this structure does not disappear while we open fds for that cdev.
In multipath mode, when we teardown the NS head, we call nvme_cdev_del() -> cdev_device_del() -> cdev_del(). However after cdev_del() returns, cdevs already open will remain and their fops will still be callable. As such, we can still reference the cdev after the nvme_ns_head reference count drops to 0 (and is freed).
This can be shown with an application which delays between opening the cdev and issuing the ioctl while the NS head is being torn down:
# ./ioctl_file /dev/ng1n1 & # waiting 10 seconds ....
# ./ini_nvme_teardown.sh [ 21.221718] nvme nvme1: Removing ctrl: NQN "nvme-test-target" [ 21.274609] nvme nvme2: Removing ctrl: NQN "nvme-test-target" # now going to issue ioctl .... [ 26.549285] ================================================================== [ 26.550841] BUG: KASAN: slab-use-after-free in cdev_put.part.0+0x3d/0x40 [ 26.552352] Read of size 8 at addr ffff88811e7fa170 by task ioctl_file/237 [ 26.553805] [ 26.554227] CPU: 3 UID: 0 PID: 237 Comm: ioctl_file Not tainted 7.2.0-rc1-00004-g6852a10e32d4 #921 PREEMPT(lazy) [ 26.554236] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 [ 26.554241] Call Trace: [ 26.554245] <TASK> [ 26.554248] dump_stack_lvl+0x68/0xa0 [ 26.554266] print_report+0x10d/0x5d0 [ 26.554276] ? __virt_addr_valid+0x21d/0x3f0 [ 26.554287] ? cdev_put.part.0+0x3d/0x40 [ 26.554292] kasan_report+0x96/0xd0 [ 26.554300] ? cdev_put.part.0+0x3d/0x40 [ 26.554307] cdev_put.part.0+0x3d/0x40 [ 26.554313] __fput+0x7bc/0xa70 [ 26.554322] fput_close_sync+0xd8/0x190 [ 26.554328] ? __pfx_fput_close_sync+0x10/0x10 [ 26.554337] __x64_sys_close+0x79/0xd0 [ 26.554344] do_syscall_64+0x117/0x6b0 [ 26.554351] entry_SYSCALL_64_after_hwframe+0x77/0x7f [ 26.554358] RIP: 0033:0x7f938c067727 [ 26.554364] Code: 48 89 fa 4c 89 df e8 28 ad 00 00 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 1a 5b c3 0f 1f 84 00 00 00 00 00 48 8b 44 24 10 0f 05 <5bf [ 26.554369] RSP: 002b:00007fff49f05980 EFLAGS: 00000202 ORIG_RAX: 0000000000000003 [ 26.554376] RAX: ffffffffffffffda RBX: 00007f938bfd7780 RCX: 00007f938c067727 [ 26.554380] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000003 [ 26.554383] RBP: 00007fff49f05a10 R08: 0000000000000000 R09: 0000000000000000 [ 26.554386] R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000000 [ 26.554389] R13: 00007fff49f05b40 R14: 00007f938c207000 R15: 000055c148471d78 [ 26.554397] </TASK> [ 26.554399] [ 26.575612] Allocated by task 100: [ 26.575871] kasan_save_stack+0x24/0x50 [ 26.576157] kasan_save_track+0x14/0x30 [ 26.576418] __kasan_kmalloc+0x7f/0x90 [ 26.576668] __kmalloc_noprof+0x281/0x6c0 [ 26.576938] nvme_alloc_ns+0x7f7/0x3170 [ 26.577206] nvme_scan_ns+0x508/0x880 [ 26.577449] async_run_entry_fn+0x8c/0x350 [ 26.577723] process_scheduled_works+0xb6f/0x1a00 [ 26.578034] worker_thread+0x4ad/0xb40 [ 26.578283] kthread+0x34f/0x450 [ 26.578501] ret_from_fork+0x563/0x800 [ 26.578752] ret_from_fork_asm+0x1a/0x30 [ 26.579012] [ 26.579124] Freed by task 237: [ 26.579335] kasan_save_stack+0x24/0x50 [ 26.579596] kasan_save_track+0x14/0x30 [ 26.579855] kasan_save_free_info+0x3a/0x60 [ 26.580131] __kasan_slab_free+0x43/0x70 [ 26.580388] kfree+0x321/0x500 [ 26.580591] nvme_ns_head_chr_release+0x39/0x50 [ 26.580883] __fput+0x352/0xa70 [ 26.581095] fput_close_sync+0xd8/0x190 [ 26.581350] __x64_sys_close+0x79/0xd0 [ 26.581595] do_syscall_64+0x117/0x6b0 [ 26.581842] entry_SYSCALL_64_after_hwframe+0x77/0x7f [ 26.582176] [ 26.582286] Last potentially related work creation: [ 26.582593] kasan_save_stack+0x24/0x50 [ 26.582841] kasan_record_aux_stack+0x89/0xa0 [ 26.583210] insert_work+0x22/0x170 [ 26.583442] __queue_work+0x7b1/0xfa0 [ 26.583682] queue_work_on+0x77/0x80 [ 26.583921] kblockd_schedule_work+0x18/0x20 [ 26.584207] nvme_mpath_put_disk+0x42/0xa0 [ 26.584632] nvme_free_ns_head+0x1c/0x160 [ 26.584904] nvme_ns_head_chr_release+0x39/0x50 [ 26.585208] __fput+0x352/0xa70 [ 26.585420] fput_close_sync+0xd8/0x190 [ 26.585677] __x64_sys_close+0x79/0xd0 [ 26.585924] do_syscall_64+0x117/0x6b0 [ 26.586173] entry_SYSCALL_64_after_hwframe+0x77/0x7f [ 26.586505] [ 26.586616] Second to last potentially related work creation: [ 26.586991] kasan_save_stack+0x24/0x50 [ 26.587246] kasan_record_aux_stack+0x89/0xa0 [ 26.587538] insert_work+0x22/0x170 [ 26.587770] __queue_work+0x7b1/0xfa0 [ 26.588010] queue_work_on+0x77/0x80 [ 26.588247] kblockd_schedule_work+0x18/0x20 [ 26.588529] nvme_remove_head+0x3d/0xb0 [ 26.588787] nvme_ns_remove+0x4b2/0x930 [ 26.589040] nvme_remove_namespaces+0x29c/0x410 [ 26.589340] nvme_do_delete_ctrl+0xf3/0x190 [ 26.589611] nvme_delete_ctrl_sync+0x71/0x90 [ 26.589889] nvme_sysfs_delete+0x91/0xb0 [ 26.590151] kernfs_fop_write_iter+0x2fb/0x4a0 [ 26.590452] vfs_write+0x929/0xfc0 [ 26.590688] ksys_write+0xf2/0x1d0 [ 26.590923] do_syscall_64+0x117/0x6b0 [ 26.591171] entry_SYSCALL_64_after_hwframe+0x77/0x7f [ 26.591498] [ 26.591605] The buggy address belongs to the object at ffff88811e7fa000 [ 26.591605] which belongs to the cache kmalloc-4k of size 4096 [ 26.592409] The buggy address is located 368 bytes inside of [ 26.592409] freed 4096-byte region [ffff88811e7fa000, ffff88811e7fb000) [ 26.593205] [ 26.593321] The buggy address belongs to the physical page: [ 26.593701] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x11e7f8 [ 26.594250] head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0 [ 26.594743] flags: 0x200000000000040(head|node=0|zone=2) [ 26.595093] page_type: f5(slab) [ 26.595312] raw: 0200000000000040 ffff888100043040 dead000000000122 0000000000000000 [ 26.595810] raw: 0000000000000000 0000000000040004 00000000f5000000 0000000000000000 [ 26.596309] head: 0200000000000040 ffff888100043040 dead000000000122 0000000000000000 [ 26.596806] head: 0000000000000000 0000000000040004 00000000f5000000 0000000000000000 [ 26.597313] head: 0200000000000003 fffffffffffffe01 00000000ffffffff 00000000ffffffff [ 26.597813] head: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000 [ 26.598317] page dumped because: kasan: bad access detected [ 26.598676] [ 26.598784] Memory state around the buggy address: [ 26.599093] ffff88811e7fa000: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 26.599559] ffff88811e7fa080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 26.600023] >ffff88811e7fa100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 26.600485] ^ [ 26.600921] ffff88811e7fa180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 26.601390] ffff88811e7fa200: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 26.601855] ================================================================== [ 26.602374] Disabling lock debugging due to kernel taint
When all fds for the cdev disappear, the cdev removal path puts a reference to the parent object, which is the nvme_ns_head.cdev_device - see cdev_default_release() -> kobject_put(parent).
Fix the lifetime for the cdev by making adding the cdev add take a reference to the NS head and drop that reference in the nvme_ns_head.cdev_device release function.
The same problem exists for the NS cdev lifetime, so resolve that issue through a similar method by taking a reference to the NS for the lifetime of the cdev. Note that nvme_ns_chr_open() -> nvme_ns_open() also takes a reference to the NS. Now that should not be needed, but that code is common to bdev ioctl, so keep as is.
[0] https://lore.kernel.org/linux-scsi/[email protected]/T/#m67265e2906d617acd2743c0a00809246d0cfc506
Stable-dep-of: 6b8a5367e9e7 ("nvme: work around -Wformat-security warning")
--- drivers/nvme/host/core.c | 7 +++++++ drivers/nvme/host/multipath.c | 22 ++-------------------- 2 files changed, 9 insertions(+), 20 deletions(-)
drivers/nvme/host/core.c +7 -0
@@ -3900,6 +3900,11 @@ static int nvme_subsys_check_duplicate_istatic void nvme_cdev_rel (struct device *dev) {ida_free (&nvme_ns_chr_minor_ida,MINOR (dev->devt)); +if (dev->parent->class == &nvme_class) + nvme_put_ns(container_of(dev, struct nvme_ns, cdev_device)); +else + nvme_put_ns_head(container_of(dev, struct nvme_ns_head, + cdev_device)); }void nvme_cdev_del (struct cdev *cdev,struct device *cdev_device)
@@ -3965,10 +3970,12 @@ static void nvme_add_ns_cdev(struct nvmesnprintf (name,sizeof (name),"ng%dn%d" , ns->ctrl->instance, ns->head->instance); +nvme_get_ns (ns);/* Undone in nvme_cdev_rel() */ if (nvme_cdev_add (name, &ns->cdev, &ns->cdev_device, &nvme_ns_chr_fops, ns->ctrl->ops->module)) {dev_err (ns->ctrl->device,"Unable to create the %s device\n" , name); +nvme_put_ns (ns);return ; }set_bit (NVME_NS_CDEV_LIVE , &ns->flags);
drivers/nvme/host/multipath.c +2 -20
@@ -611,28 +611,8 @@ const struct block_device_operations nvm .pr_ops = &nvme_pr_ops, }; -static inline struct nvme_ns_head *cdev_to_ns_head (struct cdev *cdev) -{ - return container_of(cdev, struct nvme_ns_head, cdev); -} - -static int nvme_ns_head_chr_open (struct inode *inode,struct file *file) -{ -if (!nvme_tryget_ns_head (cdev_to_ns_head (inode->i_cdev))) -return -ENXIO ; -return 0 ; -} - -static int nvme_ns_head_chr_release (struct inode *inode,struct file *file) -{ -nvme_put_ns_head (cdev_to_ns_head (inode->i_cdev)); -return 0 ; -} -static const struct file_operations nvme_ns_head_chr_fops = { .owner =THIS_MODULE , - .open = nvme_ns_head_chr_open, - .release = nvme_ns_head_chr_release, .unlocked_ioctl = nvme_ns_head_chr_ioctl, .compat_ioctl = compat_ptr_ioctl, .uring_cmd = nvme_ns_head_chr_uring_cmd,
@@ -647,10 +627,12 @@ static void nvme_add_ns_head_cdev(structsnprintf (name,sizeof (name),"ng%dn%d" , head->subsys->instance, head->instance); +nvme_get_ns_head (head);/* Undone in nvme_cdev_rel() */ if (nvme_cdev_add (name, &head->cdev, &head->cdev_device, &nvme_ns_head_chr_fops,THIS_MODULE )) {dev_err (disk_to_dev (head->disk),"Unable to create the %s device\n" , name); +nvme_put_ns_head (head);return ; }set_bit (NVME_NSHEAD_CDEV_LIVE , &head->flags);
Greg Kroah-Hartman
maintainerPATCH 106/428 nvme: work around -Wformat-security warning
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnd Bergmann <[email protected]>
[ Upstream commit 6b8a5367e9e73a17561b8ce584ae77a43f712007 ]
Passing a string variable into dev_set_name() causes a warning when building with -Wformat-security enabled:
drivers/nvme/host/core.c: In function 'nvme_cdev_add':drivers/nvme/host/core.c:3911:9: error: format not a string literal and no format arguments [-Werror=format-security]
3911 | ret = dev_set_name(cdev_device, name);
Remove the temporary strings and let dev_set_name() do the same thing internally.
--- drivers/nvme/host/core.c | 21 +++++++++------------ drivers/nvme/host/multipath.c | 12 +++++------- drivers/nvme/host/nvme.h | 6 +++--- 3 files changed, 17 insertions(+), 22 deletions(-)
drivers/nvme/host/core.c +9 -12
@@ -3913,9 +3913,9 @@ void nvme_cdev_del(struct cdev *cdev, stput_device (cdev_device); } -int nvme_cdev_add (const char *name,struct cdev *cdev, -struct device *cdev_device, -const struct file_operations *fops,struct module *owner) +int nvme_cdev_add (struct cdev *cdev,struct device *cdev_device, +const struct file_operations *fops,struct module *owner, +int ctrl,int head) {int minor, ret;
@@ -3923,7 +3923,7 @@ int nvme_cdev_add(const char *name, struif (minor <0 )return minor; - ret =dev_set_name (cdev_device, name); + ret =dev_set_name (cdev_device,"ng%dn%d" , ctrl, head);if (ret) {ida_free (&nvme_ns_chr_minor_ida, minor);return ret;
@@ -3964,17 +3964,14 @@ static const struct file_operations nvmestatic void nvme_add_ns_cdev (struct nvme_ns *ns) { -char name[32 ]; - ns->cdev_device.parent = ns->ctrl->device; -snprintf (name,sizeof (name),"ng%dn%d" , ns->ctrl->instance, - ns->head->instance);nvme_get_ns (ns);/* Undone in nvme_cdev_rel() */ -if (nvme_cdev_add (name, &ns->cdev, &ns->cdev_device, - &nvme_ns_chr_fops, ns->ctrl->ops->module)) { -dev_err (ns->ctrl->device,"Unable to create the %s device\n" , - name); +if (nvme_cdev_add (&ns->cdev, &ns->cdev_device, + &nvme_ns_chr_fops, ns->ctrl->ops->module, + ns->ctrl->instance, ns->head->instance)) { +dev_err (ns->ctrl->device,"Unable to create the ng%dn%d device\n" , + ns->ctrl->instance, ns->head->instance);nvme_put_ns (ns);return ; }
drivers/nvme/host/multipath.c +5 -7
@@ -621,17 +621,15 @@ static const struct file_operations nvmestatic void nvme_add_ns_head_cdev (struct nvme_ns_head *head) { -char name[32 ]; - head->cdev_device.parent = &head->subsys->dev; -snprintf (name,sizeof (name),"ng%dn%d" , head->subsys->instance, - head->instance);nvme_get_ns_head (head);/* Undone in nvme_cdev_rel() */ -if (nvme_cdev_add (name, &head->cdev, &head->cdev_device, - &nvme_ns_head_chr_fops,THIS_MODULE )) { +if (nvme_cdev_add (&head->cdev, &head->cdev_device, + &nvme_ns_head_chr_fops,THIS_MODULE , + head->subsys->instance, head->instance)) {dev_err (disk_to_dev (head->disk), -"Unable to create the %s device\n" , name); +"Unable to create the ng%dn%d device\n" , + head->subsys->instance, head->instance);nvme_put_ns_head (head);return ; }
drivers/nvme/host/nvme.h +3 -3
@@ -1008,9 +1008,9 @@ int nvme_get_log(struct nvme_ctrl *ctrl,void nvme_get_ns_head (struct nvme_ns_head *head);bool nvme_tryget_ns_head (struct nvme_ns_head *head);void nvme_put_ns_head (struct nvme_ns_head *head); -int nvme_cdev_add (const char *name,struct cdev *cdev, -struct device *cdev_device, -const struct file_operations *fops,struct module *owner); +int nvme_cdev_add (struct cdev *cdev,struct device *cdev_device, +const struct file_operations *fops,struct module *owner, +int ctrl,int head);void nvme_cdev_del (struct cdev *cdev,struct device *cdev_device);int nvme_ioctl (struct block_device *bdev,blk_mode_t mode,unsigned int cmd,unsigned long arg);
Greg Kroah-Hartman
maintainerPATCH 107/428 nvme: fix command effects log lifetime for multipath heads
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yao Sang <[email protected]>
[ Upstream commit 72ece656abd4de8645a421fb482d7a11e6533a45 ]
KASAN reported a use-after-free when an I/O passthrough command was sent through a multipath namespace head after the controller path that first created the head had been removed:
BUG: KASAN: slab-use-after-free in nvme_command_effects+0x192/0x200 [nvme_core] Read of size 4 at addr ffff888141b14400 by task nvme/19811 nvme_command_effects+0x192/0x200 [nvme_core] nvme_cmd_allowed+0x7e/0x1b0 [nvme_core] nvme_user_cmd.constprop.0+0x1b5/0x450 [nvme_core] nvme_ns_head_chr_ioctl+0xf4/0x2a0 [nvme_core]
Move the log cache to the subsystem, with one entry per command set. Both controllers and namespace heads hold subsystem references, keeping their log pointers valid until subsystem release.
--- drivers/nvme/host/core.c | 41 +++++++++++++++++++---------------------- drivers/nvme/host/nvme.h | 3 ++- 2 files changed, 21 insertions(+), 23 deletions(-)
drivers/nvme/host/core.c +19 -22
@@ -3179,9 +3179,16 @@ static void nvme_release_subsystem(struc {struct nvme_subsystem *subsys = container_of(dev, struct nvme_subsystem, dev); +struct nvme_effects_log *cel; +unsigned long i;if (subsys->instance >=0 )ida_free (&nvme_instance_ida, subsys->instance); +xa_for_each (&subsys->cels, i, cel) { +xa_erase (&subsys->cels, i); +kfree (cel); + } +xa_destroy (&subsys->cels);kfree (subsys); }
@@ -3293,6 +3300,7 @@ static int nvme_init_subsystem(struct nvkref_init (&subsys->ref);INIT_LIST_HEAD (&subsys->ctrls);INIT_LIST_HEAD (&subsys->nsheads); +xa_init (&subsys->cels);nvme_init_subnqn (subsys, ctrl, id);memcpy (subsys->serial, id->sn,sizeof (subsys->serial));memcpy (subsys->model, id->mn,sizeof (subsys->model));
@@ -3395,7 +3403,7 @@ int nvme_get_log(struct nvme_ctrl *ctrl,static int nvme_get_effects_log (struct nvme_ctrl *ctrl,u8 csi,struct nvme_effects_log **log) { -struct nvme_effects_log *old, *cel =xa_load (&ctrl->cels, csi); +struct nvme_effects_log *old, *cel =xa_load (&ctrl->subsys->cels, csi);int ret;if (cel)
@@ -3412,7 +3420,7 @@ static int nvme_get_effects_log(struct nreturn ret; } - old =xa_store (&ctrl->cels, csi, cel,GFP_KERNEL ); + old =xa_store (&ctrl->subsys->cels, csi, cel,GFP_KERNEL );if (xa_is_err (old)) {kfree (cel);return xa_err (old);
@@ -3487,7 +3495,7 @@ static int nvme_init_effects_log(structif (!effects)return -ENOMEM ; - old =xa_store (&ctrl->cels, csi, effects,GFP_KERNEL ); + old =xa_store (&ctrl->subsys->cels, csi, effects,GFP_KERNEL );if (xa_is_err (old)) {kfree (effects);return xa_err (old);
@@ -3533,23 +3541,27 @@ static int nvme_init_effects(struct nvme {int ret =0 ; +mutex_lock (&ctrl->subsys->lock); + ctrl->effects =xa_load (&ctrl->subsys->cels,NVME_CSI_NVM );if (ctrl->effects) -return 0 ; + goto out_unlock;if (id->lpa &NVME_CTRL_LPA_CMD_EFFECTS_LOG ) { ret =nvme_get_effects_log (ctrl,NVME_CSI_NVM , &ctrl->effects);if (ret <0 ) -return ret; + goto out_unlock; }if (!ctrl->effects) { ret =nvme_init_effects_log (ctrl,NVME_CSI_NVM , &ctrl->effects);if (ret <0 ) -return ret; + goto out_unlock; }nvme_init_known_nvm_effects (ctrl); -return 0 ; +out_unlock: +mutex_unlock (&ctrl->subsys->lock); +return ret; }static int nvme_check_ctrl_fabric_info (struct nvme_ctrl *ctrl,struct nvme_id_ctrl *id)
@@ -5134,19 +5146,6 @@ void nvme_uninit_ctrl(struct nvme_ctrl * }EXPORT_SYMBOL_GPL (nvme_uninit_ctrl); -static void nvme_free_cels (struct nvme_ctrl *ctrl) -{ -struct nvme_effects_log *cel; -unsigned long i; - -xa_for_each (&ctrl->cels, i, cel) { -xa_erase (&ctrl->cels, i); -kfree (cel); - } - -xa_destroy (&ctrl->cels); -} -static void nvme_free_ctrl (struct device *dev) { struct nvme_ctrl *ctrl =
@@ -5159,7 +5158,6 @@ static void nvme_free_ctrl(struct deviceblk_put_queue (ctrl->fabrics_q);if (!subsys || ctrl->instance != subsys->instance)ida_free (&nvme_instance_ida, ctrl->instance); -nvme_free_cels (ctrl);nvme_mpath_uninit (ctrl);cleanup_srcu_struct (&ctrl->srcu);nvme_auth_stop (ctrl);
@@ -5205,7 +5203,6 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrmutex_init (&ctrl->scan_lock);INIT_LIST_HEAD (&ctrl->namespaces); -xa_init (&ctrl->cels); ctrl->dev = dev; ctrl->ops = ops; ctrl->quirks = quirks;
drivers/nvme/host/nvme.h +2 -1
@@ -413,7 +413,6 @@ struct nvme_ctrl {unsigned long quirks;struct nvme_id_power_state psd[32 ];struct nvme_effects_log *effects; -struct xarray cels;struct work_struct scan_work;struct work_struct async_event_work;struct delayed_work ka_work;
@@ -505,6 +504,8 @@ struct nvme_subsystem {struct list_head ctrls; struct list_head nsheads__guarded_by (&lock); +/* Command effects logs, indexed by CSI and protected by lock. */ +struct xarray cels;char subnqn[NVMF_NQN_SIZE ];char serial[20 ];char model[40 ];
Greg Kroah-Hartman
maintainerPATCH 108/428 bpf: Hold map BTF for the memory allocator destructor record
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kumar Kartikeya Dwivedi <[email protected]>
[ Upstream commit ab39974240a0cff765f3bb9cce81d8001ffdb144 ]
bpf_ma_set_dtor() duplicates map->record so that the bpf_mem_alloc destructor can release the special fields of hash and rhash map elements once the allocator frees them for good. btf_record_dup() only acquires references on kernel and module BTF. Fields whose types live in the map BTF keep pointing into it: a kptr to a local type refers to map->btf, and a list_head or rb_root field carries a value_rec owned by the struct meta table of map->btf.
That borrowed state can outlive the map. When RCU callbacks are still in flight, bpf_mem_alloc_destroy() copies the allocator and defers the final drain, together with the destructor context, to a workqueue. bpf_map_free() then frees map->record and drops the map's BTF reference as soon as map_free() returns. Once the program that loaded the BTF is gone as well, the BTF is freed while the worker still uses the duplicate. The worker dereferences it through btf_is_kernel() and btf_find_struct_meta() in bpf_obj_free_fields() when destroying elements that were freed under RCU, and through btf_is_kernel() in btf_record_free() when releasing the context itself:
BUG: KASAN: slab-use-after-free in btf_is_kernel+0x19/0x30 Read of size 1 at addr ffff88811505dce8 by task kworker/u16:2/50 Workqueue: events_unbound free_mem_alloc_deferred Call Trace: btf_is_kernel+0x19/0x30 btf_record_free+0xc7/0xf0 htab_dtor_ctx_free+0x1a/0x30 free_mem_alloc_no_barrier+0x39/0x230 free_mem_alloc_deferred+0x2a/0x40 process_scheduled_works+0x5ce/0x9d0 worker_thread+0x42a/0x5e0 kthread+0x1f5/0x230 ret_from_fork+0x1dd/0x390 ret_from_fork_asm+0x1a/0x30 Allocated by task 358: __kmalloc_cache_noprof+0x287/0x510 btf_new_fd+0xf7/0x3d0 __sys_bpf+0x487/0x840 Freed by task 0: kfree+0x186/0x560 rcu_core+0x6f6/0xd40
Freeing a map that still holds more elements than the allocator's high watermark is enough to get there, because the bulk free during teardown queues the RCU callback that makes bpf_mem_alloc_destroy() defer. Non-preallocated hash maps and resizable hash maps both register the destructor and are affected alike.
Keep one reference on the map BTF in the destructor context. Every non-kernel pointer in the duplicated record is either map->btf or memory owned by it, so a single reference covers kptrs, list heads, and rb roots, and mirrors what bpf_map_meta_alloc() does for the duplicated record of an inner map. Release it only after the duplicated record has been freed: the worker is preemptible and not in an RCU read-side critical section, so dropping the last reference first would let the BTF be freed while btf_record_free() still reads its fields.
--- kernel/bpf/hashtab.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-)
kernel/bpf/hashtab.c +16 -1
@@ -128,6 +128,7 @@ struct htab_elem {struct htab_btf_record {struct btf_record *record; +struct btf *btf;u32 key_size; };
@@ -497,8 +498,13 @@ static void htab_dtor_ctx_free(void *ctx) {struct htab_btf_record *hrec = ctx; +/* +* The duplicated record still points into the map BTF, so free it +* before dropping the reference that keeps that BTF alive. +*/ btf_record_free (hrec->record); -kfree (ctx); +btf_put (hrec->btf); +kfree (hrec); } static int bpf_ma_set_dtor(struct bpf_map *map, struct bpf_mem_alloc *ma,
@@ -521,6 +527,15 @@ static int bpf_ma_set_dtor(struct bpf_map *map, struct bpf_mem_alloc *ma,kfree (hrec);return err; } +/* +* btf_record_dup() only acquires kernel and module BTF. Fields whose +* types live in the map BTF keep pointing into it: kptrs to local +* types refer to map->btf, and graph roots carry a value record owned +* by its struct meta table. The context can outlive the map when the +* allocator defers its teardown, so hold a reference of our own. +*/ + hrec->btf = map->btf; +btf_get (hrec->btf);bpf_mem_alloc_set_dtor (ma, dtor, htab_dtor_ctx_free, hrec);return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 109/428 net/mctp: publish the mctp_dev only after it is initialised
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Binbin Deng <[email protected]>
[ Upstream commit aadf655e8ea9a8ffa24bb8d69f504572e8d18181 ]
mctp_add_dev() links the new mctp_dev into dev->mctp_ptr before mdev->dev is assigned, so a reader that picks the device up in that window dereferences a net_device pointer that is still NULL:
KASAN: null-ptr-deref in range [0x00000000000000b0-0x00000000000000b7] Call Trace: <TASK> ? __pfx_mctp_sendmsg (./include/linux/sockptr.h:49) ? __pfx_mctp_dst_output (net/mctp/route.c:41) ? selinux_socket_sendmsg (security/selinux/hooks.c:5278) ____sys_sendmsg (net/socket.c:775 (discriminator 1) net/socket.c:790 (discriminator 1) net/socket.c:2684 (discriminator 1)) ? __pfx_____sys_sendmsg (net/socket.c:1131) ? __pfx_copy_msghdr_from_user (net/socket.c:2590) ? update_cfs_rq_load_avg (kernel/sched/fair.c:5478) ___sys_sendmsg (net/socket.c:2738) ? __pfx____sys_sendmsg (net/socket.c:2625) ? perf_event_task_tick (./include/linux/rcupdate.h:838) ? sched_tick (kernel/sched/core.c:5818) ? clockevents_program_event (kernel/time/clockevents.c:372) ? fdget (./include/linux/rcupdate.h:873 fs/file.c:1100) __sys_sendmsg (net/socket.c:2770) ? __pfx___sys_sendmsg (net/socket.c:2751) do_syscall_64 (arch/x86/entry/syscall_64.c:63) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) </TASK>
Fix by publishing only once the object is fully initialised:__mctp_dev_get() runs under rcu_read_lock() only and hands this object to readers as soon as mctp_ptr is assigned, so they must never observe mdev->dev == NULL.
--- net/mctp/device.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
net/mctp/device.c +3 -3
@@ -344,13 +344,13 @@ static struct mctp_dev *mctp_add_dev(struct net_device *dev) mdev->net =mctp_default_net (dev_net (dev)); -/* associate to net_device */ refcount_set (&mdev->refs,1 ); -rcu_assign_pointer (dev->mctp_ptr, mdev); -dev_hold (dev); mdev->dev = dev; +/* Associate to net_device, publish the mdev. */ +rcu_assign_pointer (dev->mctp_ptr, mdev); +return mdev; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 110/428 net/sched: cls_api: reclaim an empty proto on the error path
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jamal Hadi Salim <[email protected]>
[ Upstream commit 0bb8eab29b55045281a4963d4557f2776cdf8cfa ]
Two racing tc filter add requests on the same chain/prio of an unlocked classifier both run change() on the shared proto and both can fail: the winner's tcf_chain_tp_delete_empty() attempt gives up because the loser's handle is still in the idr, and the loser's error path drops only its own reference without a second reclamation attempt. The empty proto stays linked in the chain, holding the chain reference, a block reference and the classifier module reference until the chain or block is torn down.
Reclaim the proto on the error path of any failed request that holds a proto reference. The reclamation is emptiness-gated:tcf_chain_tp_delete_empty() unlinks the proto only when delete_empty() admits it is empty, so a live shared proto is never unlinked. A proto the request created is reclaimed unconditionally - it is the only owner, so marking it for deletion is safe even without a delete_empty callback. Classifiers without one (the check marks the proto unconditionally) are rtnl-serialized, so the raced window this guard closes cannot arise for them.
This is a follow-up to commit d4e359b3608a ("net/sched: cls_api: fix teardown of an adopted proto on insert-race loss"), which stopped the loser of the insert race from unlinking the winner's live proto but left the empty-proto residual in place.
Conditions to recreate:
- CONFIG_NET_CLS_FLOWER=y; veth pair
- tc qdisc add dev veth0 ingress
- two concurrent tc filter add dev veth0 ingress protocol ip pref 1 flower skip_sw ... action drop (both fail in fl_hw_replace_filter after publishing their handle in the idr); repeat in a loop
- an empty flower tp stays linked after both requests fail; visible as a bare filter protocol ip pref 1 flower chain 0 header in tc filter show with no filter entries
- CAP_NET_ADMIN (namespace-local via unshare -Urn suffices)
--- net/sched/cls_api.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
net/sched/cls_api.c +14 -1
@@ -2463,7 +2463,20 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n, } errout: -if (err && tp_state ==TP_CREATED ) +if (err && !IS_ERR_OR_NULL (tp) && + (tp_state ==TP_CREATED || tp->ops->delete_empty)) +/* +* The request is dropping its reference to tp. If it was +* the last user (the idr is empty now), reclaim the proto. +* A tp this request created is reclaimed unconditionally: +* it is the only owner, so marking it for deletion is +* safe. Otherwise only classifiers with a delete_empty +* callback are reclaimed -- the callback admits an empty +* proto only, so a live shared proto is never unlinked. +* Classifiers without one (deleting is set +* unconditionally) are rtnl-serialized, so the raced +* window this guard closes cannot arise for them. +*/ tcf_chain_tp_delete_empty (chain, tp, rtnl_held,NULL ); errout_tp:if (chain) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 111/428 net: bcmgenet: allocate RX buffers as page fragments
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolai Buchwitz <[email protected]>
[ Upstream commit 0e7fe2b0ca45343b53345edc174898b448ccdaa4 ]
Since the page_pool conversion every RX buffer is a whole page and the skb truesize is the page, although the hardware writes at most 2 KiB of it. On 64 KiB pages a packet therefore counts 65792 bytes against the socket buffer where it used to count 2752. As a result a UDP socket with the default buffer starts to drop after three packets, and the RX rings pin 16 MiB for 512 KiB of buffers.
Fix this and allocate the buffers as page fragments, so the truesize is what a packet occupies. 4 KiB pages stay one buffer per page.
Sync each buffer in the refill path, as page_pool can only sync a whole page on recycle. On 4 KiB pages that is twice what the hardware wrote.
--- .../net/ethernet/broadcom/genet/bcmgenet.c | 29 ++++++++++++++----- .../net/ethernet/broadcom/genet/bcmgenet.h | 2 ++ 2 files changed, 23 insertions(+), 8 deletions(-)
drivers/net/ethernet/broadcom/genet/bcmgenet.c +21 -8
@@ -57,6 +57,9 @@*/ #define GENET_RSB_PAD (sizeof(struct status_64) + 2) +/* RX buffer plus the skb_shared_info napi_build_skb() places behind it */ +#define GENET_RX_BUF_SIZE SKB_HEAD_ALIGN(RX_BUF_LENGTH) +/* Tx/Rx DMA register offset, skip 256 descriptors */ #define WORDS_PER_BD (p) (p->hw_params->words_per_bd)#define DMA_DESC_SIZE (WORDS_PER_BD(priv) * sizeof(u32))
@@ -2254,11 +2257,12 @@ static int bcmgenet_rx_refill(struct bcmgenet_rx_ring *ring, struct enet_cb *cb) {struct bcmgenet_priv *priv = ring->priv; +unsigned int size =GENET_RX_BUF_SIZE ; +unsigned int offset;dma_addr_t mapping;struct page *page; - page =page_pool_alloc_pages (ring->page_pool, -GFP_ATOMIC ); + page =page_pool_dev_alloc (ring->page_pool, &offset, &size);if (!page) { priv->mib.alloc_rx_buff_failed++; netif_err(priv, rx_err, priv->dev,
@@ -2267,9 +2271,13 @@ static int bcmgenet_rx_refill(struct bcmgenet_rx_ring *ring, }/* page_pool handles DMA mapping via PP_FLAG_DMA_MAP */ - mapping =page_pool_get_dma_addr (page); + mapping =page_pool_get_dma_addr (page) + offset; +dma_sync_single_for_device (&priv->pdev->dev, mapping,RX_BUF_LENGTH , +DMA_FROM_DEVICE ); cb->rx_page = page; + cb->rx_offset = offset; + cb->rx_size = size;dmadesc_set_addr (priv, cb->bd_addr, mapping);return 0 ;
@@ -2323,6 +2331,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,while ((rxpktprocessed < rxpkttoprocess) && (rxpktprocessed < budget)) { +unsigned int rx_offset, rx_size;struct status_64 *status;struct page *rx_page;void *hard_start;
@@ -2332,6 +2341,8 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,/* Save the received page before refilling */ rx_page = cb->rx_page; + rx_offset = cb->rx_offset; + rx_size = cb->rx_size;if (bcmgenet_rx_refill (ring, cb)) {BCMGENET_STATS64_INC (stats, dropped);
@@ -2341,10 +2352,10 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,/* Sync the full buffer; the HW may have written anywhere * up to RX_BUF_LENGTH. */ -page_pool_dma_sync_for_cpu (ring->page_pool, rx_page,0 , +page_pool_dma_sync_for_cpu (ring->page_pool, rx_page, rx_offset,RX_BUF_LENGTH ); - hard_start =page_address (rx_page); + hard_start =page_address (rx_page) + rx_offset; status = (struct status_64 *)hard_start; dma_length_status = status->length_status;
@@ -2410,7 +2421,7 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_rx_ring *ring,/* Build SKB from the page - data starts at hard_start, * frame begins after RSB(64) + pad(2) = 66 bytes. */ - skb =napi_build_skb (hard_start,PAGE_SIZE ); + skb =napi_build_skb (hard_start, rx_size);if (unlikely (!skb)) {BCMGENET_STATS64_INC (stats, dropped); page_pool_put_full_page(ring->page_pool, rx_page,
@@ -2762,14 +2773,16 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv,static int bcmgenet_rx_ring_create_pool (struct bcmgenet_priv *priv,struct bcmgenet_rx_ring *ring) { +/* Buffers share a page. bcmgenet_rx_refill() syncs each one for the +* device, PP_FLAG_DMA_SYNC_DEV would sync the whole page. +*/ struct page_pool_params pp_params = { .order =0 , - .flags =PP_FLAG_DMA_MAP |PP_FLAG_DMA_SYNC_DEV , + .flags =PP_FLAG_DMA_MAP , .pool_size = ring->size, .nid =NUMA_NO_NODE , .dev = &priv->pdev->dev, .dma_dir =DMA_FROM_DEVICE , - .max_len =RX_BUF_LENGTH , };int err;
drivers/net/ethernet/broadcom/genet/bcmgenet.h +2 -0
@@ -470,6 +470,8 @@ struct bcmgenet_rx_stats64 {struct enet_cb {struct sk_buff *skb;struct page *rx_page; +unsigned int rx_offset; +unsigned int rx_size;void __iomem *bd_addr;DEFINE_DMA_UNMAP_ADDR (dma_addr);DEFINE_DMA_UNMAP_LEN (dma_len);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 112/428 ipv6: fix prefix route expiry in modify_prefix_route()
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qishuai Liu <[email protected]>
[ Upstream commit a7bfaba4823e3c165bb2004c74eff7c096672bc7 ]
modify_prefix_route() is given the lifetime in clock_t relative to now, but fib6_set_expires() wants an absolute jiffies value. So when a permanent address is changed to a finite valid_lft, the prefix route ends up already expired and GC removes it.
Steps to reproduce:
ip link add dummy9 type dummy
ip link set dummy9 up
ip -6 addr add 2001:db8:9::1/64 dev dummy9
ip -6 addr change 2001:db8:9::1/64 dev dummy9 valid_lft 3600 preferred_lft 3600
ip -6 route show dev dummy9 # expires is negative
--- net/ipv6/addrconf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv6/addrconf.c +1 -1
@@ -4873,7 +4873,7 @@ static int modify_prefix_route(struct net *net, struct inet6_ifaddr *ifp,fib6_clean_expires (f6i);fib6_may_remove_gc_list (net, f6i); }else { -fib6_set_expires (f6i, expires); +fib6_set_expires (f6i, jiffies +clock_t_to_jiffies (expires));fib6_add_gc_list (f6i); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 113/428 netfilter: ipset: do not update comments from kernel-side adds
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit a442c8a89fb9c531f9d6ab86120c31decd778d51 ]
'Fixes' commit stopped calling ip_set_init_comment() for hash types from kernel-side-adds (xtables .. -j SET). ip_set_init_comment() says:
"The kadt functions don't use the comment extensions in any way."
But bitmap set type calls the function from kadt cb too.
While this appears to be safe (serialized via the set spinlock), it seems better to not call the init function either, least of all to keep behaviour consistent.
ip_set_list calls ip_set_init_comment() only from uadt cb, it can be kept as-is.
This was triggered by yet another LLM review, hinting that the existing rcu_dereference_protected() cannot be downgraded to only check if the nfnl mutex is held.
--- net/netfilter/ipset/ip_set_bitmap_gen.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/netfilter/ipset/ip_set_bitmap_gen.h +1 -1
@@ -159,7 +159,7 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,if (SET_WITH_COUNTER (set))ip_set_init_counter (ext_counter (x, set), ext); -if (SET_WITH_COMMENT (set)) +if (SET_WITH_COMMENT (set) && !ext->target)ip_set_init_comment (set,ext_comment (x, set), ext);if (SET_WITH_SKBINFO (set))ip_set_init_skbinfo (ext_skbinfo (x, set), ext);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 114/428 wifi: mac80211: fix slab-out-of-bounds read in ieee80211_monitor_select_queue()
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cen Zhang (Microsoft) <[email protected]>
[ Upstream commit 6f63e919fe1e335b8abcb3a28bfd4804a98d875a ]
ieee80211_monitor_select_queue() validates the skb length using skb->len before dereferencing pointers into skb->data to access the 802.11 header. However, skb->len includes data in both the linear head buffer and non-linear fragments/pages. When AF_PACKET sends a packet large enough to become non-linear, the 802.11 header at skb->data + len_rthdr may extend past the linear head buffer even though skb->len appears sufficient.
This leads to a slab-out-of-bounds read when accessing hdr->frame_control, as the kernel reads beyond the allocated skb head buffer:
BUG: KASAN: slab-out-of-bounds in ieee80211_monitor_select_queue+0x1ed/0x220
syzbot has hit the same issues.
Fix this by checking skb_headlen(skb) (which gives the length of the linear data region) instead of skb->len before dereferencing skb->data pointers. This ensures the required bytes are actually present in the linear portion of the skb.
Apply the same fix to ieee80211_validate_radiotap_len() which has the same class of bug: it uses skb->len to validate accesses to skb->data, and to the corresponding checks in ieee80211_monitor_start_xmit(): for drivers advertising NETIF_F_SG the skb is not linearized before ndo_start_xmit, so the 802.11 header can be read past the linear buffer there as well.
--- net/mac80211/iface.c | 4 ++-- net/mac80211/tx.c | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-)
net/mac80211/iface.c +2 -2
@@ -998,8 +998,8 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev, len_rthdr =ieee80211_get_radiotap_len (skb->data); hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr); -if (skb->len < len_rthdr +2 || - skb->len < len_rthdr +ieee80211_hdrlen (hdr->frame_control)) +if (skb_headlen (skb) < len_rthdr +2 || +skb_headlen (skb) < len_rthdr +ieee80211_hdrlen (hdr->frame_control))return 0 ;/* doesn't matter, frame will be dropped */ return ieee80211_select_queue_80211 (sdata, skb, hdr);
net/mac80211/tx.c +5 -5
@@ -2082,7 +2082,7 @@ static bool ieee80211_validate_radiotap_len(struct sk_buff *skb) (struct ieee80211_radiotap_header *)skb->data;/* check for not even having the fixed radiotap header part */ -if (unlikely (skb->len <sizeof (struct ieee80211_radiotap_header ))) +if (unlikely (skb_headlen (skb) <sizeof (struct ieee80211_radiotap_header )))return false;/* too short to be possibly valid */ /* is it a header version we can trust to find length from? */
@@ -2090,7 +2090,7 @@ static bool ieee80211_validate_radiotap_len(struct sk_buff *skb)return false;/* only version 0 is supported */ /* does the skb contain enough to deliver on the alleged length? */ -if (unlikely (skb->len <ieee80211_get_radiotap_len (skb->data))) +if (unlikely (skb_headlen (skb) <ieee80211_get_radiotap_len (skb->data)))return false;/* skb too short for claimed rt header extent */ return true;
@@ -2379,13 +2379,13 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,skb_set_network_header (skb, len_rthdr);skb_set_transport_header (skb, len_rthdr); -if (skb->len < len_rthdr +2 ) +if (skb_headlen (skb) < len_rthdr +2 ) goto fail; hdr = (struct ieee80211_hdr *)(skb->data + len_rthdr); hdrlen =ieee80211_hdrlen (hdr->frame_control); -if (skb->len < len_rthdr + hdrlen) +if (skb_headlen (skb) < len_rthdr + hdrlen) goto fail;/*
@@ -2393,7 +2393,7 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,* carrying a rfc1042 header */ if (ieee80211_is_data (hdr->frame_control) && - skb->len >= len_rthdr + hdrlen +sizeof (rfc1042_header) +2 ) { +skb_headlen (skb) >= len_rthdr + hdrlen +sizeof (rfc1042_header) +2 ) {u8 *payload = (u8 *)hdr + hdrlen;if (ether_addr_equal (payload, rfc1042_header))
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 115/428 ALSA: hda/realtek - Add headset mode for Dell Pro QC1255
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kailang Yang <[email protected]>
[ Upstream commit 608c0c8947f03069b651ace54538a115f5b23123 ]
It lost its headset microphone functionality, and this patch will restore it.
--- sound/hda/codecs/realtek/alc269.c | 2 ++ 1 file changed, 2 insertions(+)
sound/hda/codecs/realtek/alc269.c +2 -0
@@ -6891,6 +6891,8 @@ static const struct hda_fixup alc269_fixups[] = { [ALC236_FIXUP_DELL_HP_POP_NOISE] = { .type = HDA_FIXUP_FUNC, .v.func = alc285_fixup_invalidate_dacs, + .chained = true, + .chain_id =ALC255_FIXUP_DELL1_MIC_NO_PRESENCE }, [ALC274_FIXUP_HP_89E9_GPIO] = { .type = HDA_FIXUP_FUNC,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 116/428 drm/xe/pf: Refactor VF LMEM BAR resize helper function
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michal Wajdeczko <[email protected]>
[ Upstream commit 74dae5f33c0c64d3ca12710bfd845721d73fe2e5 ]
Improve and move diagnostics messages to the helper function to keep the caller function tidy.
Stable-dep-of: 72207463f7a4 ("drm/xe/pf: Keep VF LMEM BAR size low if no VFs enabled")
--- drivers/gpu/drm/xe/xe_pci_sriov.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-)
drivers/gpu/drm/xe/xe_pci_sriov.c +20 -7
@@ -82,16 +82,33 @@ static void pf_engine_activity_stats(struct xe_device *xe, unsigned int num_vfs, } } -static int resize_vf_vram_bar (struct xe_device *xe,int num_vfs) +static int pf_resize_vf_vram_bar (struct xe_device *xe,int num_vfs) {struct pci_dev *pdev =to_pci_dev (xe->drm.dev); +char buf[10 ];u32 sizes; +int size; +int err; + +if (!IS_DGFX (xe)) +return 0 ; sizes =pci_iov_vf_bar_get_sizes (pdev,VF_LMEM_BAR , num_vfs);if (!sizes)return 0 ; -return pci_iov_vf_bar_set_size (pdev,VF_LMEM_BAR ,__fls (sizes)); + size =__fls (sizes); +string_get_size (pci_rebar_size_to_bytes (size),1 ,STRING_UNITS_2 , buf,sizeof (buf)); + + err =pci_iov_vf_bar_set_size (pdev,VF_LMEM_BAR , size); +if (err) { +xe_sriov_notice (xe,"Failed to resize VF BAR %u to %s (%pe)\n" , +VF_LMEM_BAR , buf,ERR_PTR (err)); +return err; + } + +xe_sriov_dbg (xe,"VF LMEM BAR resized to %s\n" , buf); +return 0 ; }static int pf_prepare_vfs_enabling (struct xe_device *xe)
@@ -142,11 +159,7 @@ static int pf_enable_vfs(struct xe_device *xe, int num_vfs)if (err <0 ) goto failed; -if (IS_DGFX (xe)) { - err =resize_vf_vram_bar (xe, num_vfs); -if (err) -xe_sriov_info (xe,"Failed to set VF LMEM BAR size: %d\n" , err); - } +pf_resize_vf_vram_bar (xe, num_vfs); err =pci_enable_sriov (pdev, num_vfs);if (err <0 )
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 117/428 drm/xe/pf: Keep VF LMEM BAR size low if no VFs enabled
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marcin Bernatowicz <[email protected]>
[ Upstream commit 72207463f7a4a6818a88f4ef57802b42da534301 ]
When VFs are enabled on dGFX the driver resizes the PF VF_LMEM_BAR to fit the requested layout. After VFs are disabled the PF VF BAR size is left as-is. On platforms with tight MMIO apertures a subsequent unplug/rescan followed by another enable may fail with:
"VF BAR …: can't assign; no space"
because the PCI core reserves address space based on the (now large) VF template, often multiplied by totalvfs.
--- drivers/gpu/drm/xe/xe_pci_sriov.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/gpu/drm/xe/xe_pci_sriov.c +3 -0
@@ -177,6 +177,7 @@ static int pf_enable_vfs(struct xe_device *xe, int num_vfs)return num_vfs; failed: +pf_resize_vf_vram_bar (xe, xe->sriov.pf.device_total_vfs);xe_sriov_pf_unprovision_vfs (xe, num_vfs);xe_pm_runtime_put (xe);pf_finish_vfs_enabling (xe);
@@ -204,6 +205,8 @@ static int pf_disable_vfs(struct xe_device *xe)pci_disable_sriov (pdev); +pf_resize_vf_vram_bar (xe, xe->sriov.pf.device_total_vfs); +xe_sriov_pf_reprovision_default (xe);pf_reset_vfs (xe, num_vfs);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 118/428 Bluetooth: hci_sync: dont drain cmd_sync backlog on unregister
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nguyen Ngoc Thang <[email protected]>
[ Upstream commit b1f24c1ab52345e810c42a1a81286cb5a7c92252 ]
hci_unregister_dev() disables cmd_work and cmd_timer, then calls hci_cmd_sync_clear(), whose cancel_work_sync() waits for hci_cmd_sync_work() to return. That worker dequeues and runs every entry on cmd_sync_work_list. With cmd_work disabled nothing reaches the controller, so each queued HCI command waits the full HCI_CMD_TIMEOUT (2s).
The backlog has no bound. Userspace can keep queuing MGMT commands such as MGMT_OP_GET_CLOCK_INFO against a controller that doesn't answer. Closing /dev/vhci then blocks in vhci_release() for backlog * 2s:
INFO: task syz-executor:5749 blocked for more than 143 seconds. cancel_work_sync hci_cmd_sync_clear hci_unregister_dev vhci_release
In a local reproduction the backlog held more than 5000 entries, which comes to hours of hang.
Stop the worker from taking new entries once HCI_UNREGISTER is set, and wake any request still waiting with -ENODEV before cancelling the work. The entries left over are destroyed with -ECANCELED by the existing sweep in hci_cmd_sync_clear(). They stay on the list until the work has stopped, so hci_cmd_sync_dequeue() and friends still see them. A callback already running may still issue another command, which delays unregister by at most one timeout per remaining command, not by the whole backlog.
--- net/bluetooth/hci_sync.c | 6 ++++++ 1 file changed, 6 insertions(+)
net/bluetooth/hci_sync.c +6 -0
@@ -312,6 +312,10 @@ static void hci_cmd_sync_work(struct work_struct *work)while (1 ) {struct hci_cmd_sync_work_entry *entry; +/* Leave the backlog to hci_cmd_sync_clear() */ +if (hci_dev_test_flag (hdev,HCI_UNREGISTER )) +break ; +mutex_lock (&hdev->cmd_sync_work_lock); entry = list_first_entry_or_null(&hdev->cmd_sync_work_list, struct hci_cmd_sync_work_entry,
@@ -658,6 +662,8 @@ void hci_cmd_sync_clear(struct hci_dev *hdev) {struct hci_cmd_sync_work_entry *entry, *tmp; +/* cmd_work is disabled, the pending request can only time out */ +hci_cmd_sync_cancel_sync (hdev,ENODEV );cancel_work_sync (&hdev->cmd_sync_work);cancel_work_sync (&hdev->reenable_adv_work);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 119/428 drm/mediatek: mtk_hdmi_v2: fix VID_DOWNSAMPLE_CONFIG register offset
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Julien Stephan <[email protected]>
[ Upstream commit 3e292c56bf5e338efcda7f9bfa603180855cd1be ]
According to the datasheet, VID_DOWNSAMPLE_CONFIG is at offset 0x8f0; 0x8d0 is the VID_CSC_COEFF_0 register.
--- drivers/gpu/drm/mediatek/mtk_hdmi_regs_v2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/mediatek/mtk_hdmi_regs_v2.h +1 -1
@@ -173,7 +173,7 @@#define TPI_AUDIO_LOOKUP_EN BIT(2)/* Video downsampling configuration */ -#define VID_DOWNSAMPLE_CONFIG 0x8d0 +#define VID_DOWNSAMPLE_CONFIG 0x8f0#define C444_C422_CONFIG_ENABLE BIT(0)#define C422_C420_CONFIG_ENABLE BIT(4)#define C422_C420_CONFIG_BYPASS BIT(5)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 120/428 net: systemport: Fix buffer overflow in bcm_sysport_get_stats()
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Fainelli <[email protected]>
[ Upstream commit eb7b84af0ec5c71b4920e999611b466b3784496c ]
When running on SYSTEMPORT Lite, certain statistics are unsupported and skipped during bcm_sysport_get_stats(). The variable 'j' tracks the compacted index into the destination data buffer, whereas 'i' iterates over all elements in bcm_sysport_gstrings_stats.
Because the buffer allocated by ethtool is sized only according to bcm_sysport_get_sset_count(), storing values at data[i] instead of data[j] writes past the allocated array bounds, leading to memory corruption.
Fix this by writing to data[j] instead of data[i].
--- drivers/net/ethernet/broadcom/bcmsysport.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/ethernet/broadcom/bcmsysport.c +2 -2
@@ -482,10 +482,10 @@ static void bcm_sysport_get_stats(struct net_device *dev, s->type == BCM_SYSPORT_STAT_NETDEV64) {do { start =u64_stats_fetch_begin (syncp); - data[i] = *(u64 *)p; + data[j] = *(u64 *)p; }while (u64_stats_fetch_retry (syncp, start)); } else - data[i] = *(u32 *)p; + data[j] = *(u32 *)p; j++; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 121/428 net: systemport: Fix RUNT MIB counter register offset calculation
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Fainelli <[email protected]>
[ Upstream commit 242935adfeb096f09b29fb2cfcf12f9eb2911fc6 ]
In UniMAC hardware, there is a 0xC byte gap between the RX MIB counters and the TX MIB counters, and a second 0xC byte gap between the TX MIB counters and the RX RUNT MIB counters.
In bcm_sysport_update_mib_counters(), 'offset' was only set to UMAC_MIB_STAT_OFFSET (0xC) for all non-RX counters, omitting the second 0xC gap for BCM_SYSPORT_STAT_RUNT counters. As a result, all 4 RUNT MIB counters were read from unmapped gap register space.
Fix this by setting offset to 2 * UMAC_MIB_STAT_OFFSET (0x18) when reading BCM_SYSPORT_STAT_RUNT counters.
--- drivers/net/ethernet/broadcom/bcmsysport.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/net/ethernet/broadcom/bcmsysport.c +3 -1
@@ -391,8 +391,10 @@ static void bcm_sysport_update_mib_counters(struct bcm_sysport_priv *priv)if (priv->is_lite)continue ; -if (s->type !=BCM_SYSPORT_STAT_MIB_RX ) +if (s->type ==BCM_SYSPORT_STAT_MIB_TX ) offset =UMAC_MIB_STAT_OFFSET ; +else if (s->type ==BCM_SYSPORT_STAT_RUNT ) + offset =2 *UMAC_MIB_STAT_OFFSET ; val =umac_readl (priv,UMAC_MIB_START + j + offset);break ;case BCM_SYSPORT_STAT_RXCHK :
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 122/428 net/mlx5: Fix slab-out-of-bounds when handling team device events
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Anirudh Virdi <[email protected]>
[ Upstream commit 04c824940d52871c49866a4ac67b504146f7cf35 ]
The mlx5_handle_changeupper_event() and mlx5_handle_changeinfodata_event() functions check for LAG masters (which includes both bonding and team devices) but only call bonding-specific APIs. When processing team device events, calling bond_slave_get_rcu() and bond_is_slave_inactive() on team_port structures causes KASAN to detect an out-of-bounds memory access since team_port is smaller than bond slave.
Fix this by wrapping the bond-specific API calls with a check for bonding devices. This allows the function to still process LAG events for both bonding and teams but only calls bond-specific functions when dealing with actual bonding devices.
For mlx5_handle_changeinfodata_event(), keep the explicit bond check as mlx5 doesn't handle state information for team ports anyway.
Tested with Mellanox ConnectX-5 on Linux 7.2.0-rc6:
- Bonding: PASS (no regressions)
- Team device: PASS (no KASAN errors)
--- drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +6 -4
@@ -1943,9 +1943,11 @@ static int mlx5_handle_changeupper_event(struct mlx5_lag *ldev, } }if (i <MLX5_MAX_PORTS ) { - slave =bond_slave_get_rcu (ndev_tmp); -if (slave) - has_inactive |=bond_is_slave_inactive (slave); +if (netif_is_bond_master (upper)) { + slave =bond_slave_get_rcu (ndev_tmp); +if (slave) + has_inactive |=bond_is_slave_inactive (slave); + } bond_status |= (1 << idx); }
@@ -2029,7 +2031,7 @@ static int mlx5_handle_changeinfodata_event(struct mlx5_lag *ldev,bool has_inactive =0 ;int idx; -if (!netif_is_lag_master (ndev)) +if (!netif_is_bond_master (ndev))return 0 ;rcu_read_lock ();
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 123/428 octeontx2-pf: Fix aura BPID assignment when CONFIG_DCB is enabled
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Geetha sowjanya <[email protected]>
[ Upstream commit 056994563935e049093f100efaad7e63ad113814 ]
Previously, BPID assignment under CONFIG_DCB assumed queue_to_pfc_map was always initialized. For SDP VFs this leads to invalid memory access as it was not initialized.
This patch adds a NULL check for queue_to_pfc_map before dereferencing it. Also, simplifies the logic by always assigning a default BPID first, then conditionally overriding it if CONFIG_DCB is enabled and the map exists.
--- .../net/ethernet/marvell/octeontx2/nic/cn20k.c | 11 +---------- .../ethernet/marvell/octeontx2/nic/otx2_common.c | 16 ++++++---------- .../ethernet/marvell/octeontx2/nic/otx2_common.h | 9 +++++++++ 3 files changed, 16 insertions(+), 20 deletions(-)
drivers/net/ethernet/marvell/octeontx2/nic/cn20k.c +1 -10
@@ -242,15 +242,6 @@ int cn20k_register_pfvf_mbox_intr(struct otx2_nic *pf, int numvfs)#define RQ_BP_LVL_AURA (255 - ((85 * 256) / 100))/* BP when 85% is full */ -static u8 cn20k_aura_bpid_idx (struct otx2_nic *pfvf,int aura_id) -{ -#ifdef CONFIG_DCB -return pfvf->queue_to_pfc_map[aura_id]; -#else -return 0 ; -#endif -} -static int cn20k_tc_get_entry_index (struct otx2_flow_config *flow_cfg,struct otx2_tc_flow *node) {
@@ -580,7 +571,7 @@ static int cn20k_aura_aq_init(struct otx2_nic *pfvf, int aura_id,if (pfvf->nix_blkaddr ==BLKADDR_NIX1 ) aq->aura.bp_ena =1 ; - bpid_idx =cn20k_aura_bpid_idx (pfvf, aura_id); + bpid_idx =otx2_get_bpid_idx (pfvf, aura_id); aq->aura.bpid = pfvf->bpid[bpid_idx];/* Set backpressure level for RQ's Aura */
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +6 -10
@@ -1056,6 +1056,7 @@ int otx2_cq_init(struct otx2_nic *pfvf, u16 qidx)struct nix_aq_enq_req *aq;struct otx2_cq_queue *cq;struct otx2_pool *pool; +u8 bpid_idx; cq = &qset->cq[qidx]; cq->cq_idx = qidx;
@@ -1133,11 +1134,8 @@ int otx2_cq_init(struct otx2_nic *pfvf, u16 qidx)if (!is_otx2_lbkvf (pfvf->pdev)) {/* Enable receive CQ backpressure */ aq->cq.bp_ena =1 ; -#ifdef CONFIG_DCB - aq->cq.bpid = pfvf->bpid[pfvf->queue_to_pfc_map[qidx]]; -#else - aq->cq.bpid = pfvf->bpid[0 ]; -#endif + bpid_idx =otx2_get_bpid_idx (pfvf, qidx); + aq->cq.bpid = pfvf->bpid[bpid_idx];/* Set backpressure level is same as cq pass level */ aq->cq.bp =RQ_PASS_LVL_CQ (pfvf->hw.rq_skid, qset->rqe_cnt);
@@ -1379,6 +1377,7 @@ int otx2_aura_aq_init(struct otx2_nic *pfvf, int aura_id, {struct npa_aq_enq_req *aq;struct otx2_pool *pool; +u8 bpid_idx;int err; pool = &pfvf->qset.pool[pool_id];
@@ -1434,11 +1433,8 @@ int otx2_aura_aq_init(struct otx2_nic *pfvf, int aura_id,*/ if (pfvf->nix_blkaddr ==BLKADDR_NIX1 ) aq->aura.bp_ena =1 ; -#ifdef CONFIG_DCB - aq->aura.nix0_bpid = pfvf->bpid[pfvf->queue_to_pfc_map[aura_id]]; -#else - aq->aura.nix0_bpid = pfvf->bpid[0 ]; -#endif + bpid_idx =otx2_get_bpid_idx (pfvf, aura_id); + aq->aura.nix0_bpid = pfvf->bpid[bpid_idx];/* Set backpressure level for RQ's Aura */ aq->aura.bp =RQ_BP_LVL_AURA ;
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h +9 -0
@@ -1029,6 +1029,15 @@ static inline int otx2_tc_flower_rule_cnt(struct otx2_nic *pfvf)return pfvf->flow_cfg->nr_flows; } +static inline u8 otx2_get_bpid_idx (struct otx2_nic *pfvf,int qidx) +{ +#ifdef CONFIG_DCB +if (pfvf->queue_to_pfc_map) +return pfvf->queue_to_pfc_map[qidx]; +#endif +return 0 ; +} +/* MSI-X APIs */ void otx2_free_cints (struct otx2_nic *pfvf,int n);void otx2_set_cints_affinity (struct otx2_nic *pfvf);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 124/428 octeontx2-af: mcs: Fix SC resource cleanup loop
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baha Mesleh <[email protected]>
[ Upstream commit cdef07f3002f708a345392ee28d0d9bfac8383a1 ]
The SC resource cleanup and statistics loops were incorrectly iterating over secy.max instead of sc.max, so the highest SC id could be left allocated across teardown or FLR. Use sc.max as the loop bound.
--- drivers/net/ethernet/marvell/octeontx2/af/mcs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/ethernet/marvell/octeontx2/af/mcs.c +2 -2
@@ -314,7 +314,7 @@ int mcs_clear_all_stats(struct mcs *mcs, u16 pcifunc, int dir) }/* Clear SC stats */ -for (id =0 ; id < map->secy.max; id++) { +for (id =0 ; id < map->sc.max; id++) {if (map->sc2pf_map[id] != pcifunc)continue ;mcs_clear_stats (mcs,MCS_SC_STATS , id, dir);
@@ -738,7 +738,7 @@ int mcs_free_all_rsrc(struct mcs *mcs, int dir, u16 pcifunc) }/* free sc entries */ -for (id =0 ; id < map->secy.max; id++) { +for (id =0 ; id < map->sc.max; id++) {if (map->sc2pf_map[id] != pcifunc)continue ;mcs_free_rsrc (&map->sc, map->sc2pf_map, id, pcifunc);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 125/428 tipc: prevent GCM nonce reuse on peer key changes
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jérémy Jean <[email protected]>
[ Upstream commit 512ccd3d0e91e791fb37442aa0a2599aca19783d ]
TIPC can encrypt traffic between nodes using a different transmit key for each node. In this mode, the AES-GCM nonce for a packet sent to a known peer consists of a 32-bit prefix (a per-key salt XOR the peer's address) followed by a 64-bit counter. That counter is stored in the peer's RX crypto object. When the peer reports a change in which key it uses to receive packets, TIPC resets this counter. The sender can still be using the same TX key and salt, so subsequent packets reuse earlier nonces. This nonce reuse breaks confidentiality and exposes GCM's authentication key. This makes forgeries trivial: an attacker can exploit CTR malleability to alter captured ciphertexts and use the recovered authentication key to compute a valid tag for the modified ciphertext, under the same key and nonce.
Use the TX key's existing aead->seqno counter instead. All encryptions using that key object share the same atomic counter, so concurrent encryptions get distinct nonce counter values. The counter survives key activation and peer reconnection, and peer key-status reports cannot reset it. This prevents those transitions from causing nonce reuse while the same TX key remains installed.
The nonce format is unchanged, and receivers do not require consecutive counter values, so sharing the counter across peers remains compatible with existing receivers. A pre-existing check still invokes key revocation in the unlikely event that the counter wraps to zero.
--- net/tipc/crypto.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-)
net/tipc/crypto.c +5 -15
@@ -144,7 +144,7 @@ struct tipc_tfm {* @rcu: struct rcu_head * @key: the aead key * @gen: the key's generation -* @seqno: the key seqno (cluster scope) +* @seqno: the per-key TX nonce counter * @refcnt: the key reference counter */ struct tipc_aead {
@@ -190,7 +190,6 @@ struct tipc_crypto_stats {* @rekeying_intv: rekeying interval (in minutes) * @stats: the crypto statistics * @name: the crypto name -* @sndnxt: the per-peer sndnxt (TX) * @timer1: general timer 1 (jiffies) * @timer2: general timer 2 (jiffies) * @working: the crypto is working or not
@@ -219,7 +218,6 @@ struct tipc_crypto {struct tipc_crypto_stats __percpu *stats;char name[48 ]; -atomic64_t sndnxt____cacheline_aligned ;unsigned long timer1;unsigned long timer2;union {
@@ -1051,14 +1049,11 @@ static int tipc_ehdr_build(struct net *net, struct tipc_aead *aead,WARN_ON (skb_headroom (skb) < ehsz); ehdr = (struct tipc_ehdr *)skb_push (skb, ehsz); -/* Obtain a seqno first: -* Use the key seqno (= cluster wise) if dest is unknown or we're in -* cluster key mode, otherwise it's better for a per-peer seqno! +/* +* Keep the nonce unique for the lifetime of the TX key, +* including key state changes and peer reconnection. */ -if (!__rx || aead->mode ==CLUSTER_KEY ) - seqno =atomic64_inc_return (&aead->seqno); -else - seqno =atomic64_inc_return (&__rx->sndnxt); + seqno =atomic64_inc_return (&aead->seqno);/* Revoke the key if seqno is wrapped around */ if (unlikely (!seqno))
@@ -1237,7 +1232,6 @@ void tipc_crypto_key_flush(struct tipc_crypto *c)tipc_crypto_key_set_state (c,0 ,0 ,0 );for (k =KEY_MIN ; k <=KEY_MAX ; k++)tipc_crypto_key_detach (c->aead[k], &c->lock); -atomic64_set (&c->sndnxt,0 );spin_unlock_bh (&c->lock); }
@@ -1384,8 +1378,6 @@ static struct tipc_aead *tipc_crypto_key_pick_tx(struct tipc_crypto *tx,* It also considers if peer has no key, then we need to make own master key * (if any) taking over i.e. starting grace period and also trigger key * distributing process. -* -* The "per-peer" sndnxt is also reset when the peer key has switched. */ static void tipc_crypto_key_synch (struct tipc_crypto *rx,struct sk_buff *skb) {
@@ -1436,7 +1428,6 @@ static void tipc_crypto_key_synch(struct tipc_crypto *rx, struct sk_buff *skb)if (cur)tipc_aead_users_dec (tx->aead[cur],0 ); -atomic64_set (&rx->sndnxt,0 );/* Mark the point TX key users changed */ tx->timer1 = jiffies;
@@ -1501,7 +1492,6 @@ int tipc_crypto_start(struct tipc_crypto **crypto, struct net *net,tipc_crypto_key_set_state (c,0 ,0 ,0 );atomic_set (&c->key_distr,0 );atomic_set (&c->peer_rx_active,0 ); -atomic64_set (&c->sndnxt,0 ); c->timer1 = jiffies; c->timer2 = jiffies; c->rekeying_intv =TIPC_REKEYING_INTV_DEF ;
Signature · 1 line
2.53.0