7.2.8-rc1 review
Greg Kroah-Hartman
maintainercover 7.2.8-rc1 review
This is the start of the stable review cycle for the 7.2.8 release. There are 438 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 Fri, 25 Sep 2026 14:05:46 +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.8-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.8-rc1
Namjae Jeon <[email protected]>
ksmbd: fix partial normalized name responses
Mario Limonciello <[email protected]>
drm/amdgpu: restrict BAR0 fallback read to SR-IOV VFs only
Vadim Nikitushkin <[email protected]>
drm/ttm: fix swapped-out resources never leaving their bulk_move range
Iván Ezequiel Rodriguez <[email protected]>
ntsync: reject wait ioctls with zero owner
Mario Limonciello <[email protected]>
drm/amdgpu: Fix GPU PCIe link capability reporting
chong li <[email protected]>
drm/amdgpu: reduce early full GPU access during SR-IOV init
Arun Easi <[email protected]>
scsi: fnic: Fix missed link-up when critical IRQ targets offline CPU
Karan Tilak Kumar <[email protected]>
scsi: fnic: Bump up version number
Karan Tilak Kumar <[email protected]>
scsi: fnic: Make debug logging protocol independent
Qi Zheng <[email protected]>
fs: fix missed removal of super_fs_objects_eligible()
Usama Arif <[email protected]>
fs/super: skip non-memcg-aware nr_cached_objects in memcg slab shrink
Frank Sorenson <[email protected]>
smb: client: fix missing iov bounds check in parse_posix_sids()
Frank Sorenson <[email protected]>
smb: client: fix missing lower-bound check on DFS referral string offsets
Frank Sorenson <[email protected]>
smb: client: fix server->total_read for compound encrypted PDUs
Frank Sorenson <[email protected]>
smb: client: fix reparse buffer bounds in cifs_query_reparse_point()
Frank Sorenson <[email protected]>
smb: client: fix potential OOB read in smb3_enum_snapshots()
Frank Sorenson <[email protected]>
smb: client: fix OOB struct field reads in move_smb2_ea_to_cifs()
Frank Sorenson <[email protected]>
smb: client: fix next_buffer UAF and NextCommand bounds in compound PDUs
Paulo Alcantara <[email protected]>
smb: client: fix fattr leaking on wsl_to_fattr() failure
Paulo Alcantara <[email protected]>
smb: client: fix unaligned access in WSL reparse point parser
Paulo Alcantara <[email protected]>
smb: client: fix smbd_connection leak on cifs_get_tcp_session() error
Frank Sorenson <[email protected]>
smb: client: reject short Next offsets in parse_server_interfaces()
Joseph Qi <[email protected]>
smb: client: fix use-after-free of iface in cifs_try_adding_channels()
Paulo Alcantara <[email protected]>
smb: client: fix rlist race and missing initialization
April Cardenas <[email protected]>
smb/client: send lease break ACKs thru correct session for multiuser mounts
Paulo Alcantara <[email protected]>
smb: client: cancel reconnect work in clean_demultiplex_info()
Vladimir Marioukhine <[email protected]>
drm/amdkfd: implement restore_mqd callbacks for GFX12/12.1
David Francis <[email protected]>
drm/amdkfd: Avoid integer underflow with ffs in EOP ring size calc
David Francis <[email protected]>
drm/amdkfd: Avoid integer underflow in EOP ring size calculation.
Mario Limonciello <[email protected]>
drm/amdgpu: Skip KFD mapping clear before initialization
Mike Lothian <[email protected]>
drm/amdgpu: hold a runtime PM reference for P2P dma-buf attachments
Chengjun Yao <[email protected]>
drm/amdgpu: fix rmmio iounmap skipped on device removal
Tvrtko Ursulin <[email protected]>
drm/sched: Fix virtual runtime race
Jonghyuk Kim(MalHyuk) <[email protected]>
drm/msm: RCU-free the scheduler-containing ring and VM objects
Guangshuo Li <[email protected]>
drm/msm/hdmi_phy: fix runtime PM cleanup on probe failure
Saim Shujah <[email protected]>
drm/msm/dpu: clear pending peripheral flush state
Guangshuo Li <[email protected]>
drm/msm/adreno: fix autosuspend cleanup during teardown
Sophie D <[email protected]>
drm/gud: Ignore damage clips in full update mode
Sajal Gupta <[email protected]>
drm/gud: fix out-of-bounds write in gud_plane_atomic_check()
Devin Wittmayer <[email protected]>
wifi: mac80211: refuse to make a monitor active when it has no queue
Ivan Pustogarov <[email protected]>
wifi: mac80211: avoid out-of-bounds read for empty PREQ elements
Rik van Riel <[email protected]>
wifi: mac80211: avoid WARN in set_bitrate_mask when sdata not in driver
Zhao Li <[email protected]>
wifi: mwifiex: validate action frame fixed fields
Linmao Li <[email protected]>
wifi: mwifiex: prevent authentication frame length truncation
Pengpeng Hou <[email protected]>
wifi: mwifiex: validate scan response extents
Doruk Tan Ozturk <[email protected]>
wifi: mwifiex: bound the pairwise-cipher OUI walk to the IE length
Shengzhuo Wei <[email protected]>
wifi: p54: require a full exp_if record in PDR_INTERFACE_LIST
Shengzhuo Wei <[email protected]>
wifi: p54: validate curve data length in the calibration curve converters
Tianchu Chen <[email protected]>
wifi: wilc1000: fix RX buffer OOB-write in wilc_wlan_handle_isr_ext()
Ali Ahmet Memis <[email protected]>
wifi: wilc1000: fix out-of-bounds read in P2P public action frames
Runyu Xiao <[email protected]>
wifi: wlcore: release runtime PM ref on regdomain config failure
Fan Wu <[email protected]>
wifi: wcn36xx: Fix potential use-after-free in TX ack timer teardown
Tianchu Chen <[email protected]>
wifi: rsi: fix heap OOB write on key removal
Daehyeon Ko <[email protected]>
wifi: libipw: reject TKIP frames without a full MIC
Jiangshan Yi <[email protected]>
wifi: libertas_tf: fix UAF in lbtf_free_adapter()
Stanislaw Gruszka <[email protected]>
wifi: iwlegacy: fix broadcast stations deallocation
Jiangshan Yi <[email protected]>
wifi: brcmsmac: fix UAF in brcms_free_timer()
Wentao Liang <[email protected]>
watchdog: starfive-wdt: Fix runtime PM leak in starfive_wdt_pm_start()
Wentao Liang <[email protected]>
watchdog: sp5100_tco: Fix pci_dev reference leak in sp5100_tco_init()
Tzung-Bi Shih <[email protected]>
watchdog: rzv2h: Avoid division by zero
Tzung-Bi Shih <[email protected]>
watchdog: rtd119x: Avoid division by zero
Tzung-Bi Shih <[email protected]>
watchdog: msc313e: Propagate error code in resume()
Tzung-Bi Shih <[email protected]>
watchdog: msc313e: Fix premature reset during timeout update
Tzung-Bi Shih <[email protected]>
watchdog: digicolor: Avoid division by zero
Li Jun <[email protected]>
watchdog: da9063: fix suspend/resume handling of HW_RUNNING watchdog
Thomas Richard (congatec GmbH) <[email protected]>
hwmon: (cgbc-hwmon) Add missing sensors
Thomas Richard (congatec GmbH) <[email protected]>
hwmon: (cgbc-hwmon) Fix current sensors ID lookup
Guangshuo Li <[email protected]>
hwmon: (w83793) release probe data through kref
Guangshuo Li <[email protected]>
hwmon: (w83791d) remove fan/pwm 4-5 sysfs group on remove
Yibo Tan <[email protected]>
hwmon: (pwm-fan) Stop RPM timer before freeing tach data
Sanman Pradhan <[email protected]>
hwmon: (pmbus/tps53679) Select page 0 for single-page TPS53676
Sanman Pradhan <[email protected]>
hwmon: (pmbus/tps53679) Fix TPS53676 phase page decoding
Nuno Sá <[email protected]>
hwmon: (pmbus/core) increase number of phases and add new mask
Muhammad Bilal <[email protected]>
hwmon: (hp-wmi-sensors) Fix use-after-free in fungible_show()
Iván Ezequiel Rodriguez <[email protected]>
Input: zero ff_effect before compat copy in input_ff_effect_from_user
Dmitry Torokhov <[email protected]>
Input: synaptics-rmi4 - fix GPF in suspend and resume when unbound
Raphaël Larocque <[email protected]>
Input: synaptics - disable InterTouch on ThinkPad T440p (board id 2722)
Hans de Goede <[email protected]>
Input: soc_button_array - check btns_desc->package.count
Hans de Goede <[email protected]>
Input: soc_button_array - fix MS Surface Pro 11 probe failure
Dmitry Torokhov <[email protected]>
Input: rmi_smbus - fix out-of-bounds read in rmi_smb_write_block()
Chris Sommers <[email protected]>
Input: i8042 - add quirk for Acer Aspire Go 15 AG15-42P
Runyu Xiao <[email protected]>
Input: hp_sdc - shut down kicker timer on module exit
Iván Ezequiel Rodriguez <[email protected]>
Input: evdev - zero absinfo before partial copy in EVIOCSABS
Linkai Gong <[email protected]>
Input: cyttsp5 - clamp the HID report size before memcpy
Alexei Turtanov <[email protected]>
Input: atkbd - skip deactivate for Xiaomi Redmi Book Pro 16 2026
Alvin Šipraga <[email protected]>
Input: adp5588-keys - cache GPIO state before registering the gpiochip
Diogo Ivo (Schneider Electric) <[email protected]>
mmc: sdhci_am654: Fallback to DT-provided itap delay on DDR50 tuning failure
Diogo Ivo (Schneider Electric) <[email protected]>
mmc: sdhci_am654: Clear ITAPDLY on tuning failure
Diogo Ivo (Schneider Electric) <[email protected]>
mmc: sdhci_am654: Reset command and data lines on failed tuning
Diogo Ivo (Schneider Electric) <[email protected]>
mmc: sdhci_am654: Move tuning_loop to local variable
Xu Rao <[email protected]>
mmc: spi: reset bytes_xfered before retrying CRC failures
Runyu Xiao <[email protected]>
mmc: sh_mmcif: initialize IRQ-thread mutex before requesting interrupt
Felix Gu <[email protected]>
mmc: sdio_uart: fix xmit_fifo leak when the port table is full
Myeonghun Pak <[email protected]>
mmc: sdhci-of-aspeed: Remove children before releasing SDC resources
Florian Maillard <[email protected]>
mmc: rtsx_pci_sdmmc: ignore broken write-protect on ThinkPad X260
Fan Wu <[email protected]>
mmc: mxcmmc: cancel data work and watchdog on remove
Fan Wu <[email protected]>
mmc: mmci: Fix use-after-free in busy-timeout work
Fan Wu <[email protected]>
mmc: hsq: Fix use-after-free in retry work
Zhu Ling <[email protected]>
mmc: core: Fix OF node reference leak on card add failure
Fan Wu <[email protected]>
mmc: core: Cancel SDIO IRQ work before freeing host
Bartosz Golaszewski <[email protected]>
power: sequencing: fix NULL-pointer dereference in pwrseq_device_register()
Bartosz Golaszewski <[email protected]>
power: sequencing: fix NULL-pointer dereference in pwrseq_unit_new()
Bartosz Golaszewski <[email protected]>
power: sequencing: don't call .post_enable() if pwrseq_unit_enable() failed
Christian Göttsche <[email protected]>
selinux: always fill AVC decision in avc_has_perm_noaudit()
Karl Mehltretter <[email protected]>
selinux: recheck intermediate backing files on mprotect()
Karl Mehltretter <[email protected]>
selinux: preserve user SID across nested backing files
Shuhei Takeshita <[email protected]>
IB/hfi1: Fix the PIO_CRED credit-return mmap
Shuhei Takeshita <[email protected]>
IB/hfi1: Resolve the credit-return buffer through the send context's node
Shuangpeng Bai <[email protected]>
IB/mlx4: Fix use-after-free on pkey sysfs registration failure
Guangshuo Li <[email protected]>
i2c: imx: disable autosuspend on remove
Shengzhuo Wei <[email protected]>
i2c: imx: release DMA channels on probe error
Liu Zhenlong <[email protected]>
i2c: qcom-cci: fix device_node refcount leak in cci_probe()/cci_remove()
Linkai Gong <[email protected]>
i2c: atr: fix dangling adapter pointer on add failure
Shengzhuo Wei <[email protected]>
i2c: at91: release DMA channels on remove and probe error
fangqiurong <[email protected]>
sched_ext: Close the pre-enable ops error claim window
Wanwu Li <[email protected]>
sched_ext: Fix NULL sched deref in kfunc sub-sched error paths
Jarkko Sakkinen <[email protected]>
KEYS: trusted: Fix tpm2_load_cmd() boundary check
Maoyi Xie <[email protected]>
keys: translate request_key_auth pid for the reading procfs instance
Cen Zhang <[email protected]>
KEYS: encrypted: fix integer overflow of datablob_len
Wenjie Qi <[email protected]>
mm: filemap: retain mapped dropbehind folios
Lorenzo Stoakes (ARM) <[email protected]>
mm/vma: correctly unaccount on mmap_prepare() failure
Jiayuan Chen <[email protected]>
mm/shrinker: fix bogus set_shrinker_bit() with cgroup.memory=nokmem
Lorenzo Stoakes (ARM) <[email protected]>
mm/mremap: account mm->locked_vm correctly for MREMAP_DONTUNMAP
Shakeel Butt <[email protected]>
mm/mlock: use the IRQ-safe accessor for NR_MLOCK in __munlock_folio()
Lorenzo Stoakes (ARM) <[email protected]>
mm/huge_memory: bypass THP tuneables for huge pfnmap mappings
Nhat Pham <[email protected]>
mm, swap: fix SWAP_USAGE_OFFLIST_BIT collision with real usage count
Yifei Gao <[email protected]>
memstick: ms_block: destroy io_queue workqueue on removal
Shakeel Butt <[email protected]>
memcg: avoid charging the root memcg from obj_cgroup_charge_pages()
Théo Lebrun <[email protected]>
mips: select CONFIG_WEAK_REORDERING_BEYOND_LLSC from CONFIG_EYEQ
Alexey Klimov <[email protected]>
soc: samsung: exynos-pmu: fix use-after-free of interrupt generator node
Zhiling Zou <[email protected]>
xfrm: save input state data before secpath resets
Siwei Zhang <[email protected]>
xfrm: use hlist_del_init_rcu for state_cache and state_cache_input
Chengfeng Ye <[email protected]>
xfrm: serialize state GC with device state flush
Alberto Carboneri <[email protected]>
scsi: core: Validate MODE SENSE lengths in scsi_cdl_enable()
Mark Amirkan <[email protected]>
net/packet: avoid truncating TPACKET_V3 private size
Mark Amirkan <[email protected]>
net/packet: clear RX owner on VNET header error
Jamal Hadi Salim <[email protected]>
net/sched: hhf: cap hh_flows_limit at change time
Xuanqiang Luo <[email protected]>
net/sched: act_api: release tail references on DELACTION failure
Guanglei Zhu <[email protected]>
net: wwan: mhi_wwan_mbim: check skb_copy_bits() return value
Guanglei Zhu <[email protected]>
net: wwan: mhi_wwan_mbim: guard against a cyclic NDP chain
Guanglei Zhu <[email protected]>
net: wwan: t7xx: validate the netif index in t7xx_ccmni_recv_skb()
Ahmed Naseef <[email protected]>
net: phy: mediatek: do not report link and per-speed LED rules together
Mark Amirkan <[email protected]>
net: lan743x: fix RX checksum use-after-free
Gris Ge <[email protected]>
net: ip_tunnel: initialize options_len before referencing options
Zhiling Zou <[email protected]>
ipv6: xfrm: use full sockets in local error paths
David Hu <[email protected]>
dma-buf: Split sgl by largest page-aligned chunk
David Hu <[email protected]>
dma-buf: Fix silent overflow for phys vec to sgt
Christian König <[email protected]>
dma-buf/dma-fence: fix checking signaling bit for timeline and driver name v3
Alexander Chesnokov <[email protected]>
dmaengine: ti: k3-udma-glue: fix NULL dereference in k3_udma_glue_release_rx_chn()
Christian Lugnberg <[email protected]>
dmaengine: sun6i: fix undefined behaviour in sun6i_dma_tx_status
Christian Lugnberg <[email protected]>
dmaengine: sun6i: fix non-atomic read of DMA position registers
Abdurrahman Hussain <[email protected]>
gpiolib: of: don't mark hog nodes OF_POPULATED before a chip is found
Michail Tatas <[email protected]>
gpiolib: Put fwnode reference on failure
Guanghui Yang <[email protected]>
btrfs: clear free space tree creation state on rebuild failure
Anand Jain <[email protected]>
btrfs: derive f_fsid with dev_t only when temp_fsid is active
Filipe Manana <[email protected]>
btrfs: fix creation of compressed inline extents that don't save space
Hongling Zeng <[email protected]>
btrfs: take commit root semaphore when iterating in mark_block_group_to_copy()
Radek Podgorny <[email protected]>
Bluetooth: keep dst_type with dst when reusing an LE connection
Chengfeng Ye <[email protected]>
Bluetooth: hci_sync: Serialize local codec list cleanup
Laxman Acharya Padhya <[email protected]>
Bluetooth: hci_codec: validate vendor codec count length
Aamir Ahmed <[email protected]>
Bluetooth: eir: validate service data length before reading UUID
Nicolas Thibert <[email protected]>
Bluetooth: btusb: fix NXP IW610 composite device handling
Mark Rutland <[email protected]>
arm64: percpu: Fix LSE operations on {8,16}-bit types
Mark Rutland <[email protected]>
arm64: percpu: Fix this_cpu_and() mask generation
Mark Rutland <[email protected]>
arm64: percpu: Fix this_cpu_write() casting
Dinh Nguyen <[email protected]>
arm64: dts: socfpga: change access permission from 755 to 644
Koichiro Den <[email protected]>
arm64: dts: renesas: r8a779f0: Set UFS lane count
Bradley Morgan <[email protected]>
arm64: hibernate: pass HVC_SET_VECTORS args to the resume hvc
Thomas Huth <[email protected]>
kselftest/arm64: Fix size of thread_data values for pthread_join()
Wyatt Feng <[email protected]>
net: xfrm: reject unrepresentable espintcp transport headers
Jeff Layton <[email protected]>
nfsd: fix handling of NFSEXP_PNFS in the netlink codepath
Zhiling Zou <[email protected]>
openvswitch: avoid reallocating confirmed conntrack labels
Jeffin Philip <[email protected]>
RDMA/core: fix refcount bug in iwpm_get_nlmsg_request()
Quanye Yang <[email protected]>
RDMA/ucma: Serialize join and leave on copy_to_user failure
Hao-Qun Huang <[email protected]>
spi: virtio: Use the per-transfer bits per word
Itai Handler <[email protected]>
spi: spi-zynqmp-gqspi: stop the controller on shutdown
Frieder Schrempf <[email protected]>
spi: fsl-qspi: Reprogram the clock rate when the operation frequency changes
Ian Luites <[email protected]>
soundwire: dmi-quirks: Disable ghost Realtek on Asus GX651AX
Donggeun Yoo <[email protected]>
swiotlb: use the adjusted address for the highmem page lookup
Inbal Schussheim <[email protected]>
tcp: exclude old ACKs from tcp fast path
Chang S. Bae <[email protected]>
x86/microcode/intel: Reject problematic loading on Granite Rapids systems
Chang S. Bae <[email protected]>
x86/build/64: Prevent native builds from generating EGPR use
Lyude Paul <[email protected]>
drm/nouveau/gsp/r570: Enable S/R Display workaround in GSP
Lyude Paul <[email protected]>
drm/nouveau/gsp/r570: Set GcOff = 0 in fbsr
Lyude Paul <[email protected]>
drm/nouveau/gsp: Increase delay for magic sleep in r535_gsp_fini()
Lyude Paul <[email protected]>
Revert "nouveau/gsp: fix suspend/resume regression on r570 firmware"
Chunfeng Song <[email protected]>
rust: net: phy: fix off-by-one bit positions in device status accessors
Thomas Gleixner <[email protected]>
signal: Prevent exec() race
Aohan Mei <[email protected]>
rds: ib: use rds_conn_drop() on protocol version mismatch
Thomas Gleixner <[email protected]>
posix-cpu-timers: Prevent freeing a timer which is queued on the expiry list
Claudiu Beznea <[email protected]>
phy: renesas: rcar-gen3-usb2: Avoid long delay in atomic context
Richard Zhu <[email protected]>
PCI: imx6: Move clock enable after core reset assertion
Seunguk Shin <[email protected]>
fs/dax: check zero or empty entry before converting xarray entry
Hyunwoo Kim <[email protected]>
exec: Cleanup POSIX timers right after de_thread()
Wentao Liang <[email protected]>
cifs: Fix server use-after-free in cifs_chan_skip_or_disable()
Wentao Liang <[email protected]>
ata: libahci_platform: Fix device reference leak in ahci_platform_get_resources()
Niklas Cassel <[email protected]>
ata: libahci: clear PxCLBU and PxFBU for AHCI_HFLAG_32BIT_ONLY
Michal Koutný <[email protected]>
cgroup: Avoid iteration of dying tasks with zero refcount
Jiangshan Yi <[email protected]>
ASoC: codecs: rt712-sdca-dmic: fix uninitialized stream_config->type
Yuho Choi <[email protected]>
ALSA: virtio: reset device before deleting virtqueues
Xiang Mei <[email protected]>
ALSA: usb-audio: Clamp implicit feedback packet count to URB capacity
Takashi Iwai <[email protected]>
ALSA: core: Fix potential UAF after asynchronous card release
David Howells <[email protected]>
9p: Fix v9fs_issue_write() to update i_size and remote_i_size
Jeremy Nyberg <[email protected]>
Input: xpad - fix PDP Marvel Xbox 360 controller
Roberts Kursitis <[email protected]>
Input: xpad - add support for Azeron devices
Erich Sartison <[email protected]>
Input: xpad - add support for Victrix Pro BFG Controller
Li Jun <[email protected]>
watchdog: da9062: fix suspend/resume handling of HW_RUNNING watchdog
James Seo <[email protected]>
hwmon: (hp-wmi-sensors) Improve raw WMI string handling
Cong Nguyen <[email protected]>
hwmon: (gpio-fan) return IRQ_HANDLED from the shared alarm IRQ handler
hpp.iscas <[email protected]>
Input: eeti_ts - publish the OF module alias
Matthew Schwartz <[email protected]>
x86/fred: Reconstruct the #GP context for rejected INT instructions
Andrea Righi <[email protected]>
sched/core: Avoid false migration warning for proxy donors
Vinay Belgaumkar <[email protected]>
perf: Fix null pointer access in is_include_guest_event()
Filipe Manana <[email protected]>
btrfs: check if there is space for chunk item when validating sys chunk array
Filipe Manana <[email protected]>
btrfs: abort transaction on failure to update inode for hole punching and reflinking
Francis Marlou Pacaro <[email protected]>
drm/amd/display: fix MALL hysteresis timer underflow at high refresh rates
Dmitriy Chumachenko <[email protected]>
drm/amdgpu: check ras and obj before dereference
Eric Dumazet <[email protected]>
net: skbuff: do not leave stale header offsets after pskb_carve()
Dmitriy Okunev <[email protected]>
net: mvpp2: prevent buffer overflow in page_pool allocation
James Clark <[email protected]>
net: macb: fix ordering around PTP timestamp read
Jinke Han <[email protected]>
x86/kprobes: Fix crash when probing CS CALL instructions
Daniel Zahka <[email protected]>
net: psp: avoid conflicts with skb->decrypted and sk_validate_xmit_skb()
Lorenzo Bianconi <[email protected]>
net: stmmac: preserve real_num_tx_queues on mqprio setup failure
Eric Dumazet <[email protected]>
net: prevent torn reads in netdev_tc_txq
Lorenzo Bianconi <[email protected]>
net: stmmac: propagate FPE preemption-class mapping errors
Linus Walleij <[email protected]>
net: ethernet: cortina: Ack RX overrun interrupt correctly
Eric Dumazet <[email protected]>
net: lock the socket in sock_gettstamp()
Jakub Kicinski <[email protected]>
eth: fbnic: ring the doorbell if a burst ends in a drop
Yige Jiang <[email protected]>
net: netsec: fix device_node reference leak on phy_np
Farhad Alemi <[email protected]>
net: remove WARN_ON_ONCE() from the dev_fill_forward_path() loop check
Lorenzo Bianconi <[email protected]>
net: pass net_device_path_ctx to dev_fill_forward_path()
Pablo Neira Ayuso <[email protected]>
net: pass dst via net_device_path in dev_fill_forward_path()
Pablo Neira Ayuso <[email protected]>
net: do not advance stack index from dev_fwd_path()
Jamal Hadi Salim <[email protected]>
net/sched: codel: bound the dropping loop per dequeue call
Vijendar Mukunda <[email protected]>
ASoC: amd: acp: fix ffs() operator precedence for SoundWire link ID
Vijendar Mukunda <[email protected]>
ASoC: amd: acp: refactor codec config count in SOF SoundWire machine driver
Kuninori Morimoto <[email protected]>
ASoC: sdw_utils: tidyup asoc_sdw_parse_sdw_endpoints()
Kuninori Morimoto <[email protected]>
ASoC: sdw_utils: tidyup .count_sidecar
Vijendar Mukunda <[email protected]>
ASoC: amd: acp: bounds-check SoundWire link ID in machine drivers
Richard Fitzgerald <[email protected]>
ASoC: cs-amp-lib: Prevent NULL pointer if efi variable is zero length
HyeongJun An <[email protected]>
ASoC: hdmi-codec: Report a change when the channel status moves
Sasha Levin <[email protected]>
ASoC: ux500: Parenthesize MSP_{RX,TX}_CLKPOL_BIT() arguments
Daniel Linjama <[email protected]>
btrfs: handle lack of space when cleaning up verity items
Raag Jadav <[email protected]>
drm/xe/i2c: Disable IRQ on unbind
Peter Zijlstra <[email protected]>
futex: Also allocate private hash on vfork()
Nemesa Garg <[email protected]>
Revert "drm/i915/display: Clear SEL_FETCH_PLANE_CTL on plane disable"
Shivaprasad G Bhat <[email protected]>
powerpc/iommu: Fix the overflow validation in iommu_tce_check_ioba
Amit Machhiwal <[email protected]>
KVM: PPC: Book3S HV: fix secure device page leak on uv_page_in() failure
Amit Machhiwal <[email protected]>
KVM: PPC: Book3S HV: fix use-after-free in kvmhv_emulate_tlbie_all_lpid()
Eric Dumazet <[email protected]>
netlink: do not free nlk->groups while lockless readers can use it
Nikolay Aleksandrov <[email protected]>
net: bridge: vlan: fix bugs caused by switchdev deletion errors
Lorenzo Bianconi <[email protected]>
net: stmmac: do not overwrite phc_index when no PTP clock is registered
Eric Dumazet <[email protected]>
drop_monitor: fix out-of-bounds write in reset_per_cpu_data()
Eric Dumazet <[email protected]>
drop_monitor: use raw_cpu_ptr() in tracepoint probes
Eric Dumazet <[email protected]>
drop_monitor: use timer_shutdown_sync() to prevent timer rearming during teardown
Eric Dumazet <[email protected]>
drop_monitor: synchronize tracepoint unregistration on error path
Eric Dumazet <[email protected]>
pppoatm: ensure a writable skb header and linear data
Lorenzo Bianconi <[email protected]>
net: stmmac: fix TSO header length truncation
Kuniyuki Iwashima <[email protected]>
af_unix: Unify scc_index when finalising SCC in __unix_walk_scc().
Juan Perdomo <[email protected]>
Bluetooth: RFCOMM: avoid socket lock inversion in listener cleanup
Sai Teja Aluvala <[email protected]>
Bluetooth: btintel_pcie: fix off-by-one bounds check in RX submit
Tzung-Bi Shih <[email protected]>
Bluetooth: btmtksdio: Fix PM runtime reference leak in shutdown
Chris Lu <[email protected]>
Bluetooth: btmtksdio, btmtkuart: validate WMT event length before struct access
Chris Lu <[email protected]>
Bluetooth: btmtk: fix wrong status for short WMT FUNC_CTRL events
Luiz Augusto von Dentz <[email protected]>
Bluetooth: ISO: set BT_LISTEN before requesting a BIG sync
Luiz Augusto von Dentz <[email protected]>
Bluetooth: ISO: Fix parent socket leak in iso_conn_ready()
Ibrahim Abdelkader <[email protected]>
Bluetooth: hci_qca: Do not write to the serial port after it is closed
Radek Podgorny <[email protected]>
Bluetooth: put the peer's on-air address on air when we cannot resolve
Weiming Shi <[email protected]>
Bluetooth: coredump: Quiesce dump work on unregister
Chandrashekar Devegowda <[email protected]>
Bluetooth: btintel_pcie: validate TX skb length in send_sync
ThangNN99 <[email protected]>
Bluetooth: hci_core: Fix queuing tx_work after workqueue is drained
Baineng Shou <[email protected]>
dmaengine: mmp_pdma: fix wrong sg length in mmp_pdma_prep_slave_sg()
Namjae Jeon <[email protected]>
ksmbd: keep compound responses on query info errors
Namjae Jeon <[email protected]>
ksmbd: fix partial file information responses
Namjae Jeon <[email protected]>
ksmbd: return buffer overflow for partial filesystem info
Eric Dumazet <[email protected]>
tcp: do not let tcp_rmem be set below 4096
Kuniyuki Iwashima <[email protected]>
tcp: Don't call skb_clone_and_charge_r() for close()d listener in tcp_v6_do_rcv().
Nikolay Aleksandrov <[email protected]>
net: bridge: mst: move switchdev call outside rcu
Karl Mehltretter <[email protected]>
wifi: brcmfmac: fix lost 802.1x TX completion wakeup
Hohyun Sim <[email protected]>
net: fddi: skfp: fix NULL deref when setting the MAC address while down
Dong Chenchen <[email protected]>
ipv4: icmp: reject RTN_UNREACHABLE input routes in icmp_route_lookup
Kuniyuki Iwashima <[email protected]>
sysctl: Check range in proc_dointvec_ms_jiffies_minmax
Nicolai Buchwitz <[email protected]>
net: bcmgenet: restore the hardware filters on open
Daniel Golle <[email protected]>
net: dsa: mxl862xx: disable the stats poll on teardown
Andrea Mayer <[email protected]>
seg6: set IPSKB_L3SLAVE from IP6SKB_L3SLAVE on IPIP decapsulation
Dmitry Baryshkov <[email protected]>
drm/msm/dsi: round the byte clock rate after reparenting to the PHY PLL
Filipe Manana <[email protected]>
btrfs: tree-checker: print dev extent offset in error message
Nicolas Escande <[email protected]>
wifi: ath11k: cleanup arsta in ath11k_mac_peer_cleanup_all()
Slavin Liu <[email protected]>
ALSA: hda: trace PCM open only after assigning a stream
Karl Mehltretter <[email protected]>
drm/vc4: Use managed KMS polling to fix UAF on unbind
Shuicheng Lin <[email protected]>
drm/xe/shrinker: Take a runtime PM ref before shrinking non-system memory
Shuicheng Lin <[email protected]>
drm/xe/shrinker: Return the freed page count through a parameter
Shuicheng Lin <[email protected]>
drm/xe/mmio_gem: Revoke drm_vma_node on xe_mmio_gem destroy
Ilia Levi <[email protected]>
drm/xe/mmio_gem: use write-back mapping for dummy page
Ilia Levi <[email protected]>
drm/xe/mmio_gem: forbid VMA split
Zihan Xi <[email protected]>
wifi: virt_wifi: don't transfer operstate before register
Namjae Jeon <[email protected]>
ksmbd: follow SMB2 session expiration semantics
Namjae Jeon <[email protected]>
ksmbd: extend procfs server statistics
Namjae Jeon <[email protected]>
ksmbd: fix malformed procfs status output
Xiang Mei <[email protected]>
ALSA: 6fire: fix OOB write from device-reported iso length
Takashi Iwai <[email protected]>
ALSA: usb: 6fire: Avoid embedded URBs
Runyu Xiao <[email protected]>
gpio: virtuser: skip free_irq when no IRQ is installed
Ulises Mendez Martinez <[email protected]>
objtool: Validate disassembler headers in libopcodes probe
Karl Mehltretter <[email protected]>
Input: trackpoint - fix the inertia attribute name in the ABI document
Gabor Juhos <[email protected]>
spi: spi-qpic-snand: avoid writing QPIC_EBI2_ECC_BUF_CFG register
Richard Fitzgerald <[email protected]>
ASoC: soc-pcm: Apply snd_soc_dai_link_ch_map.codec_ch_mask to codec params
Richard Fitzgerald <[email protected]>
ASoC: Add codec_ch_mask to snd_soc_dai_link_ch_map
Richard Fitzgerald <[email protected]>
ASoC: Rename snd_soc_dai_link_ch_map.ch_mask to cpu_ch_mask
William Bright <[email protected]>
drm/msm/dp: fix link bandwidth check when wide bus is enabled
Jesse Casco <[email protected]>
drm/msm/dp: skip PUSH_IDLE when the link was never enabled
Nguyen Ngoc Thang <[email protected]>
ALSA: pcm: set timer->private_data before registering the PCM timer
AngeloGioacchino Del Regno <[email protected]>
phy: mediatek: phy-mtk-hdmi-mt8195: Fix TMDS clk bit ratio setting
AngeloGioacchino Del Regno <[email protected]>
phy: mediatek: phy-mtk-hdmi-mt8195: Fix PLL calc divisor overflow
Namjae Jeon <[email protected]>
ntfs: ignore interrupted inode reads as corruption
Namjae Jeon <[email protected]>
ntfs: propagate folio errors
Namjae Jeon <[email protected]>
ntfs: protect runlist updates with the runlist lock
Namjae Jeon <[email protected]>
ntfs: account for MFT records added during allocation
Namjae Jeon <[email protected]>
ntfs: repack $MFT/$ATTRIBUTE LIST
Namjae Jeon <[email protected]>
ntfs: use dynamic MFT tail reservation
Takashi Iwai <[email protected]>
ALSA: bcd2000: Fix race between rawmidi and disconnect
Kuniyuki Iwashima <[email protected]>
neighbour: Skip default parms when resumed in neightbl_dump_info().
Kuniyuki Iwashima <[email protected]>
neighbour: Don't render blackhole_netdev via RTM_GETNEIGHTBL.
Kuniyuki Iwashima <[email protected]>
neighbour: Enforce min/max to NDTPA_INTERVAL_PROBE_TIME_MS.
Kuniyuki Iwashima <[email protected]>
neighbour: Add missing RCU annotation for neightbl_dump_info().
Karl Mehltretter <[email protected]>
keys: fix lost wakeup when reaping a dead key type
Jérémy Jean <[email protected]>
smb: client: validate absolute native symlink targets before NT fixups
Thadeu Lima de Souza Cascardo <[email protected]>
drm: Fix drm_pending_vblank_event leak in error path for out_fence_ptr
Catalin Marinas <[email protected]>
arm64: mte: Fix PTRACE_{PEEK,POKE}MTETAGS error documentation
Breno Leitao <[email protected]>
arm64: hibernate: clone only the linear map that exists at runtime
Shouping Wang <[email protected]>
perf/arm-cmn: Fix wp_dev_sel2 setting for multi-DTM configurations
Pablo Neira Ayuso <[email protected]>
netfilter: flowtable: hold reference on ct until flow is released
Pablo Neira Ayuso <[email protected]>
netfilter: nf_nat: unregister and release hooks on error
Fernando Fernandez Mancera <[email protected]>
netfilter: nf_tables: fix device name and prefix match in hook lookup
Theodor Arsenij Larionov Trichkine <[email protected]>
netfilter: nft_nat: fully initialise new_addr in netmap setup
Karl Mehltretter <[email protected]>
dma-buf: Make DMABUF_DEBUG default to y on DEBUG_KERNEL kernels
Karl Mehltretter <[email protected]>
drm/msm/adreno: Fix the skip_gpu parameter description
Karl Mehltretter <[email protected]>
drm/msm: Fix the separate_gpu_kms parameter description
David Laight <[email protected]>
x86/div64: Fix addition of large constants in mul_u64_add_u64_div_u64()
Jérémy Jean <[email protected]>
RDMA/siw: Bound fragmented header copies by the remaining length
Leon Romanovsky <[email protected]>
RDMA/efa: Keep EQ resources alive while IRQ is registered
Leon Romanovsky <[email protected]>
RDMA/efa: Keep admin queues alive while IRQ is registered
Alex Bereza <[email protected]>
dmaengine: xilinx_dma: Fix hardware buffer descriptor chain after cyclic DMA
Sascha Hauer <[email protected]>
dmaengine: pxa: fix double counting of the hw descriptors
Alex Bereza <[email protected]>
dmaengine: xilinx_dma: Fix hardware buffer descriptor reuse order
Karl Mehltretter <[email protected]>
scsi: qla2xxx: Fix the ql2xfc2target parameter description
Karl Mehltretter <[email protected]>
scsi: pm80xx: Fix the use_msix, use_tasklet and read_wwn parameter descriptions
Meijing Zhao <[email protected]>
mm: memblock: show all region flags in debugfs
Johannes Berg <[email protected]>
wifi: mac80211: set up the TX info early to fix failure paths
Johannes Berg <[email protected]>
wifi: mac80211: mesh: release the channel if start fails
Johannes Berg <[email protected]>
wifi: mac80211: mesh: reset the CSA state when leaving
Johannes Berg <[email protected]>
wifi: mac80211: add HE 6 GHz capability in the scan elems len
Johannes Berg <[email protected]>
wifi: mac80211: don't access the TSF of a down interface
Johannes Berg <[email protected]>
wifi: mac80211: don't RCU-dereference the mesh CSA settings we just set
Johannes Berg <[email protected]>
wifi: mac80211: don't allow link changes when iface is down
Johannes Berg <[email protected]>
wifi: mac80211: require a peer station for TDLS setup confirm
Johannes Berg <[email protected]>
wifi: mac80211: reset the AP_VLAN tailroom counter on ifdown
Johannes Berg <[email protected]>
wifi: mac80211: don't allow injecting frames wider than the chanctx
Johannes Berg <[email protected]>
wifi: mac80211_hwsim: don't hand frames to mac80211 while stopping
Johannes Berg <[email protected]>
wifi: cfg80211: get the wiphy out of a dying network namespace
Johannes Berg <[email protected]>
wifi: mac80211: unlist vifs when their netdev is unregistered
Johannes Berg <[email protected]>
wifi: cfg80211: undo netns switch if renaming the wiphy fails
Johannes Berg <[email protected]>
wifi: cfg80211: restore netns_immutable on failures
Johannes Berg <[email protected]>
wifi: mac80211: only operate on TDLS peers in the TDLS code
Johannes Berg <[email protected]>
wifi: mac80211: reset the LED state when ifup fails
Johannes Berg <[email protected]>
wifi: mac80211: reset state when starting AP fails
Johannes Berg <[email protected]>
wifi: mac80211: abort chanswitch when leaving a mesh
Johannes Berg <[email protected]>
wifi: mac80211: suppress chanctx warning for debugfs reset
Johannes Berg <[email protected]>
wifi: mac80211: don't offload TC setup on AP_VLAN interfaces
Johannes Berg <[email protected]>
wifi: mac80211: don't warn when an IBSS has no channel to scan
Johannes Berg <[email protected]>
wifi: mac80211: don't start a ROC while scanning
Johannes Berg <[email protected]>
wifi: cfg80211: fix NAN regulatory enforcement
Johannes Berg <[email protected]>
wifi: cfg80211: ibss: ref BSS entry for joined event
Johannes Berg <[email protected]>
wifi: cfg80211: don't filter by BSS type when removing stale entries
Johannes Berg <[email protected]>
wifi: cfg80211: only group hidden BSSes with beacon entries
Johannes Berg <[email protected]>
wifi: cfg80211: don't free driver-owned scan requests
Shivank Garg <[email protected]>
dmaengine: wait for RCU readers before releasing dma_device
Shivank Garg <[email protected]>
dmaengine: fix use-after-free in dma_chan_put() and dma_release_channel()
Shivank Garg <[email protected]>
dmaengine: Fix device kref underflow in dma_chan_put()
Donggeun Yoo <[email protected]>
dma-mapping: don't trace the DMA address when the allocation fails
Donggeun Yoo <[email protected]>
dma-coherent: report a failed reserved memory assignment
Orgad Shaneh <[email protected]>
MIPS: Octeon: apply USB FDT fixups also when USB is modular
Julian Braha <[email protected]>
mips: econet: fix unmet dependencies for ECONET
Bard Liao <[email protected]>
soundwire: cadence_master: wait and cancel cdns->work before clock stop
Johannes Berg <[email protected]>
wifi: cfg80211: check IP header size in cfg80211_classify8021d()
Johannes Berg <[email protected]>
wifi: cfg80211: don't get the radio mask for netdev-less wdevs
Carolina Jubran <[email protected]>
IB/IPoIB: Avoid restoring OPER_UP after multicast flush
Shmulik Cohen <[email protected]>
wifi: libipw: reject too-short association responses
Shmulik Cohen <[email protected]>
wifi: libipw: reject too-short beacon and probe responses
Bogdan Nicolae <[email protected]>
wifi: brcmfmac: cyw: pass PMKID to firmware if present
Peng Hao <[email protected]>
wifi: mwifiex: fix IRQ leak using wrong index in MSI-X error path
Mariano Baragiola <[email protected]>
wifi: virt_wifi: free skb when disconnected
Lachlan Hodges <[email protected]>
wifi: mac80211: include TIM bitmap control for buffered S1G mcast traffic
Ruoyu Wang <[email protected]>
dmaengine: sprd: Fix runtime PM reference leak in probe
Troy Mitchell <[email protected]>
dmaengine: mmp_pdma: fix wrong extended DRCMR base for SpacemiT K3
Quanye Yang <[email protected]>
RDMA/rtrs-clt: Fix CQ pool leak when connect is interrupted
Jacob Moroni <[email protected]>
RDMA/irdma: Enforce local fence for IB_WR_REG_MR
Cheng Xu <[email protected]>
RDMA/erdma: Use IRQ-safe XArray helpers for QP and CQ tables
Li RongQing <[email protected]>
RDMA/mad: Fix receive buffer leak when PKey enforcement fails
Li RongQing <[email protected]>
RDMA/uverbs: Fix potential leak of resources->collection in flow_resources_alloc()
Sriharsha Basavapatna <[email protected]>
RDMA/bnxt_re: Avoid exposing umdbr to userspace
Ryan Mehri <[email protected]>
RDMA/rtrs: guard against null kobj name
Linkai Gong <[email protected]>
RDMA/bnxt_re: check create_singlethread_workqueue() in DCB setup
Yehyeong Lee <[email protected]>
IB/isert: wait for deferred control PDU completions before releasing the connection
Yehyeong Lee <[email protected]>
IB/iser: reject a remote invalidation of an unregistered direction
Ovidiu Panait <[email protected]>
arm64: dts: renesas: r9a09g087: Switch GBETH TX queue scheduling to WRR
Ovidiu Panait <[email protected]>
arm64: dts: renesas: r9a09g077: Switch GBETH TX queue scheduling to WRR
Ovidiu Panait <[email protected]>
arm64: dts: renesas: r9a09g047: Switch GBETH TX queue scheduling to WRR
Ovidiu Panait <[email protected]>
arm64: dts: renesas: r9a09g056: Switch GBETH TX queue scheduling to WRR
Ovidiu Panait <[email protected]>
arm64: dts: renesas: r9a09g057: Switch GBETH TX queue scheduling to WRR
Biju Das <[email protected]>
power: sequencing: Fix build issue with COMPILE_TEST
Or Har-Toov <[email protected]>
RDMA/uverbs: Fix mmap_lock/disassociation_lock circular dependency
Krystian Kaniewski <[email protected]>
RDMA/core: Reject unregistering netdevs in ib_get_eth_speed
Or Har-Toov <[email protected]>
RDMA/mlx5: Remove warn on missing representor in query_port_speed
Michael Bommarito <[email protected]>
RDMA/rxe: insert mcg into mcg_tree only after rxe_mcast_add() succeeds
Weiming Shi <[email protected]>
RDMA/rxe: Restore HMM_PFN_WRITE check in ODP write paths
Xixin Liu <[email protected]>
clk: scpi: register scpi-cpufreq once and clear on failure
Xixin Liu <[email protected]>
clk: scpi: bound-check DVFS index in scpi_dvfs_recalc_rate
Xixin Liu <[email protected]>
firmware: arm_scpi: reject DVFS OPP count above MAX_DVFS_OPPS
Cen Zhang (Microsoft Security FORGE Labs) <[email protected]>
xfrm: hold net_device reference under RCU in bundle creation
Gang Yan <[email protected]>
RDMA/rxe: Fix integer overflow in mr_check_range() leading to OOB access
Norbert Szetei <[email protected]>
RDMA/rxe: validate access flags before swapping the MR's PD
Guoqing Jiang <[email protected]>
RDMA/siw: Clear association under lock if siw_qp_modify fails in siw_accept
Pengpeng Hou <[email protected]>
ARM: socfpga: select the PL310 erratum 753970 workaround
Lucas Tanure <[email protected]>
arm64: dts: amlogic: t7: fix the pin groups of the vsync PWM
Lucas Tanure <[email protected]>
arm64: dts: amlogic: t7: khadas-vim4: add the PWM-driven supplies
Lucas Tanure <[email protected]>
arm64: dts: amlogic: t7: fix the pin groups of two PWM outputs
Lucas Tanure <[email protected]>
arm64: dts: amlogic: t7: khadas-vim4: allow the SD card to be power cycled
Lucas Tanure <[email protected]>
arm64: dts: amlogic: t7: use the real UART pclk
Maher Azzouzi <[email protected]>
esp: downgrade zerocopy managed frags before mutating skb frags
Eric Dumazet <[email protected]>
xfrm: add missing rcu_read_lock(), skb_dst_force() and dev_hold() for xfrm_trans_reinject()
Kyle Zeng <[email protected]>
xfrm: fix compat ALLOCSPI request use-after-free
Henry Martin <[email protected]>
xfrm: iptfs: fix runt reassembly panic from short inner tot_len
Aleksandr Nogikh <[email protected]>
xfrm: add missing RCU read lock in xfrm_send_migrate_state()
Roshan Kumar <[email protected]>
xfrm: iptfs: fix stack OOB read in iptfs_skb_reset_frag_walk()
Jens Axboe <[email protected]>
sunvdc: fix -EIO issue due to lack of retries
Günther Noack <[email protected]>
selftests/landlock: Add audit test for whiteout object creation
Günther Noack <[email protected]>
selftests/landlock: Add tests for whiteout object creation
Günther Noack <[email protected]>
selftests/landlock: Use an actual chardev for MAKE_CHAR audit test
-------------
Diffstat:
.../ABI/testing/sysfs-devices-platform-trackpoint | 2 +- .../arch/arm64/memory-tagging-extension.rst | 5 +- Documentation/hwmon/cgbc-hwmon.rst | 42 +- Documentation/netlink/specs/rt-neigh.yaml | 3 + Documentation/networking/ip-sysctl.rst | 4 +- Makefile | 4 +- arch/arm/mach-socfpga/Kconfig | 2 +- .../boot/dts/altera/socfpga_stratix10_socdk.dtsi | 0 .../dts/altera/socfpga_stratix10_socdk_emmc.dts | 0 .../boot/dts/amlogic/amlogic-t7-a311d2-an400.dts | 2 +- .../dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts | 113 +++- arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi | 44 +- arch/arm64/boot/dts/renesas/r8a779f0.dtsi | 1 + arch/arm64/boot/dts/renesas/r9a09g047.dtsi | 10 + arch/arm64/boot/dts/renesas/r9a09g056.dtsi | 10 + arch/arm64/boot/dts/renesas/r9a09g057.dtsi | 10 + arch/arm64/boot/dts/renesas/r9a09g077.dtsi | 27 + arch/arm64/boot/dts/renesas/r9a09g087.dtsi | 27 + arch/arm64/include/asm/percpu.h | 20 +- arch/arm64/kernel/hibernate-asm.S | 2 + arch/arm64/kernel/hibernate.c | 4 +- arch/arm64/kernel/mte.c | 2 +- arch/mips/Kconfig | 4 +- arch/mips/cavium-octeon/octeon-platform.c | 4 +- arch/powerpc/kernel/iommu.c | 2 +- arch/powerpc/kvm/book3s_hv_nested.c | 2 + arch/powerpc/kvm/book3s_hv_uvmem.c | 5 +- arch/x86/Kconfig.cpu | 11 + arch/x86/Makefile | 5 + arch/x86/entry/entry_fred.c | 11 +- arch/x86/include/asm/div64.h | 2 +- arch/x86/include/asm/text-patching.h | 4 +- arch/x86/kernel/alternative.c | 6 +- arch/x86/kernel/cpu/microcode/intel.c | 26 + arch/x86/kernel/kprobes/core.c | 5 +- drivers/ata/libahci.c | 15 +- drivers/ata/libahci_platform.c | 2 +- drivers/block/sunvdc.c | 9 +- drivers/bluetooth/btintel_pcie.c | 8 +- drivers/bluetooth/btmtk.c | 7 +- drivers/bluetooth/btmtksdio.c | 24 +- drivers/bluetooth/btmtkuart.c | 20 +- drivers/bluetooth/btusb.c | 17 + drivers/bluetooth/hci_qca.c | 14 +- drivers/clk/clk-scpi.c | 8 +- drivers/dma-buf/Kconfig | 2 +- drivers/dma-buf/dma-buf-mapping.c | 31 +- drivers/dma-buf/dma-fence.c | 14 +- drivers/dma/dmaengine.c | 10 +- drivers/dma/mmp_pdma.c | 5 +- drivers/dma/pxa_dma.c | 3 +- drivers/dma/sprd-dma.c | 3 +- drivers/dma/sun6i-dma.c | 9 +- drivers/dma/ti/k3-udma-glue.c | 5 +- drivers/dma/xilinx/xilinx_dma.c | 26 +- drivers/firmware/arm_scpi.c | 4 +- drivers/gpio/gpio-virtuser.c | 3 +- drivers/gpio/gpiolib-of.c | 6 +- drivers/gpio/gpiolib-shared.c | 9 +- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 + drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 145 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 43 +- drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c | 7 +- drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c | 2 +- .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 7 +- drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v10.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12.c | 61 +- drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v12_1.c | 70 +- drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v9.c | 6 +- drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c | 5 +- .../drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c | 13 +- drivers/gpu/drm/drm_atomic_uapi.c | 13 +- drivers/gpu/drm/gud/gud_pipe.c | 7 +- drivers/gpu/drm/i915/display/intel_cursor.c | 15 +- drivers/gpu/drm/i915/display/skl_universal_plane.c | 15 +- drivers/gpu/drm/msm/adreno/adreno_device.c | 2 +- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 2 + drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 1 + drivers/gpu/drm/msm/dp/dp_display.c | 21 +- drivers/gpu/drm/msm/dsi/dsi_host.c | 36 +- drivers/gpu/drm/msm/hdmi/hdmi_phy.c | 8 +- drivers/gpu/drm/msm/msm_drv.c | 2 +- drivers/gpu/drm/msm/msm_gem.h | 3 + drivers/gpu/drm/msm/msm_gem_vma.c | 2 +- drivers/gpu/drm/msm/msm_ringbuffer.c | 2 +- drivers/gpu/drm/msm/msm_ringbuffer.h | 1 + .../gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/fbsr.c | 2 +- .../gpu/drm/nouveau/nvkm/subdev/gsp/rm/r535/gsp.c | 8 +- .../gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/fbsr.c | 8 +- .../gpu/drm/nouveau/nvkm/subdev/gsp/rm/r570/gsp.c | 3 +- .../drm/nouveau/nvkm/subdev/gsp/rm/r570/nvrm/gsp.h | 8 + drivers/gpu/drm/nouveau/nvkm/subdev/gsp/rm/rm.h | 2 +- drivers/gpu/drm/scheduler/sched_entity.c | 8 +- drivers/gpu/drm/scheduler/sched_rq.c | 20 +- drivers/gpu/drm/ttm/ttm_bo.c | 2 +- drivers/gpu/drm/vc4/vc4_kms.c | 2 +- drivers/gpu/drm/xe/xe_i2c.c | 3 + drivers/gpu/drm/xe/xe_mmio_gem.c | 33 +- drivers/gpu/drm/xe/xe_mmio_gem.h | 2 +- drivers/gpu/drm/xe/xe_shrinker.c | 124 ++-- drivers/hwmon/cgbc-hwmon.c | 129 ++-- drivers/hwmon/gpio-fan.c | 4 +- drivers/hwmon/hp-wmi-sensors.c | 32 +- drivers/hwmon/pmbus/pmbus.h | 3 +- drivers/hwmon/pmbus/tps53679.c | 11 +- drivers/hwmon/pwm-fan.c | 13 +- drivers/hwmon/w83791d.c | 1 + drivers/hwmon/w83793.c | 4 +- drivers/i2c/busses/i2c-at91-core.c | 3 + drivers/i2c/busses/i2c-at91-master.c | 12 +- drivers/i2c/busses/i2c-at91.h | 1 + drivers/i2c/busses/i2c-imx.c | 3 + drivers/i2c/busses/i2c-qcom-cci.c | 20 +- drivers/i2c/i2c-atr.c | 1 + drivers/infiniband/core/iwpm_util.c | 9 +- drivers/infiniband/core/mad.c | 3 +- drivers/infiniband/core/rdma_core.c | 1 - drivers/infiniband/core/ucma.c | 7 +- drivers/infiniband/core/uverbs_flow.c | 1 + drivers/infiniband/core/uverbs_main.c | 25 +- drivers/infiniband/core/verbs.c | 12 +- drivers/infiniband/hw/bnxt_re/main.c | 10 +- drivers/infiniband/hw/bnxt_re/uapi.c | 6 +- drivers/infiniband/hw/efa/efa_com.c | 7 +- drivers/infiniband/hw/efa/efa_com.h | 1 + drivers/infiniband/hw/efa/efa_main.c | 35 +- drivers/infiniband/hw/erdma/erdma_main.c | 4 +- drivers/infiniband/hw/erdma/erdma_verbs.c | 18 +- drivers/infiniband/hw/hfi1/file_ops.c | 23 +- drivers/infiniband/hw/irdma/verbs.c | 2 +- drivers/infiniband/hw/mlx4/sysfs.c | 4 + drivers/infiniband/hw/mlx5/main.c | 7 +- drivers/infiniband/sw/rxe/rxe_mcast.c | 50 +- drivers/infiniband/sw/rxe/rxe_mr.c | 3 +- drivers/infiniband/sw/rxe/rxe_odp.c | 16 +- drivers/infiniband/sw/rxe/rxe_verbs.c | 13 +- drivers/infiniband/sw/siw/siw_cm.c | 7 +- drivers/infiniband/sw/siw/siw_qp_rx.c | 2 +- drivers/infiniband/ulp/ipoib/ipoib.h | 7 + drivers/infiniband/ulp/ipoib/ipoib_ib.c | 12 +- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 16 +- drivers/infiniband/ulp/iser/iser_initiator.c | 16 +- drivers/infiniband/ulp/isert/ib_isert.c | 22 + drivers/infiniband/ulp/isert/ib_isert.h | 2 + drivers/infiniband/ulp/rtrs/rtrs-clt-trace.h | 2 +- drivers/infiniband/ulp/rtrs/rtrs-clt.c | 8 + drivers/infiniband/ulp/rtrs/rtrs-clt.h | 2 + drivers/infiniband/ulp/rtrs/rtrs-srv-trace.h | 2 +- drivers/input/evdev.c | 2 + drivers/input/input-compat.c | 2 + drivers/input/joystick/xpad.c | 10 +- drivers/input/keyboard/adp5588-keys.c | 12 +- drivers/input/keyboard/atkbd.c | 8 + drivers/input/misc/soc_button_array.c | 16 +- drivers/input/mouse/synaptics.c | 8 + drivers/input/rmi4/rmi_driver.c | 13 + drivers/input/rmi4/rmi_smbus.c | 10 +- drivers/input/serio/hp_sdc.c | 2 +- drivers/input/serio/i8042-acpipnpio.h | 7 + drivers/input/touchscreen/cyttsp5.c | 1 + drivers/input/touchscreen/eeti_ts.c | 1 + drivers/memstick/core/ms_block.c | 2 + drivers/misc/ntsync.c | 3 + drivers/mmc/core/bus.c | 2 +- drivers/mmc/core/host.c | 1 + drivers/mmc/core/sdio_uart.c | 3 + drivers/mmc/host/mmc_hsq.c | 8 +- drivers/mmc/host/mmc_spi.c | 1 + drivers/mmc/host/mmci.c | 3 + drivers/mmc/host/mxcmmc.c | 4 + drivers/mmc/host/rtsx_pci_sdmmc.c | 5 + drivers/mmc/host/sdhci-of-aspeed.c | 5 +- drivers/mmc/host/sdhci_am654.c | 43 +- drivers/mmc/host/sh_mmcif.c | 3 +- drivers/net/dsa/mxl862xx/mxl862xx.c | 23 +- drivers/net/ethernet/airoha/airoha_ppe.c | 17 +- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 19 +- drivers/net/ethernet/cadence/macb_ptp.c | 9 + drivers/net/ethernet/cortina/gemini.c | 2 +- drivers/net/ethernet/intel/igc/igc_tsn.c | 6 +- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 7 +- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 3 +- drivers/net/ethernet/mediatek/mtk_ppe_offload.c | 17 +- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 2 +- drivers/net/ethernet/meta/fbnic/fbnic_txrx.c | 42 +- drivers/net/ethernet/meta/fbnic/fbnic_txrx.h | 9 +- drivers/net/ethernet/microchip/lan743x_main.c | 2 +- drivers/net/ethernet/sfc/falcon/tx.c | 8 +- drivers/net/ethernet/sfc/siena/tx.c | 8 +- drivers/net/ethernet/socionext/netsec.c | 2 + drivers/net/ethernet/stmicro/stmmac/hwif.h | 2 +- .../net/ethernet/stmicro/stmmac/stmmac_ethtool.c | 2 - drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c | 14 +- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 6 +- drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 99 ++- drivers/net/fddi/skfp/skfddi.c | 3 +- drivers/net/phy/mediatek/mtk-phy-lib.c | 27 +- drivers/net/wireless/ath/ath11k/mac.c | 25 +- drivers/net/wireless/ath/wcn36xx/dxe.c | 2 +- .../wireless/broadcom/brcm80211/brcmfmac/core.c | 2 + .../broadcom/brcm80211/brcmfmac/cyw/core.c | 5 +- .../broadcom/brcm80211/brcmsmac/mac80211_if.c | 4 + .../wireless/intel/ipw2x00/libipw_crypto_tkip.c | 12 +- drivers/net/wireless/intel/ipw2x00/libipw_rx.c | 6 + drivers/net/wireless/intel/iwlegacy/common.c | 2 +- drivers/net/wireless/intersil/p54/eeprom.c | 22 +- drivers/net/wireless/marvell/libertas_tf/main.c | 2 +- drivers/net/wireless/marvell/mwifiex/cfg80211.c | 12 +- drivers/net/wireless/marvell/mwifiex/pcie.c | 2 +- drivers/net/wireless/marvell/mwifiex/scan.c | 54 +- drivers/net/wireless/marvell/mwifiex/util.c | 10 +- drivers/net/wireless/microchip/wilc1000/cfg80211.c | 14 + drivers/net/wireless/microchip/wilc1000/wlan.c | 9 + drivers/net/wireless/rsi/rsi_91x_mgmt.c | 2 - drivers/net/wireless/ti/wlcore/main.c | 4 +- drivers/net/wireless/virtual/mac80211_hwsim_main.c | 39 +- drivers/net/wireless/virtual/virt_wifi.c | 4 +- drivers/net/wwan/mhi_wwan_mbim.c | 28 +- drivers/net/wwan/t7xx/t7xx_netdev.c | 4 + drivers/pci/controller/dwc/pci-imx6.c | 12 +- drivers/perf/arm-cmn.c | 10 +- drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c | 4 +- drivers/phy/mediatek/phy-mtk-hdmi-mt8195.h | 3 + drivers/phy/renesas/phy-rcar-gen3-usb2.c | 310 +++++++-- drivers/power/sequencing/Kconfig | 3 +- drivers/power/sequencing/core.c | 11 +- drivers/scsi/fnic/fdls_disc.c | 726 +++++++++++---------- drivers/scsi/fnic/fip.c | 117 ++-- drivers/scsi/fnic/fip.h | 2 +- drivers/scsi/fnic/fnic.h | 68 +- drivers/scsi/fnic/fnic_fcs.c | 126 ++-- drivers/scsi/fnic/fnic_isr.c | 41 +- drivers/scsi/fnic/fnic_main.c | 89 ++- drivers/scsi/fnic/fnic_scsi.c | 210 +++--- drivers/scsi/pm8001/pm8001_init.c | 6 +- drivers/scsi/qla2xxx/qla_os.c | 2 +- drivers/scsi/scsi.c | 24 +- drivers/soc/samsung/exynos-pmu.c | 7 +- drivers/soundwire/cadence_master.c | 7 + drivers/soundwire/dmi-quirks.c | 7 + drivers/spi/spi-fsl-qspi.c | 5 +- drivers/spi/spi-qpic-snand.c | 4 - drivers/spi/spi-virtio.c | 2 +- drivers/spi/spi-zynqmp-gqspi.c | 34 + drivers/watchdog/da9062_wdt.c | 4 +- drivers/watchdog/da9063_wdt.c | 4 +- drivers/watchdog/digicolor_wdt.c | 13 +- drivers/watchdog/msc313e_wdt.c | 16 +- drivers/watchdog/rtd119x_wdt.c | 7 +- drivers/watchdog/rzv2h_wdt.c | 7 +- drivers/watchdog/sp5100_tco.c | 6 +- drivers/watchdog/starfive-wdt.c | 2 +- fs/9p/vfs_addr.c | 28 +- fs/btrfs/dev-replace.c | 1 + fs/btrfs/disk-io.c | 4 + fs/btrfs/file.c | 4 +- fs/btrfs/free-space-tree.c | 14 +- fs/btrfs/inode.c | 18 +- fs/btrfs/super.c | 8 +- fs/btrfs/tree-checker.c | 2 +- fs/btrfs/verity.c | 18 +- fs/dax.c | 9 +- fs/exec.c | 29 +- fs/nfsd/export.c | 3 +- fs/ntfs/attrib.c | 259 ++++++-- fs/ntfs/attrib.h | 9 + fs/ntfs/attrlist.c | 224 ++++++- fs/ntfs/attrlist.h | 2 + fs/ntfs/compress.c | 2 +- fs/ntfs/file.c | 3 +- fs/ntfs/inode.c | 35 +- fs/ntfs/mft.c | 445 ++++++++++--- fs/ntfs/mft.h | 2 +- fs/ntfs/namei.c | 2 +- fs/ntfs/super.c | 12 +- fs/ntfs/volume.h | 12 +- fs/smb/client/cifssmb.c | 2 +- fs/smb/client/connect.c | 9 + fs/smb/client/file.c | 4 +- fs/smb/client/misc.c | 12 +- fs/smb/client/reparse.c | 58 +- fs/smb/client/reparse.h | 7 +- fs/smb/client/sess.c | 104 +-- fs/smb/client/smb2inode.c | 11 + fs/smb/client/smb2ops.c | 51 +- fs/smb/client/smb2pdu.c | 13 +- fs/smb/client/trace.h | 1 + fs/smb/server/connection.c | 84 ++- fs/smb/server/connection.h | 3 + fs/smb/server/mgmt/user_session.c | 199 ++++-- fs/smb/server/mgmt/user_session.h | 8 +- fs/smb/server/misc.h | 7 +- fs/smb/server/proc.c | 159 ++++- fs/smb/server/server.c | 9 +- fs/smb/server/smb2pdu.c | 126 ++-- fs/smb/server/smb2pdu.h | 3 +- fs/smb/server/smb_common.h | 2 +- fs/smb/server/stats.h | 58 +- fs/smb/server/vfs_cache.c | 26 +- fs/smb/server/vfs_cache.h | 1 + fs/super.c | 1 + include/keys/request_key_auth-type.h | 2 +- include/linux/dma-fence.h | 6 + include/linux/ieee80211-mesh.h | 4 +- include/linux/netdevice.h | 13 +- include/net/bluetooth/coredump.h | 2 + include/net/codel.h | 5 + include/net/codel_impl.h | 16 +- include/net/mac80211.h | 5 +- include/net/sock.h | 2 + include/rdma/uverbs_types.h | 2 - include/sound/soc.h | 3 +- include/sound/soc_sdw_utils.h | 31 +- include/trace/events/dma.h | 2 +- include/uapi/rdma/bnxt_re-abi.h | 2 +- kernel/cgroup/cgroup.c | 7 +- kernel/dma/coherent.c | 3 +- kernel/dma/swiotlb.c | 4 +- kernel/events/core.c | 4 + kernel/exit.c | 11 +- kernel/fork.c | 4 +- kernel/sched/core.c | 9 +- kernel/sched/ext/ext.c | 27 +- kernel/sched/ext/idle.c | 11 +- kernel/signal.c | 117 +++- kernel/time/jiffies.c | 2 +- kernel/time/posix-cpu-timers.c | 40 +- mm/filemap.c | 2 +- mm/huge_memory.c | 86 ++- mm/memblock.c | 18 +- mm/memcontrol.c | 2 +- mm/mlock.c | 2 +- mm/mremap.c | 9 +- mm/shrinker.c | 2 + mm/swapfile.c | 2 +- mm/vma.c | 6 +- net/atm/pppoatm.c | 42 +- net/bluetooth/coredump.c | 65 +- net/bluetooth/eir.c | 10 +- net/bluetooth/hci_codec.c | 36 +- net/bluetooth/hci_conn.c | 21 + net/bluetooth/hci_core.c | 18 +- net/bluetooth/hci_sync.c | 2 + net/bluetooth/iso.c | 53 +- net/bluetooth/rfcomm/sock.c | 13 +- net/bridge/br_mst.c | 20 +- net/bridge/br_vlan.c | 31 +- net/core/dev.c | 110 +++- net/core/drop_monitor.c | 18 +- net/core/neighbour.c | 35 +- net/core/skbuff.c | 32 +- net/core/sock.c | 16 +- net/ipv4/esp4.c | 6 + net/ipv4/icmp.c | 17 +- net/ipv4/ip_tunnel_core.c | 16 +- net/ipv4/sysctl_net_ipv4.c | 4 +- net/ipv4/tcp_input.c | 3 +- net/ipv4/tcp_ulp.c | 4 + net/ipv6/esp6.c | 6 + net/ipv6/seg6_local.c | 3 + net/ipv6/tcp_ipv6.c | 3 +- net/ipv6/xfrm6_output.c | 10 +- net/mac80211/cfg.c | 18 +- net/mac80211/debugfs.c | 2 +- net/mac80211/debugfs_netdev.c | 9 + net/mac80211/ieee80211_i.h | 2 +- net/mac80211/iface.c | 39 +- net/mac80211/main.c | 4 + net/mac80211/mesh.c | 34 +- net/mac80211/offchannel.c | 7 + net/mac80211/pm.c | 8 +- net/mac80211/scan.c | 2 +- net/mac80211/tdls.c | 40 +- net/mac80211/tx.c | 107 +-- net/netfilter/nf_flow_table_core.c | 12 +- net/netfilter/nf_flow_table_path.c | 7 +- net/netfilter/nf_nat_core.c | 46 +- net/netfilter/nf_tables_api.c | 22 +- net/netfilter/nft_nat.c | 2 +- net/netlink/af_netlink.c | 42 +- net/netlink/diag.c | 18 +- net/openvswitch/conntrack.c | 2 +- net/packet/af_packet.c | 4 +- net/packet/internal.h | 2 +- net/psp/psp_sock.c | 4 + net/rds/ib_cm.c | 2 +- net/sched/act_api.c | 11 +- net/sched/sch_hhf.c | 9 +- net/sched/sch_mqprio.c | 4 +- net/sched/sch_mqprio_lib.c | 7 +- net/sched/sch_taprio.c | 26 +- net/unix/garbage.c | 17 +- net/wireless/core.c | 150 +++-- net/wireless/core.h | 16 +- net/wireless/ibss.c | 38 +- net/wireless/rdev-ops.h | 3 + net/wireless/reg.c | 2 +- net/wireless/scan.c | 43 +- net/wireless/util.c | 38 +- net/xfrm/espintcp.c | 6 +- net/xfrm/xfrm_input.c | 22 +- net/xfrm/xfrm_iptfs.c | 12 +- net/xfrm/xfrm_policy.c | 20 +- net/xfrm/xfrm_state.c | 9 +- net/xfrm/xfrm_user.c | 18 +- rust/kernel/net/phy.rs | 38 +- scripts/generate_rust_target.rs | 5 + security/keys/encrypted-keys/encrypted.c | 20 +- security/keys/gc.c | 4 +- security/keys/request_key_auth.c | 12 +- security/keys/trusted-keys/trusted_tpm2.c | 12 +- security/selinux/avc.c | 5 +- security/selinux/hooks.c | 158 ++++- security/selinux/include/objsec.h | 10 +- sound/core/init.c | 3 +- sound/core/pcm_timer.c | 7 +- sound/hda/common/controller.c | 2 +- sound/soc/amd/acp/acp-sdw-legacy-mach.c | 16 +- sound/soc/amd/acp/acp-sdw-sof-mach.c | 21 +- sound/soc/codecs/cs-amp-lib.c | 2 + sound/soc/codecs/hdmi-codec.c | 6 +- sound/soc/codecs/rt712-sdca-dmic.c | 14 +- sound/soc/intel/boards/sof_sdw.c | 2 +- sound/soc/sdw_utils/soc_sdw_bridge_cs35l56.c | 4 +- sound/soc/sdw_utils/soc_sdw_utils.c | 9 +- sound/soc/soc-pcm.c | 18 +- sound/soc/ux500/ux500_msp_i2s.h | 4 +- sound/usb/6fire/comm.c | 42 +- sound/usb/6fire/comm.h | 2 +- sound/usb/6fire/midi.c | 43 +- sound/usb/6fire/midi.h | 2 +- sound/usb/6fire/pcm.c | 138 ++-- sound/usb/6fire/pcm.h | 5 +- sound/usb/bcd2000/bcd2000.c | 33 +- sound/usb/card.h | 1 + sound/usb/endpoint.c | 12 +- sound/virtio/virtio_card.c | 4 +- tools/objtool/Makefile | 8 +- .../selftests/arm64/mte/check_gcr_el1_cswitch.c | 2 +- tools/testing/selftests/landlock/fs_test.c | 197 +++++- 442 files changed, 6831 insertions(+), 2723 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/438 selftests/landlock: Use an actual chardev for MAKE_CHAR audit test
7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Günther Noack <[email protected]>
[ Upstream commit 173b1bd8730825e1f6862dbd07856e7d68447a41 ]
By passing a (0, 0) device number, the audit test for LANDLOCK_ACCESS_FS_MAKE_CHAR was accidentally creating a whiteout object rather than a char device. In preparation to treating whiteout objects differently, use an actual character device instead.
--- tools/testing/selftests/landlock/fs_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/landlock/fs_test.c +1 -1
@@ -7436,7 +7436,7 @@ TEST_F(audit_layout1, make_char)enforce_fs (_metadata,ACCESS_ALL ,NULL ); -EXPECT_EQ (-1 ,mknod (file1_s1d3,S_IFCHR |0644 ,0 )); +EXPECT_EQ (-1 ,mknod (file1_s1d3,S_IFCHR |0644 ,makedev (7 ,0 )));EXPECT_EQ (EACCES , errno);EXPECT_EQ (0 ,matches_log_fs (_metadata, self->audit_fd,"fs\\.make_char" , dir_s1d3));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 2/438 selftests/landlock: Add tests for whiteout object creation
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Günther Noack <[email protected]>
[ Upstream commit ee890889b30b22f9a21636061def7a04e4f89380 ]
Add tests to check that whiteout object creation is guarded by LANDLOCK_ACCESS_FS_MAKE_REG, in the cases where these are created from userspace:
* Conventional creation with mknod()
* Linking or renaming an existing whiteout object
* renameat2() with RENAME_WHITEOUT,
which creates a new whiteout object in the source location
* renameat2() with RENAME_EXCHANGE,
with one of the renamed objects being a whiteout object
--- tools/testing/selftests/landlock/fs_test.c | 176 +++++++++++++++++++++ 1 file changed, 176 insertions(+)
tools/testing/selftests/landlock/fs_test.c +176 -0
@@ -2247,6 +2247,170 @@ TEST_F_FORK(layout1, rename_file) RENAME_EXCHANGE)); } +TEST_F_FORK(layout1, rename_whiteout_denied) +{ +/* The affected file is a FIFO. */ +ASSERT_EQ (0 ,unlink (file1_s3d3)); +ASSERT_EQ (0 ,mknod (file1_s3d3,S_IFIFO |0600 ,0 )); + +/* Deny MAKE_REG, but allow MAKE_FIFO. */ +enforce_fs (_metadata,LANDLOCK_ACCESS_FS_MAKE_REG ,NULL ); + +/* +* Try to rename a file with RENAME_WHITEOUT. +* file1_s3d3 is in dir_s3d2 (tmpfs), so it supports RENAME_WHITEOUT. +* Denied, because whiteout creation is guarded with MAKE_REG. +*/ +EXPECT_EQ (-1 ,renameat2 (AT_FDCWD , file1_s3d3,AT_FDCWD , +TMP_DIR "/s3d1/s3d2/s3d3/f2" ,RENAME_WHITEOUT )); +EXPECT_EQ (EACCES , errno); +} + +static bool is_whiteout (const char *const path) +{ +struct stat st; + +if (stat (path, &st) ==-1 ) +return false; + +return S_ISCHR (st.st_mode) && st.st_rdev ==makedev (0 ,0 ); +} + +static bool is_fifo (const char *const path) +{ +struct stat st; + +return stat (path, &st) ==0 &&S_ISFIFO (st.st_mode); +} + +TEST_F_FORK(layout1, rename_whiteout_allowed) +{ +const struct rule rules[] = { + { + .path = dir_s3d3, + .access =LANDLOCK_ACCESS_FS_MAKE_REG , + }, + {}, + }; + +/* The affected file is a FIFO. */ +ASSERT_EQ (0 ,unlink (file1_s3d3)); +ASSERT_EQ (0 ,mknod (file1_s3d3,S_IFIFO |0600 ,0 )); + +/* Allow MAKE_REG below dir_s3d3. */ +enforce_fs (_metadata,LANDLOCK_ACCESS_FS_MAKE_REG , rules); + +/* +* Rename a file with RENAME_WHITEOUT within the same directory. +* Allowed, because MAKE_REG is granted for the whiteout object which +* gets created in the source location. +*/ +EXPECT_EQ (0 ,renameat2 (AT_FDCWD , file1_s3d3,AT_FDCWD , +TMP_DIR "/s3d1/s3d2/s3d3/f2" ,RENAME_WHITEOUT )); + +/* A whiteout object took the place of the moved FIFO. */ +EXPECT_TRUE (is_whiteout (file1_s3d3)); +EXPECT_TRUE (is_fifo (TMP_DIR "/s3d1/s3d2/s3d3/f2" )); +} + +TEST_F_FORK(layout1, rename_whiteout_reparenting) +{ +const struct rule rules[] = { + { + .path = dir_s3d2, + .access =LANDLOCK_ACCESS_FS_REFER , + }, + { + .path = dir_s3d3, + .access =LANDLOCK_ACCESS_FS_MAKE_REG , + }, + {}, + }; + +/* The moved files are FIFOs. */ +ASSERT_EQ (0 ,unlink (file1_s3d3)); +ASSERT_EQ (0 ,mknod (file1_s3d3,S_IFIFO |0600 ,0 )); +ASSERT_EQ (0 ,unlink (file1_s3d4)); +ASSERT_EQ (0 ,mknod (file1_s3d4,S_IFIFO |0600 ,0 )); + +/* Allow REFER below dir_s3d2, but MAKE_REG only below dir_s3d3. */ +enforce_fs (_metadata, +LANDLOCK_ACCESS_FS_MAKE_REG |LANDLOCK_ACCESS_FS_REFER , + rules); + +/* +* The whiteout object is created in the source directory: Moving the +* FIFO out of dir_s3d4 is denied because MAKE_REG is not granted +* there, even though it is granted in the destination directory +* dir_s3d3. +*/ +EXPECT_EQ (-1 ,renameat2 (AT_FDCWD , file1_s3d4,AT_FDCWD , +TMP_DIR "/s3d1/s3d2/s3d3/f2" ,RENAME_WHITEOUT )); +EXPECT_EQ (EACCES , errno); + +/* +* Moving the FIFO out of dir_s3d3 is allowed, because MAKE_REG is +* granted there for the created whiteout object. +*/ +EXPECT_EQ (0 ,renameat2 (AT_FDCWD , file1_s3d3,AT_FDCWD , +TMP_DIR "/s3d1/s3d2/s3d4/f2" ,RENAME_WHITEOUT )); + +/* A whiteout object took the place of the moved FIFO. */ +EXPECT_TRUE (is_whiteout (file1_s3d3)); +EXPECT_TRUE (is_fifo (TMP_DIR "/s3d1/s3d2/s3d4/f2" )); +} + +TEST_F_FORK(layout1, rename_whiteout_exchange) +{ +const char *const whiteout_s3d3 =TMP_DIR "/s3d1/s3d2/s3d3/f2" ; +const struct rule rules[] = { + { + .path = dir_s3d2, + .access =LANDLOCK_ACCESS_FS_REFER , + }, + { + .path = dir_s3d3, + .access =LANDLOCK_ACCESS_FS_MAKE_REG , + }, + {}, + }; + +/* The exchanged files are FIFOs and an existing whiteout object. */ +ASSERT_EQ (0 ,unlink (file1_s3d3)); +ASSERT_EQ (0 ,mknod (file1_s3d3,S_IFIFO |0600 ,0 )); +ASSERT_EQ (0 ,mknod (whiteout_s3d3,S_IFCHR |0600 ,makedev (0 ,0 ))); +ASSERT_EQ (0 ,unlink (file1_s3d4)); +ASSERT_EQ (0 ,mknod (file1_s3d4,S_IFIFO |0600 ,0 )); + +/* Allow REFER below dir_s3d2, but MAKE_REG only below dir_s3d3. */ +enforce_fs (_metadata, +LANDLOCK_ACCESS_FS_MAKE_REG |LANDLOCK_ACCESS_FS_REFER , + rules); + +/* +* With RENAME_EXCHANGE, the whiteout object moves into the source +* directory of the rename: Exchanging the FIFO in dir_s3d4 with the +* whiteout object is denied because MAKE_REG is not granted in +* dir_s3d4, even though it is granted in the whiteout object's own +* directory dir_s3d3. +*/ +EXPECT_EQ (-1 ,renameat2 (AT_FDCWD , file1_s3d4,AT_FDCWD , whiteout_s3d3, +RENAME_EXCHANGE )); +EXPECT_EQ (EACCES , errno); + +/* +* Exchanging the FIFO in dir_s3d3 with the whiteout object is +* allowed, because MAKE_REG is granted in the directory into which +* the whiteout object moves. +*/ +EXPECT_EQ (0 ,renameat2 (AT_FDCWD , file1_s3d3,AT_FDCWD , whiteout_s3d3, +RENAME_EXCHANGE )); + +/* The FIFO and the whiteout object swapped places. */ +EXPECT_TRUE (is_whiteout (file1_s3d3)); +EXPECT_TRUE (is_fifo (whiteout_s3d3)); +} + TEST_F_FORK(layout1, rename_dir) {const struct rule rules[] = {
@@ -3270,6 +3434,18 @@ TEST_F_FORK(layout1, make_char) makedev(1, 3)); } +TEST_F_FORK(layout1, make_whiteout) +{ +/* +* Creates a whiteout object (creation guarded by MAKE_REG). +* +* Contrary to the other character devices, this does not require +* CAP_MKNOD, cf. vfs_mknod(). +*/ +test_make_file (_metadata,LANDLOCK_ACCESS_FS_MAKE_REG ,S_IFCHR , +makedev (0 ,0 )); +} + TEST_F_FORK(layout1, make_block) {/* Creates a /dev/loop0 device. */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 3/438 selftests/landlock: Add audit test for whiteout object creation
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Günther Noack <[email protected]>
[ Upstream commit 8c46c6acbebe0d8544fd1b55e5ddf36828d7b9ea ]
Add audit_layout1.make_whiteout: This test looks similar to audit_layout1.make_char, but creates a whiteout object through mknod(). Since whiteout object creation is now guarded with LANDLOCK_ACCESS_FS_MAKE_REG rather than LANDLOCK_ACCESS_FS_MAKE_CHAR, it also needs to log the matching denial to audit.
--- tools/testing/selftests/landlock/fs_test.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
tools/testing/selftests/landlock/fs_test.c +19 -0
@@ -7622,6 +7622,25 @@ TEST_F(audit_layout1, make_char)EXPECT_EQ (1 , records.domain); } +TEST_F(audit_layout1, make_whiteout) +{ +struct audit_records records; + +EXPECT_EQ (0 ,unlink (file1_s1d3)); + +enforce_fs (_metadata,ACCESS_ALL ,NULL ); + +/* Whiteout creation is denied and logged as fs.make_reg. */ +EXPECT_EQ (-1 ,mknod (file1_s1d3,S_IFCHR |0644 ,makedev (0 ,0 ))); +EXPECT_EQ (EACCES , errno); +EXPECT_EQ (0 ,matches_log_fs (_metadata, self->audit_fd,"fs\\.make_reg" , + dir_s1d3)); + +EXPECT_EQ (0 ,audit_count_records (self->audit_fd, &records)); +EXPECT_EQ (0 , records.access); +EXPECT_EQ (1 , records.domain); +} + TEST_F(audit_layout1, make_dir) {struct audit_records records;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 4/438 sunvdc: fix -EIO issue due to lack of retries
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jens Axboe <[email protected]>
[ Upstream commit 5067d4ba713961d8ccea1e06cd4c453793f3121e ]
John reports that since commit:
a11f6ca9aef9 ("sunvdc: Do not spin in an infinite loop when vio_ldc_send() returns EAGAIN")
users of Linux inside Solaris ldom see occasional -EIO errors because the request send loop now times out. The current loop does 10 retries, and inside vio_ldc_send() a further 1000 1usec retries are done as well. Even with 10.5 msec of busy loop retries that's apparently not enough to always succeed.
Rather than introduce continued busy looping, requeue the request and have the delayed queue kicking retry the request after another 10ms. This obviously isn't ideal, but there's seemingly no way to wait for this type of event. And if 10ms of busy looping was not enough to make progress, then presumably this is an edge condition and we just need to guarantee to make forward progress at some later point in time. That's more suitably done through letting the CPU tend to other work, rather than sitting in a tight loop retrying.
[stian: rebased on top of the cookie-unmap fix, without which every
requeued attempt leaks LDC map table entries; tested on an UltraSPARC T4 LDOM where the vdc_tx_trigger failure condition was reproduced and absorbed by the requeue with no I/O error]
--- drivers/block/sunvdc.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/block/sunvdc.c +8 -1
@@ -556,6 +556,7 @@ static blk_status_t vdc_queue_rq(struct blk_mq_hw_ctx *hctx,struct vdc_port *port = hctx->queue->queuedata;struct vio_dring_state *dr;unsigned long flags; +int ret; dr = &port->vio.drings[VIO_DRIVER_TX_RING ];
@@ -577,7 +578,13 @@ static blk_status_t vdc_queue_rq(struct blk_mq_hw_ctx *hctx,return BLK_STS_DEV_RESOURCE ; } -if (__send_request (bd->rq) <0 ) { + ret =__send_request (bd->rq); +if (ret == -EAGAIN ) { +spin_unlock_irqrestore (&port->vio.lock, flags); +/* already spun for 10msec, defer 10msec and retry */ +blk_mq_delay_kick_requeue_list (hctx->queue,10 ); +return BLK_STS_DEV_RESOURCE ; + }else if (ret <0 ) {spin_unlock_irqrestore (&port->vio.lock, flags);return BLK_STS_IOERR ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 5/438 xfrm: iptfs: fix stack OOB read in iptfs_skb_reset_frag_walk()
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Roshan Kumar <[email protected]>
[ Upstream commit d042487dc118e494db2e2c1382310255c90ff544 ]
iptfs_skb_reset_frag_walk() advances to the fragment containing @offset with an unbounded loop:
while (offset >= walk->past + walk->frags[walk->fragi].len) walk->past += walk->frags[walk->fragi++].len;
walk->fragi is advanced and walk->frags[walk->fragi] is dereferenced without ever checking fragi against walk->nr_frags. When the requested offset is at or beyond the total length spanned by the walk's fragments, fragi runs past nr_frags and off the end of the fixed-size on-stack frags[MAX_SKB_FRAGS + 1] array, reading out-of-bounds stack memory.
The two callers behave differently: iptfs_skb_add_frags() already guards against this with
if (!walk->nr_frags || offset >= walk->total + walk->initial_offset) return len;
but iptfs_skb_can_add_frags() has no such guard and calls iptfs_skb_reset_frag_walk() unconditionally, so it performs the out-of-range walk. Its own "fragi < walk->nr_frags" bound check runs only afterwards, too late to prevent the read.
This is reachable from the receive path: a crafted IP-TFS (AGGFRAG) payload delivered to an IPTFS SA drives iptfs_reassem_cont() -> iptfs_skb_can_add_frags() with an offset past the fragment total, e.g.:
BUG: KASAN: stack-out-of-bounds in iptfs_skb_reset_frag_walk+0x235/0x250 Read of size 4 at addr ffff888008ad7210 by task repro/345 iptfs_skb_reset_frag_walk+0x235/0x250 net/xfrm/xfrm_iptfs.c:392 iptfs_skb_can_add_frags+0x155/0x310 net/xfrm/xfrm_iptfs.c:420 iptfs_reassem_cont+0xcf8/0x1140 net/xfrm/xfrm_iptfs.c:902 iptfs_input_ordered+0x552/0x670 net/xfrm/xfrm_iptfs.c:1280 iptfs_input+0x3d6/0xde0 net/xfrm/xfrm_iptfs.c:1741 xfrm_input+0x282f/0x6140 net/xfrm/xfrm_input.c:700 xfrm4_esp_rcv+0x93/0x120 net/ipv4/xfrm4_protocol.c:104 ip_rcv+0x278/0x2d0 net/ipv4/ip_input.c:612
Give iptfs_skb_can_add_frags() the same up-front guard that iptfs_skb_add_frags() already has, so the walk is never entered with an out-of-range offset. When it triggers, the caller falls back to the existing linearize-and-copy path, which is safe.
--- net/xfrm/xfrm_iptfs.c | 8 ++++++++ 1 file changed, 8 insertions(+)
net/xfrm/xfrm_iptfs.c +8 -0
@@ -416,6 +416,14 @@ static bool iptfs_skb_can_add_frags(const struct sk_buff *skb,if (skb_has_frag_list (skb) || skb->pp_recycle != walk->pp_recycle)return false; +/* Reject an @offset that is at or beyond the end of the walk's data +* before calling iptfs_skb_reset_frag_walk(), whose fragment-advance +* loop is otherwise unbounded and would index past walk->frags[]. +* This mirrors the guard already present in iptfs_skb_add_frags(). +*/ +if (!walk->nr_frags || offset >= walk->total + walk->initial_offset) +return false; +/* Make offset relative to current frag after setting that */ offset =iptfs_skb_reset_frag_walk (walk, offset);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 6/438 xfrm: add missing RCU read lock in xfrm_send_migrate_state()
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aleksandr Nogikh <[email protected]>
[ Upstream commit 42d100f5232f39b8ea7b00a7c2482325c7f032a4 ]
xfrm_nlmsg_multicast() requires the RCU read lock to be held because it safely dereferences the net->xfrm.nlsk pointer using rcu_dereference(). When it is called from xfrm_send_migrate_state(), the RCU read lock is not held, which triggers a suspicious RCU usage warning:
WARNING: suspicious RCU usagenet/xfrm/xfrm_user.c:1630 suspicious rcu_dereference_check() usage!
Call Trace: lockdep_rcu_suspicious+0x13f/0x1d0 kernel/locking/lockdep.c:6876 xfrm_nlmsg_multicast+0x1d8/0x1f0 net/xfrm/xfrm_user.c:1630 xfrm_send_migrate_state+0x870/0xae0 net/xfrm/xfrm_user.c:3340 xfrm_do_migrate_state+0x1749/0x1e90 net/xfrm/xfrm_user.c:3507 xfrm_user_rcv_msg+0x7a8/0xf30 net/xfrm/xfrm_user.c:3907
Fix this by wrapping the xfrm_nlmsg_multicast() call in xfrm_send_migrate_state() with rcu_read_lock() and rcu_read_unlock().
--- net/xfrm/xfrm_user.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
net/xfrm/xfrm_user.c +5 -1
@@ -3337,7 +3337,11 @@ static int xfrm_send_migrate_state(struct net *net,return err; } -return xfrm_nlmsg_multicast (net, skb,0 ,XFRMNLGRP_MIGRATE ); +rcu_read_lock (); + err =xfrm_nlmsg_multicast (net, skb,0 ,XFRMNLGRP_MIGRATE ); +rcu_read_unlock (); + +return err; } static int xfrm_do_migrate_state(struct sk_buff *skb, struct nlmsghdr *nlh,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 7/438 xfrm: iptfs: fix runt reassembly panic from short inner tot_len
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Henry Martin <[email protected]>
[ Upstream commit dc33262be1fe43d0eb0b84fb58c6ed42e2f64a8c ]
When the start of an inner packet is split across two outer packets such that fewer than 4 bytes land at the end of the first one, __input_process_payload() saves those bytes as a runt and skips the iplen/iphlen validation performed for in-place packets. When the continuation packet arrives, iptfs_reassem_cont() only requires the declared inner length to be >= sizeof(ra_runt) (6) before allocating the reassembly skb with that attacker-controlled length.
However, __iptfs_iphlen() always returns the fixed minimum IP header size (20 for IPv4, 40 for IPv6), so for an inner IPv4 tot_len in [6, 19] the header-completion copy writes past the declared packet length, and the subsequent "ipremain -= copylen" underflows to ~4GB, leaving the payload copy length bounded only by blkoff (up to 64KB). At runtime the skb_put() tailroom check turns this into skb_over_panic(), i.e. an unprivileged kernel panic (DoS), reachable locally via userns+netns IPTFS SAs and remotely against IPTFS VPN gateways when the decrypted outer skb is linear (e.g. AF_PACKET taps, tun/tap delivery).
Align the runt path with the normal path by requiring the declared inner length to cover at least the IP header size. This also subsumes the previous >= sizeof(ra_runt) check, since the minimum IP header is always larger than the runt buffer.
This issue was found by the autokbug dynamic kernel fuzzer at Tencent Yunding Lab.
--- net/xfrm/xfrm_iptfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/xfrm/xfrm_iptfs.c +2 -2
@@ -828,8 +828,8 @@ static u32 iptfs_reassem_cont(struct xfrm_iptfs_data *xtfs, u64 seq,* allocate an in progress skb */ ipremain =__iptfs_iplen (xtfs->ra_runt); -if (ipremain <sizeof (xtfs->ra_runt)) { -/* length has to be at least runtsize large */ +if (ipremain <__iptfs_iphlen (xtfs->ra_runt)) { +/* length has to be at least the IP header size */ XFRM_INC_STATS (xs_net (xtfs->x),LINUX_MIB_XFRMINIPTFSERROR ); goto abandon;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 8/438 xfrm: fix compat ALLOCSPI request use-after-free
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kyle Zeng <[email protected]>
[ Upstream commit d1ebd9081879fd9ae9c8fb7e8928f19cc88ae320 ]
xfrm_state_netlink() builds the ALLOCSPI response with dump_one_state(), which already calls alloc_compat() with the response skb and header.
xfrm_alloc_userspi() then calls alloc_compat() again, but passes the original request skb and its header. For a compat request, the translator therefore interprets the 228-byte compat xfrm_userspi_info as the 232-byte native layout and reads four bytes past the declared payload. It also publishes the translated child through the request's frag_list.
A multicast clone of the request shares skb_shared_info and can observe that child. xfrm_user_rcv_msg() frees it after the request handler returns, racing a compat receiver which may still be copying from it and resulting in a use-after-free.
Remove the redundant conversion. The response keeps its correct compat translation from dump_one_state(), and no child is attached to the inbound request.
--- net/xfrm/xfrm_user.c | 12 ------------ 1 file changed, 12 deletions(-)
net/xfrm/xfrm_user.c +0 -12
@@ -1877,7 +1877,6 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,struct net *net =sock_net (skb->sk);struct xfrm_state *x;struct xfrm_userspi_info *p; -struct xfrm_translator *xtr;struct sk_buff *resp_skb;xfrm_address_t *daddr;int family;
@@ -1943,17 +1942,6 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh, goto out; } - xtr =xfrm_get_translator (); -if (xtr) { - err = xtr->alloc_compat (skb,nlmsg_hdr (skb)); - -xfrm_put_translator (xtr); -if (err) { -kfree_skb (resp_skb); - goto out; - } - } - err =nlmsg_unicast (xfrm_net_nlsk (net, skb), resp_skb,NETLINK_CB (skb).portid); out:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 9/438 xfrm: add missing rcu_read_lock(), skb_dst_force() and dev_hold() for xfrm_trans_reinject()
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit d2f5082f9e84653fa1a9e8aebaaff23e688f5e19 ]
syzbot reported a suspicious RCU usage warning in ip6_pkt_drop():
WARNING: suspicious RCU usage in ip6_pkt_drop include/net/addrconf.h:389 suspicious rcu_dereference_check() usage!
Call Trace: __in6_dev_get_safely include/net/addrconf.h:389 [inline] ip6_pkt_drop+0x596/0x610 net/ipv6/route.c:4620 ip6_pkt_discard+0x1c/0x30 net/ipv6/route.c:4651 xfrm_trans_reinject+0x324/0x630 net/xfrm/xfrm_input.c:806 process_one_work kernel/workqueue.c:3322 [inline] process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3405 worker_thread+0xa47/0xfb0 kernel/workqueue.c:3486
When commit 4f4920669d21 ("xfrm: Reinject transport-mode packets through workqueue") converted xfrm_trans_reinject from a tasklet to a workqueue, the reinjection loop ceased running in softirq context. Workqueue workers run in process context where local_bh_disable() does not enter an RCU read-side critical section under CONFIG_PREEMPT_RCU.
Because finish callbacks (such as ip6_rcv_finish) expect to run under an RCU read lock (performing route lookups, l3mdev lookups, and accessing RCU-protected data structures), invoking them in workqueue context without rcu_read_lock() triggers RCU lockdep warnings.
Furthermore, packets queued to the workqueue via xfrm_trans_queue_net() may carry non-refcounted (noref) dst entries (e.g. from ip_route_input_noref). Additionally, on netdevice unregistration, dst_dev_put() replaces dst->dev with blackhole_netdev, so dst entries do not keep skb->dev alive while queued in the workqueue.
Fix these issues by:
1. Calling skb_dst_force(skb) in xfrm_trans_queue_net() while still in the caller's RCU section to ensure dst is reference-counted before queuing.
2. Holding a reference on skb->dev via dev_hold()/dev_put() across workqueue deferral so skb->dev remains valid during finish() callback processing.
3. Acquiring rcu_read_lock() around the finish callback invocation loop in xfrm_trans_reinject().
--- net/xfrm/xfrm_input.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
net/xfrm/xfrm_input.c +11 -0
@@ -800,12 +800,17 @@ static void xfrm_trans_reinject(struct work_struct *work)spin_unlock_bh (&trans->queue_lock);local_bh_disable (); +rcu_read_lock ();while ((skb =__skb_dequeue (&queue))) {struct net *net =XFRM_TRANS_SKB_CB (skb)->net; +struct net_device *dev = skb->dev;XFRM_TRANS_SKB_CB (skb)->finish (net,NULL , skb); +if (dev) +dev_put (dev);put_net (net); } +rcu_read_unlock ();local_bh_enable (); }
@@ -821,12 +826,18 @@ int xfrm_trans_queue_net(struct net *net, struct sk_buff *skb,if (skb_queue_len (&trans->queue) >=READ_ONCE (net_hotdata.max_backlog))return -ENOBUFS ; +if (skb_dst (skb) && !skb_dst_force (skb)) +return -EHOSTUNREACH ; +BUILD_BUG_ON (sizeof (struct xfrm_trans_cb ) >sizeof (skb->cb)); hold_net =maybe_get_net (net);if (!hold_net)return -ENODEV ; +if (skb->dev) +dev_hold (skb->dev); +XFRM_TRANS_SKB_CB (skb)->finish = finish;XFRM_TRANS_SKB_CB (skb)->net = hold_net;spin_lock_bh (&trans->queue_lock);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 10/438 esp: downgrade zerocopy managed frags before mutating skb frags
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maher Azzouzi <[email protected]>
[ Upstream commit f89416eb3db151170a6f3c6dfc5239d26cdce4d2 ]
On the out-of-place output path (esp->inplace == false) ESP rewrites the skb frag array: esp_output_head() appends a trailer frag and esp_output_tail() replaces the frags with a destination page, both referenced with get_page().
When the skb carries zerocopy managed frags (SKBFL_MANAGED_FRAG_REFS) the payload frags are owned by the ubuf and must not be referenced or unreferenced individually, but ESP mutates the frag array without ever downgrading the skb. This breaks the managed-frag invariant two ways:
- esp_ssg_unref() walks the source scatterlist and drops a page reference for every frag, including the ubuf-owned payload frags, pushing their refcount below the GUP pin bias while the pages are still pinned, i.e. a use-after-free of the zerocopy pages;
- esp_output_tail() installs its destination page as frag 0 with get_page() but leaves SKBFL_MANAGED_FRAG_REFS set, so skb_release_data() takes the skip_unref branch and never drops that reference, leaking the x->xfrag page at packet rate.
Fix this the way every other frag-mutating site does (__ip_append_data(), __ip6_append_data(), tcp_sendmsg_locked()) and call skb_zcopy_downgrade_managed() before ESP touches the frag array: it takes a real reference on each existing frag and clears SKBFL_MANAGED_FRAG_REFS, so the per-frag unref in esp_ssg_unref() and the frag release in skb_release_data() are both balanced and no mixed-ownership frag array is left behind.
--- net/ipv4/esp4.c | 6 ++++++ net/ipv6/esp6.c | 6 ++++++ 2 files changed, 12 insertions(+)
net/ipv4/esp4.c +6 -0
@@ -441,6 +441,12 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info * esp->inplace = false; +/* Take real page refs and clear SKBFL_MANAGED_FRAG_REFS before +* we mutate the frag array, so the per-frag unref stays balanced +* for zerocopy managed frags (see __ip_append_data()). +*/ +skb_zcopy_downgrade_managed (skb); + allocsize =ALIGN (tailen,L1_CACHE_BYTES );spin_lock_bh (&x->lock);
net/ipv6/esp6.c +6 -0
@@ -470,6 +470,12 @@ int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info esp->inplace = false; +/* Take real page refs and clear SKBFL_MANAGED_FRAG_REFS before +* we mutate the frag array, so the per-frag unref stays balanced +* for zerocopy managed frags (see __ip_append_data()). +*/ +skb_zcopy_downgrade_managed (skb); + allocsize =ALIGN (tailen,L1_CACHE_BYTES );spin_lock_bh (&x->lock);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 11/438 arm64: dts: amlogic: t7: use the real UART pclk
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lucas Tanure <[email protected]>
[ Upstream commit 882de800bf583dd15969836088789edbf035a944 ]
uart_a listed the 24MHz crystal for all three of its clocks because the T7 clock controller driver did not exist when these boards were added.
That leaves the real UART bus clock without a user, so the kernel turns it off when it disables unused clocks at the end of boot, and the board hangs.
Update the board DTS files to point uart_a's pclk to CLKID_SYS_UART_A instead of the dummy crystal clock.
--- arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-an400.dts | 2 +- arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-an400.dts +1 -1
@@ -33,7 +33,7 @@ xtal: xtal-clk { }; &uart_a { - clocks = <&xtal>, <&xtal>, <&xtal>; + clocks = <&xtal>, <&clkc_periphs CLKID_SYS_UART_A>, <&xtal>; clock-names = "xtal", "pclk", "baud"; status = "okay"; };
arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts +1 -1
@@ -266,6 +266,6 @@ &sd_emmc_c { &uart_a { status = "okay"; - clocks = <&xtal>, <&xtal>, <&xtal>; + clocks = <&xtal>, <&clkc_periphs CLKID_SYS_UART_A>, <&xtal>; clock-names = "xtal", "pclk", "baud"; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 12/438 arm64: dts: amlogic: t7: khadas-vim4: allow the SD card to be power cycled
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lucas Tanure <[email protected]>
[ Upstream commit c793a084ab3088744516aef437b4239d0d98623f ]
SD cards start at 3.3V and switch to 1.8V to reach UHS-I speeds. Some cards refuse that switch, and the SD specification says the only way to recover is to power the card off and start again.
SD_3V3 is marked regulator-always-on, so the supply never goes off, the card stays stuck half way through the switch, and the MMC core retries forever:
mmc1: error -95 whilst initialising SD card
Drop regulator-always-on. regulator-boot-on still turns the supply on at boot, and a card that refuses the switch now falls back to high speed instead of failing to initialise.
--- arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts | 1 - 1 file changed, 1 deletion(-)
arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts +0 -1
@@ -71,7 +71,6 @@ sd_3v3: regulator-sdcard-3v3 { vin-supply = <&vddao_3v3>; gpio = <&gpio GPIOD_11 GPIO_ACTIVE_LOW>; regulator-boot-on; - regulator-always-on; }; sdio_pwrseq: sdio-pwrseq {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 13/438 arm64: dts: amlogic: t7: fix the pin groups of two PWM outputs
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lucas Tanure <[email protected]>
[ Upstream commit ae7be5c58a819259e5eb98a3abfa60842478f2ae ]
Two of the PWM outputs can each appear on more than one pin, but the description named a single group that does not exist, so anything using it refused to start.
Name the real groups instead, one entry per pin, the same way the other multi-pin PWM output is already described.
--- arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi | 32 ++++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-)
arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi +28 -4
@@ -458,9 +458,25 @@ mux { }; }; - pwm_ao_g_pins: pwm-ao-g { + pwm_ao_g_d11_pins: pwm-ao-g-d11 { mux { - groups = "pwm_ao_g"; + groups = "pwm_ao_g_d11"; + function = "pwm_ao_g"; + bias-disable; + }; + }; + + pwm_ao_g_d7_pins: pwm-ao-g-d7 { + mux { + groups = "pwm_ao_g_d7"; + function = "pwm_ao_g"; + bias-disable; + }; + }; + + pwm_ao_g_e_pins: pwm-ao-g-e { + mux { + groups = "pwm_ao_g_e"; function = "pwm_ao_g"; bias-disable; };
@@ -474,9 +490,17 @@ mux { }; }; - pwm_ao_h_pins: pwm-ao-h { + pwm_ao_h_d5_pins: pwm-ao-h-d5 { + mux { + groups = "pwm_ao_h_d5"; + function = "pwm_ao_h"; + bias-disable; + }; + }; + + pwm_ao_h_d10_pins: pwm-ao-h-d10 { mux { - groups = "pwm_ao_h"; + groups = "pwm_ao_h_d10"; function = "pwm_ao_h"; bias-disable; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 14/438 arm64: dts: amlogic: t7: khadas-vim4: add the PWM-driven supplies
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lucas Tanure <[email protected]>
[ Upstream commit 1e5a53bd16ac501e68463e84023d1bff543cc696 ]
The board powers its two CPU clusters, the GPU, the NPU, the memory and the always-on domain from regulators steered by PWM outputs. None of them were described, so Linux treated those outputs as unused and switched them off part way through boot. The supplies then drifted away from the levels the bootloader had set, which showed up as random hangs and memory corruption.
Describe each supply so it has an owner and is left alone.
The voltage ranges are read off the feedback networks on the board schematic. VDDNPU is deliberately not the range in Amlogic's own device tree: this board fits a different feedback resistor, which puts it about 40mV higher at both ends.
--- .../amlogic/amlogic-t7-a311d2-khadas-vim4.dts | 110 +++++++++++++++++- 1 file changed, 109 insertions(+), 1 deletion(-)
arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts +109 -1
@@ -104,6 +104,66 @@ vcc5v0_usb: regulator-vcc-usb { enable-active-high; }; + vdd_ddr: regulator-vddddr { + /* + * SY8003ADFC Regulator. + */ + compatible = "pwm-regulator"; + regulator-name = "VDDDDR"; + regulator-min-microvolt = <690000>; + regulator-max-microvolt = <890000>; + pwm-supply = <&dc_in>; + pwms = <&pwm_ao_gh 0 1500 0>; + pwm-dutycycle-range = <100 0>; + regulator-boot-on; + regulator-always-on; + }; + + vdd_ee: regulator-vddee { + /* + * MP8756GD Regulator. + */ + compatible = "pwm-regulator"; + regulator-name = "VDDEE"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <922000>; + pwm-supply = <&dc_in>; + pwms = <&pwm_ao_ab 0 1500 0>; + pwm-dutycycle-range = <100 0>; + regulator-boot-on; + regulator-always-on; + }; + + vdd_gpu: regulator-vddgpu { + /* + * SY8003ADFC Regulator. + */ + compatible = "pwm-regulator"; + regulator-name = "VDDGPU"; + regulator-min-microvolt = <700000>; + regulator-max-microvolt = <922000>; + pwm-supply = <&dc_in>; + pwms = <&pwm_ao_ef 0 1500 0>; + pwm-dutycycle-range = <100 0>; + regulator-boot-on; + regulator-always-on; + }; + + vdd_npu: regulator-vddnpu { + /* + * SY8003ADFC Regulator. + */ + compatible = "pwm-regulator"; + regulator-name = "VDDNPU"; + regulator-min-microvolt = <733000>; + regulator-max-microvolt = <933000>; + pwm-supply = <&dc_in>; + pwms = <&pwm_ao_ef 1 1500 0>; + pwm-dutycycle-range = <100 0>; + regulator-boot-on; + regulator-always-on; + }; + vddao_1v8: regulator-vddao-1v8 { compatible = "regulator-fixed"; regulator-name = "VDDAO_1V8";
@@ -122,6 +182,36 @@ vddao_3v3: regulator-vddao-3v3 { regulator-always-on; }; + vddcpu_a: regulator-vddcpu-a { + /* + * MP8756GD Regulator. + */ + compatible = "pwm-regulator"; + regulator-name = "VDDCPU_A"; + regulator-min-microvolt = <689000>; + regulator-max-microvolt = <1049000>; + pwm-supply = <&dc_in>; + pwms = <&pwm_ao_cd 1 1500 0>; + pwm-dutycycle-range = <100 0>; + regulator-boot-on; + regulator-always-on; + }; + + vddcpu_b: regulator-vddcpu-b { + /* + * MP8756GD Regulator. + */ + compatible = "pwm-regulator"; + regulator-name = "VDDCPU_B"; + regulator-min-microvolt = <689000>; + regulator-max-microvolt = <1049000>; + pwm-supply = <&dc_in>; + pwms = <&pwm_ao_ab 1 1500 0>; + pwm-dutycycle-range = <100 0>; + regulator-boot-on; + regulator-always-on; + }; + vddio_1v8: regulator-vddio-1v8 { compatible = "regulator-fixed"; regulator-name = "VDDIO_1V8";
@@ -172,9 +262,27 @@ &pwm_ab { pinctrl-names = "default"; }; +&pwm_ao_ab { + status = "okay"; + pinctrl-0 = <&pwm_ao_a_pins>, <&pwm_ao_b_pins>; + pinctrl-names = "default"; +}; + &pwm_ao_cd { status = "okay"; - pinctrl-0 = <&pwm_ao_c_d_pins>; + pinctrl-0 = <&pwm_ao_c_d_pins>, <&pwm_ao_d_pins>; + pinctrl-names = "default"; +}; + +&pwm_ao_ef { + status = "okay"; + pinctrl-0 = <&pwm_ao_e_pins>, <&pwm_ao_f_pins>; + pinctrl-names = "default"; +}; + +&pwm_ao_gh { + status = "okay"; + pinctrl-0 = <&pwm_ao_g_e_pins>; pinctrl-names = "default"; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 15/438 arm64: dts: amlogic: t7: fix the pin groups of the vsync PWM
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lucas Tanure <[email protected]>
[ Upstream commit 406292fd75f95aa3010fec95b5beb5a8b7e3ba3a ]
The vsync PWM output can appear on either of two pins, but the description named a single group that does not exist, so anything using it would refuse to start.
Name the real groups instead, one entry per pin. No board describes this output yet, so nothing changes today.
--- arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi +10 -2
@@ -546,9 +546,17 @@ mux { }; }; - pwm_vs_pins: pwm-vs { + pwm_vs_y_pins: pwm-vs-y { mux { - groups = "pwm_vs"; + groups = "pwm_vs_y"; + function = "pwm_vs"; + bias-disable; + }; + }; + + pwm_vs_h_pins: pwm-vs-h { + mux { + groups = "pwm_vs_h"; function = "pwm_vs"; bias-disable; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 16/438 ARM: socfpga: select the PL310 erratum 753970 workaround
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 cfc1e9a543e3589ba200795b6e7fd8ef4314efdf ]
ARCH_INTEL_SOCFPGA selects CACHE_L2X0 and several PL310 erratum workarounds. The 753970 workaround is still conditioned on PL310, but that Kconfig symbol no longer exists, so this one selection is always disabled.
Select PL310_ERRATA_753970 directly, consistently with the other PL310 workarounds required by the platform.
--- arch/arm/mach-socfpga/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/mach-socfpga/Kconfig +1 -1
@@ -16,7 +16,7 @@ menuconfig ARCH_INTEL_SOCFPGA select ARM_ERRATA_775420 select PL310_ERRATA_588369 select PL310_ERRATA_727915 - select PL310_ERRATA_753970 if PL310 + select PL310_ERRATA_753970 select PL310_ERRATA_769419 select RESET_CONTROLLER
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 17/438 RDMA/siw: Clear association under lock if siw_qp_modify fails in siw_accept
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guoqing Jiang <[email protected]>
[ Upstream commit 32cd87f54dd1070020e664ccb0312a9f0fea79b4 ]
We need to clear cep before release state_lock as siw_qp_llp_close and siw_qp_modify->siw_qp_llp_close did.
Otherwise if siw_qp_modify() fails in siw_accept(), the QP's state_lock is released before the error path cleanup. A concurrent ibv_modify_qp() transitioning the QP to ERROR can race in this window:
siw_accept() ibv_modify_qp(ERROR)
---------------------- ----------------------
siw_qp_modify() fails
up_write(&qp->state_lock)
down_write(&qp->state_lock)
nextstate_from_idle():
if (qp->cep)
siw_cep_put(qp->cep) <- frees cep
qp->cep = NULL
goto error
cep->qp = NULL <- UAFClear qp->cep and drop the association reference taken by siw_cep_get(), all under the write lock held from the initial down_write(&qp->state_lock). Thread B therefore sees qp->cep == NULL, skips its own put, and cannot free the cep before siw_accept() is done with it.
--- drivers/infiniband/sw/siw/siw_cm.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/infiniband/sw/siw/siw_cm.c +5 -2
@@ -1719,9 +1719,12 @@ int siw_accept(struct iw_cm_id *id, struct iw_cm_conn_param *params)SIW_QP_ATTR_STATE |SIW_QP_ATTR_LLP_HANDLE |SIW_QP_ATTR_ORD |SIW_QP_ATTR_IRD | SIW_QP_ATTR_MPA); +if (rv) { + qp->cep =NULL ; +siw_cep_put (cep); + goto error_unlock; + }up_write (&qp->state_lock); -if (rv) - goto error;siw_dbg_cep (cep,"[QP %u]: send mpa reply, %d byte pdata\n" ,qp_id (qp), params->private_data_len);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 18/438 RDMA/rxe: validate access flags before swapping the MRs PD
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Norbert Szetei <[email protected]>
[ Upstream commit ae36a5b609ae79f4de966328b78d2584be9719a4 ]
rxe_rereg_user_mr() reassigns mr->ibmr.pd first and only then validates the IB_MR_REREG_ACCESS argument:
if (flags & IB_MR_REREG_PD) {
rxe_put(old_pd);
rxe_get(pd);
mr->ibmr.pd = ibpd;
}
if (flags & IB_MR_REREG_ACCESS) {
if (access & ~RXE_ACCESS_SUPPORTED_MR)
return ERR_PTR(-EOPNOTSUPP);
mr->access = access;
}Both flags pass the entry check because RXE_MR_REREG_SUPPORTED is IB_MR_REREG_PD | IB_MR_REREG_ACCESS, so a caller can reach the access check with mr->ibmr.pd already reassigned.
mr->ibmr.pd is owned by the core, which adjusts pd->usecnt only on the success path: ib_uverbs_rereg_mr() jumps to put_new_uobj on a driver error without undoing the reassignment, so mr->pd == new_pd while the usecnts still charge the MR to orig_pd. ib_dereg_mr_user() then decrements new_pd, whose count can reach zero while a memory window still references it; uverbs_free_pd() frees the PD on that count alone and rxe_mw_cleanup() writes to freed memory:
BUG: KASAN: slab-use-after-free in __rxe_put+0x31/0xa0 Write of size 4 at addr ffff8881301dd690 by task rxe_poc/591 __rxe_put+0x31/0xa0 rxe_mw_cleanup+0x42/0x200 __rxe_cleanup+0x115/0x370 rxe_dealloc_mw+0x4c/0x80 Allocated by task 591: ib_uverbs_alloc_pd+0x258/0x540 Freed by task 591: ib_dealloc_pd_user+0x174/0x210 uverbs_free_pd+0x8d/0xc0 ib_uverbs_dealloc_pd+0x18e/0x1d0
Validate the access flags before mutating any state so the callback either applies every requested change or none.
--- drivers/infiniband/sw/rxe/rxe_verbs.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/infiniband/sw/rxe/rxe_verbs.c +7 -6
@@ -1327,19 +1327,20 @@ static struct ib_mr *rxe_rereg_user_mr(struct ib_mr *ibmr, int flags,if (err)return ERR_PTR (err); +if ((flags &IB_MR_REREG_ACCESS ) && + (access & ~RXE_ACCESS_SUPPORTED_MR )) { +rxe_err_mr (mr,"access = %#x not supported\n" , access); +return ERR_PTR (-EOPNOTSUPP ); + } +if (flags &IB_MR_REREG_PD ) {rxe_put (old_pd);rxe_get (pd); mr->ibmr.pd = ibpd; } -if (flags &IB_MR_REREG_ACCESS ) { -if (access & ~RXE_ACCESS_SUPPORTED_MR ) { -rxe_err_mr (mr,"access = %#x not supported\n" , access); -return ERR_PTR (-EOPNOTSUPP ); - } +if (flags &IB_MR_REREG_ACCESS ) mr->access = access; - }return NULL ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 19/438 RDMA/rxe: Fix integer overflow in mr_check_range() leading to OOB access
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gang Yan <[email protected]>
[ Upstream commit d10e2a08799e858d3e71ea4169bcd018f216d444 ]
mr_check_range() validates that [iova, iova+length) falls within the registered MR range using wraparound-prone arithmetic:
if (iova < mr->ibmr.iova ||
iova + length > mr->ibmr.iova + mr->ibmr.length)A remote peer can craft an RDMA-Write/Read RETH so that iova + length wraps to 0 (e.g. iova=0xfffffffffffffff8, length=8), bypassing the check. rxe_mr_iova_to_index() then computes a huge index (int idx, only guarded by WARN_ON) and rxe_mr_copy_xarray() dereferences mr->page_info[huge], causing an out-of-bounds read/write and a kernel oops that is triggerable by an unauthenticated remote peer.
Rewrite the check in overflow-safe form; the first two clauses guarantee that the subsequent subtractions do not underflow:
if (iova < mr->ibmr.iova ||
length > mr->ibmr.length ||
iova - mr->ibmr.iova > mr->ibmr.length - length)With the fix, mr_check_range() returns -EINVAL for the crafted iova and the responder reports REMOTE_ACCESS_ERROR instead of triggering the OOB.
--- drivers/infiniband/sw/rxe/rxe_mr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/infiniband/sw/rxe/rxe_mr.c +2 -1
@@ -33,7 +33,8 @@ int mr_check_range(struct rxe_mr *mr, u64 iova, size_t length)case IB_MR_TYPE_USER :case IB_MR_TYPE_MEM_REG :if (iova < mr->ibmr.iova || - iova + length > mr->ibmr.iova + mr->ibmr.length) { + length > mr->ibmr.length || + iova - mr->ibmr.iova > mr->ibmr.length - length) {rxe_dbg_mr (mr,"iova/length out of range\n" );return -EINVAL ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 20/438 xfrm: hold net_device reference under RCU in bundle creation
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cen Zhang (Microsoft Security FORGE Labs) <[email protected]>
[ Upstream commit 9fa903b24b1f46b4ff5443bcd4aca23e5c57f9c1 ]
xfrm_bundle_create() and xfrm_create_dummy_bundle() read dst->dev into a local pointer without taking a device reference, then pass it to xfrm_fill_dst(). A concurrent RTM_DELLINK replaces dst->dev via dst_dev_put() and frees the old net_device, causing a use-after-free when xfrm6_fill_dst() later dereferences the stale dev pointer.
BUG: KASAN: slab-use-after-free in xfrm6_fill_dst+0x82c/0x860 (net/ipv6/xfrm6_policy.c:86 netdev_hold()) Read of size 8 at addr ffff8880142fe588 by task exploit/153 Call Trace: xfrm6_fill_dst+0x82c/0x860 xfrm_resolve_and_create_bundle+0x21d4/0x2bd0 xfrm_lookup_with_ifid+0x485/0x1640 ip6_dst_lookup_flow+0x19b/0x1e0 udpv6_sendmsg+0x1443/0x2dd0
Fix this by reading dst->dev via dst_dev_rcu() and keeping the RCU read-side critical section active until xfrm_fill_dst() has taken the required device references.
--- net/xfrm/xfrm_policy.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-)
net/xfrm/xfrm_policy.c +15 -5
@@ -2770,9 +2770,12 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, xdst0->path = dst; err = -ENODEV ; - dev = dst->dev; -if (!dev) +rcu_read_lock (); + dev =dst_dev_rcu (dst); +if (!dev) { +rcu_read_unlock (); goto free_dst; + }xfrm_init_path (xdst0, dst, nfheader_len);xfrm_init_pmtu (bundle, nx);
@@ -2780,8 +2783,10 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,for (xdst_prev = xdst0; xdst_prev != (struct xfrm_dst *)dst; xdst_prev = (struct xfrm_dst *)xfrm_dst_child (&xdst_prev->u.dst)) { err =xfrm_fill_dst (xdst_prev, dev, fl); -if (err) +if (err) { +rcu_read_unlock (); goto free_dst; + } xdst_prev->u.dst.header_len = header_len; xdst_prev->u.dst.trailer_len = trailer_len;
@@ -2789,6 +2794,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, trailer_len -= xdst_prev->u.dst.xfrm->props.trailer_len; } +rcu_read_unlock ();return &xdst0->u.dst; put_states:
@@ -3058,11 +3064,15 @@ static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net,xfrm_init_path ((struct xfrm_dst *)dst1, dst,0 ); err = -ENODEV ; - dev = dst->dev; -if (!dev) +rcu_read_lock (); + dev =dst_dev_rcu (dst); +if (!dev) { +rcu_read_unlock (); goto free_dst; + } err =xfrm_fill_dst (xdst, dev, fl); +rcu_read_unlock ();if (err) goto free_dst;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 21/438 firmware: arm_scpi: reject DVFS OPP count above MAX_DVFS_OPPS
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xixin Liu <[email protected]>
[ Upstream commit 32471d84a487c7fd74532bc96be56f8028cf4a3f ]
scpi_dvfs_get_info() already rejected a zero opp_count, but still trusted any larger value from the SCP firmware. The shared-memory reply only holds MAX_DVFS_OPPS entries in buf.opps[]; a bigger count over-reads that array and then sizes the allocated OPP table incorrectly (garbage OPPs / OOB). The missing upper bound dates back to the original SCPI DVFS support.
Reject zero and out-of-range counts in one check and return -EINVAL.
--- drivers/firmware/arm_scpi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/firmware/arm_scpi.c +2 -2
@@ -631,8 +631,8 @@ static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain)if (ret)return ERR_PTR (ret); -if (!buf.opp_count) -return ERR_PTR (-ENOENT ); +if (!buf.opp_count || buf.opp_count >MAX_DVFS_OPPS ) +return ERR_PTR (-EINVAL ); info =kmalloc_obj (*info);if (!info)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 22/438 clk: scpi: bound-check DVFS index in scpi_dvfs_recalc_rate
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xixin Liu <[email protected]>
[ Upstream commit 70f4b78d560e592cbf3325b162424737d032fc1d ]
dvfs_get_idx() may return an out-of-range index if the SCP firmware is buggy or returns a stale value. Only negative indexes were rejected, so a large index walked past info->opps and could treat garbage as a clock rate (KASAN OOB / wrong frequency to consumers). The missing upper bound dates back to the original SCPI clock driver.
Treat indexes >= opp count as invalid and return 0, same as idx < 0.
--- drivers/clk/clk-scpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/clk/clk-scpi.c +1 -1
@@ -85,7 +85,7 @@ static unsigned long scpi_dvfs_recalc_rate(struct clk_hw *hw,int idx = clk->scpi_ops->dvfs_get_idx (clk->id);const struct scpi_opp *opp; -if (idx <0 ) +if (idx <0 || idx >= clk->info->count)return 0 ; opp = clk->info->opps + idx;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 23/438 clk: scpi: register scpi-cpufreq once and clear on failure
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xixin Liu <[email protected]>
[ Upstream commit ab06cf8152dace327cd873188e4a036c4e0b5944 ]
scpi_clocks_probe() walks clock children and, for each DVFS provider, calls platform_device_register_simple("scpi-cpufreq", -1, ...). Two related bugs:
Since all DVFS providers register the fixed scpi-cpufreq device using PLATFORM_DEVID_NONE, a second registration fails with -EEXIST and overwrites the pointer to the successfully registered device. The first device can then no longer be unregistered.
Register the virtual device only once. If registration fails, reset the pointer to NULL so a subsequent DVFS provider can retry and the global pointer only represents a successfully registered device.
(sudeep.holla: reworded the commit message to improve readability)
--- drivers/clk/clk-scpi.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/clk/clk-scpi.c +5 -1
@@ -284,10 +284,14 @@ static int scpi_clocks_probe(struct platform_device *pdev)if (match->data != &scpi_dvfs_ops)continue ;/* Add the virtual cpufreq device if it's DVFS clock provider */ +if (cpufreq_dev) +continue ; cpufreq_dev =platform_device_register_simple ("scpi-cpufreq" ,-1 ,NULL ,0 ); -if (IS_ERR (cpufreq_dev)) +if (IS_ERR (cpufreq_dev)) {pr_warn ("unable to register cpufreq device" ); + cpufreq_dev =NULL ; + } }return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 24/438 RDMA/rxe: Restore HMM_PFN_WRITE check in ODP write paths
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiming Shi <[email protected]>
[ Upstream commit 769001ce838d907ecaa95f1d0a4e8fc86f761f9f ]
Commit 0b261d7c1cd3 ("RDMA/rxe: Break endless pagefault loop for RO pages") dropped the access permission test from rxe_check_pagefault() and left only HMM_PFN_VALID. A page faulted in read-only, for example a page-cache folio behind a PROT_READ file mapping, then satisfies the check and ODP write operations (RDMA WRITE, RDMA READ response, SEND payload, atomics) modify it through kmap without ever breaking CoW.
An unprivileged user can register an ODP MR over such a mapping and have incoming RDMA traffic overwrite the page cache of a file it only holds O_RDONLY, including /etc/passwd or setuid binaries. This is the same primitive class as Dirty COW and CVE-2022-2590.
mlx5 has the missing invariant: its ODP path sets the device write bit only for pfns that carry HMM_PFN_WRITE. Restore it in rxe by requiring HMM_PFN_WRITE in rxe_check_pagefault() for every operation except RXE_PAGEFAULT_RDONLY. A write to a non-writable VMA now fails the one fault attempt with -EPERM from hmm_vma_fault() instead of re-faulting forever. For a writable VMA the fault breaks CoW and the write lands in the private page.
Keep pmem flushes on the read-only check. arch_wb_cache_pmem() never modifies memory, and the FLUSH access bits do not make the umem writable, so classifying flushes as writes would make every flush against a flush-only MR fail.
--- drivers/infiniband/sw/rxe/rxe_odp.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
drivers/infiniband/sw/rxe/rxe_odp.c +11 -5
@@ -125,19 +125,23 @@ int rxe_odp_mr_init_user(struct rxe_dev *rxe, u64 start, u64 length, }static inline bool rxe_check_pagefault (struct ib_umem_odp *umem_odp,u64 iova, -int length) +int length,bool write) {bool need_fault = false; +u64 access =HMM_PFN_VALID ;u64 addr;int idx; +if (write) + access |=HMM_PFN_WRITE ; + addr = iova & (~(BIT (umem_odp->page_shift) -1 ));/* Skim through all pages that are to be accessed. */ while (addr < iova + length) { idx = (addr -ib_umem_start (umem_odp)) >> umem_odp->page_shift; -if (!(umem_odp->map.pfn_list[idx] &HMM_PFN_VALID )) { +if ((umem_odp->map.pfn_list[idx] & access) != access) { need_fault = true;break ; }
@@ -160,6 +164,7 @@ static unsigned long rxe_odp_iova_to_page_offset(struct ib_umem_odp *umem_odp, ustatic int rxe_odp_map_range_and_lock (struct rxe_mr *mr,u64 iova,int length,u32 flags) {struct ib_umem_odp *umem_odp =to_ib_umem_odp (mr->umem); +bool write = !(flags &RXE_PAGEFAULT_RDONLY );bool need_fault;int err;
@@ -168,7 +173,7 @@ static int rxe_odp_map_range_and_lock(struct rxe_mr *mr, u64 iova, int length, umutex_lock (&umem_odp->umem_mutex); - need_fault =rxe_check_pagefault (umem_odp, iova, length); + need_fault =rxe_check_pagefault (umem_odp, iova, length, write);if (need_fault) {mutex_unlock (&umem_odp->umem_mutex);
@@ -178,7 +183,7 @@ static int rxe_odp_map_range_and_lock(struct rxe_mr *mr, u64 iova, int length, uif (err <0 )return err; - need_fault =rxe_check_pagefault (umem_odp, iova, length); + need_fault =rxe_check_pagefault (umem_odp, iova, length, write);if (need_fault) {mutex_unlock (&umem_odp->umem_mutex);return -EFAULT ;
@@ -340,8 +345,9 @@ int rxe_odp_flush_pmem_iova(struct rxe_mr *mr, u64 iova,int err;u8 *va; +/* A flush never modifies memory; read-only access suffices. */ err =rxe_odp_map_range_and_lock (mr, iova, length, -RXE_PAGEFAULT_DEFAULT ); +RXE_PAGEFAULT_RDONLY );if (err)return err;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 25/438 RDMA/rxe: insert mcg into mcg_tree only after rxe_mcast_add() succeeds
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
[ Upstream commit 1caceeb2d74bbe88223aea55eb8626b4c5f076fd ]
rxe_get_mcg() publishes a newly allocated multicast group in rxe->mcg_tree before programming the backing Ethernet multicast address with rxe_mcast_add(), which runs outside mcg_lock. A local userspace RDMA client reaches this path with ATTACH_MCAST on a UD QP; if rxe_mcast_add() then returns an error (for example -ENODEV when the backing netdev has been removed, or a propagated dev_mc_add() error), the unwind frees the published group without removing it from the tree. A later lookup of the same MGID dereferences the freed struct rxe_mcg from __rxe_lookup_mcg().
Fix this by keeping the new mcg private until rxe_mcast_add() succeeds. Split the tree publication into __rxe_publish_mcg(), call rxe_mcast_add() before taking the tree reference, and free the still-private mcg on failure. Because the group is never visible in mcg_tree until the multicast address is programmed, no concurrent caller can look it up or attach a QP to a group that is about to be torn down, so the error path needs no conditional unwind. If another caller publishes the same MGID while the address is being programmed, the post-add re-check under mcg_lock finds the winner; this caller then drops its private object and balances its own rxe_mcast_add() with rxe_mcast_del() before returning the winner.
Reproduced by forcing the rxe_mcast_add() error return under KASAN:
without the change the next attach to the same MGID reports a slab-use-after-free in __rxe_lookup_mcg(); with it the forced failure returns cleanly. A no-injection attach/detach regression, including a two-QP shared join/leave and re-attach, stays KASAN- and leak-clean.
--- drivers/infiniband/sw/rxe/rxe_mcast.c | 50 +++++++++++++++++++-------- 1 file changed, 36 insertions(+), 14 deletions(-)
drivers/infiniband/sw/rxe/rxe_mcast.c +36 -14
@@ -175,7 +175,9 @@ struct rxe_mcg *rxe_lookup_mcg(struct rxe_dev *rxe, union ib_gid *mgid)* @mgid: multicast address as a gid * @mcg: new mcg object * -* Context: caller should hold rxe->mcg lock +* Initializes the mcg fields. The mcg is private and not yet visible in +* mcg_tree, so this may run without rxe->mcg_lock; __rxe_publish_mcg() +* makes it visible under the lock once it is ready. */ static void __rxe_init_mcg (struct rxe_dev *rxe,union ib_gid *mgid,struct rxe_mcg *mcg)
@@ -184,13 +186,22 @@ static void __rxe_init_mcg(struct rxe_dev *rxe, union ib_gid *mgid,memcpy (&mcg->mgid, mgid,sizeof (mcg->mgid));INIT_LIST_HEAD (&mcg->qp_list); mcg->rxe = rxe; +} -/* caller holds a ref on mcg but that will be -* dropped when mcg goes out of scope. We need to take a ref -* on the pointer that will be saved in the red-black tree -* by __rxe_insert_mcg and used to lookup mcg from mgid later. -* Inserting mcg makes it visible to outside so this should -* be done last after the object is ready. +/** +* __rxe_publish_mcg - make a fully initialized mcg visible in mcg_tree +* @mcg: the mcg object +* +* Context: caller must hold rxe->mcg_lock and a reference on mcg +*/ +static void __rxe_publish_mcg (struct rxe_mcg *mcg) +{ +/* caller holds a ref on mcg but that will be dropped when mcg goes +* out of scope. We need to take a ref on the pointer that will be +* saved in the red-black tree by __rxe_insert_mcg and used to lookup +* mcg from mgid later. Inserting mcg makes it visible to outside so +* this is done last after the object is ready and the multicast +* address has been programmed. */ kref_get (&mcg->ref_cnt);__rxe_insert_mcg (mcg);
@@ -228,26 +239,37 @@ static struct rxe_mcg *rxe_get_mcg(struct rxe_dev *rxe, union ib_gid *mgid) err = -ENOMEM ; goto err_dec; } +__rxe_init_mcg (rxe, mgid, mcg); + +/* program the multicast address while mcg is still private, before +* it is inserted into mcg_tree. dev_mc_add() may sleep so this must +* run outside mcg_lock. On failure mcg was never published, so a +* plain free is correct and the tree is untouched. +*/ + err =rxe_mcast_add (rxe, mgid); +if (err) { +kfree (mcg); + goto err_dec; + }spin_lock_bh (&rxe->mcg_lock); -/* re-check to see if someone else just added it */ +/* re-check to see if someone else just added it while we were adding +* the multicast address; if so use theirs and drop ours +*/ tmp =__rxe_lookup_mcg (rxe, mgid);if (tmp) {spin_unlock_bh (&rxe->mcg_lock); +rxe_mcast_del (rxe, mgid);atomic_dec (&rxe->mcg_num);kfree (mcg);return tmp; } -__rxe_init_mcg (rxe, mgid, mcg); +__rxe_publish_mcg (mcg);spin_unlock_bh (&rxe->mcg_lock); -/* add mcast address outside of lock */ - err =rxe_mcast_add (rxe, mgid); -if (!err) -return mcg; +return mcg; -kfree (mcg); err_dec:atomic_dec (&rxe->mcg_num);return ERR_PTR (err);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 26/438 RDMA/mlx5: Remove warn on missing representor in query_port_speed
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Or Har-Toov <[email protected]>
[ Upstream commit 2be77295316c2dff0a33c0dc3a65abdab4ccf796 ]
The representor ib_device's phys_port_cnt is set to the total vport count when the uplink vport rep loads. Individual port[i].rep entries are populated only as each VF/SF vport rep registers. A NULL .rep for a given port index is therefore expected while VF reps are still loading or haven't been enabled yet.
Tools like ibstat and ibv_devinfo iterate over all ports of all RDMA devices. Some ports may not have an eswitch representor, causing repeated dmesg warnings when these tools run without a device argument. This causes dmesg to be flooded with this message on every ibstat invocation.
Remove the warning and return -ENODEV when no representor exists for the queried port.
--- drivers/infiniband/hw/mlx5/main.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
drivers/infiniband/hw/mlx5/main.c +2 -5
@@ -1684,11 +1684,8 @@ static int mlx5_ib_query_port_speed_rep(struct mlx5_ib_dev *dev, u32 port_num,struct mlx5_core_dev *mdev;u16 op_mod; -if (!dev->port[port_num -1 ].rep) { -mlx5_ib_warn (dev,"Representor doesn't exist for port %u\n" , - port_num); -return -EINVAL ; - } +if (!dev->port[port_num -1 ].rep) +return -ENODEV ; rep = dev->port[port_num -1 ].rep; mdev =mlx5_eswitch_get_core_dev (rep->esw);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 27/438 RDMA/core: Reject unregistering netdevs in ib_get_eth_speed
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krystian Kaniewski <[email protected]>
[ Upstream commit ef9fbe1b93f3b617b96e86d5cd76b3fa44514cb5 ]
ib_device_get_netdev() intentionally returns a referenced net_device even when it is unregistering, so matching and cleanup callers can still find the association. The reference keeps struct net_device allocated, but does not guarantee that the device remains operational.
ib_get_eth_speed() uses the returned device operationally by invoking its ethtool callback. Although that call is made under RTNL, the function does not verify the registration state first. An asynchronous RDMA port query can therefore call into a netdev after NETDEV_UNREGISTER and ndo_uninit have completed.
Check for NETREG_REGISTERED while holding RTNL and return -ENODEV for a device which is being unregistered. Keeping RTNL across the check and the ethtool operation prevents unregister from starting between them.
Keep the speed fallback and warning under RTNL as well, so the warning can safely read netdev->name. Drop the netdev reference before releasing RTNL once all accesses to the device are complete.
--- drivers/infiniband/core/verbs.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
drivers/infiniband/core/verbs.c +8 -4
@@ -2056,11 +2056,13 @@ int ib_get_eth_speed(struct ib_device *dev, u32 port_num, u16 *speed, u8 *width)return -ENODEV ;rtnl_lock (); - rc =__ethtool_get_link_ksettings (netdev, &lksettings); -rtnl_unlock (); - -dev_put (netdev); +if (READ_ONCE (netdev->reg_state) !=NETREG_REGISTERED ) { +dev_put (netdev); +rtnl_unlock (); +return -ENODEV ; + } + rc =__ethtool_get_link_ksettings (netdev, &lksettings);if (!rc && lksettings.base.speed != (u32 )SPEED_UNKNOWN ) { netdev_speed = lksettings.base.speed; }else {
@@ -2069,6 +2071,8 @@ int ib_get_eth_speed(struct ib_device *dev, u32 port_num, u16 *speed, u8 *width)pr_warn ("%s speed is unknown, defaulting to %u\n" , netdev->name, netdev_speed); } +dev_put (netdev); +rtnl_unlock ();ib_get_width_and_speed (netdev_speed, lksettings.lanes, speed, width);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 28/438 RDMA/uverbs: Fix mmap_lock/disassociation_lock circular dependency
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Or Har-Toov <[email protected]>
[ Upstream commit a44a3f175eaee7e5aeb6a8fed381c4a0d5f49236 ]
Commit 51976c6cd786 ("RDMA/core: Provide rdma_user_mmap_disassociate() to disassociate mmap pages") introduced disassociation_lock to protect new mmap registrations against uverbs_user_mmap_disassociate(), but created an ABBA deadlock:
Thread A (mmap / fork):
mmap_lock -> disassociation_lock
Thread B (disassociate):
disassociation_lock -> mmap_lock
Fix by removing disassociation_lock entirely and using the pre-existing hw_destroy_rwsem instead. hw_destroy_rwsem already provides the same
protection: rdma_umap_open() and ib_uverbs_mmap() both use down_read_trylock() before registering a new VMA, so holding hw_destroy_rwsem in uverbs_user_mmap_disassociate() is sufficient to block new registrations. trylock is used in both mmap paths (not blocking down_read) because mmap_lock is already held on entry, and uverbs_user_mmap_disassociate() acquires mmap_lock internally — a blocking read would recreate the same deadlock.
The only caller that was not taking hw_destroy_rwsem for write was rdma_user_mmap_disassociate(). Fix it to take the rwsem per-ufile while iterating under lists_mutex. This is safe because ib_uverbs_close() releases hw_destroy_rwsem entirely before acquiring lists_mutex, so the two locks are never held simultaneously.
lockdep warning:
[ 776.654252] ======================================================
[ 776.655214] WARNING: possible circular locking dependency detected
[ 776.656167] 6.18.0for-upstream_debug_94e244d9ccab #1 Not tainted
[ 776.657114] ------------------------------------------------------
[ 776.658087] devlink/14824 is trying to acquire lock:
[ 776.658879] ffff88811170c800 (&mm->mmap_lock){++++}-{4:4}, at: uverbs_user_mmap_disassociate+0x168/0x780 [ib_uverbs]
[ 776.660479]
[ 776.660479] but task is already holding lock:
[ 776.661460] ffff888142d92b08 (&file->disassociation_lock){+.+.}-{4:4}, at: uverbs_user_mmap_disassociate+0x39/0x780 [ib_uverbs]
[ 776.663177]
[ 776.663177] which lock already depends on the new lock.
[ 776.663177]
[ 776.664525]
[ 776.664525] the existing dependency chain (in reverse order) is:
[ 776.665724]
[ 776.665724] -> #2 (&file->disassociation_lock){+.+.}-{4:4}:
[ 776.666887] __mutex_lock+0x16d/0x2330
[ 776.667633] rdma_umap_open+0x129/0x280 [ib_uverbs]
[ 776.668489] dup_mmap+0xa40/0x1790
[ 776.669170] copy_process+0x5dd2/0x6170
[ 776.669933] kernel_clone+0xb6/0x610
[ 776.670636] __do_sys_clone+0xb5/0xf0
[ 776.671354] do_syscall_64+0x70/0x12e0
[ 776.672083] entry_SYSCALL_64_after_hwframe+0x4b/0x53
[ 776.672940]
[ 776.672940] -> #1 (&mm->mmap_lock/1){+.+.}-{4:4}:
[ 776.673985] down_write_nested+0x90/0x1e0
[ 776.674751] dup_mmap+0x201/0x1790
[ 776.675448] copy_process+0x5dd2/0x6170
[ 776.676180] kernel_clone+0xb6/0x610
[ 776.676904] __do_sys_clone+0xb5/0xf0
[ 776.677615] do_syscall_64+0x70/0x12e0
[ 776.678351] entry_SYSCALL_64_after_hwframe+0x4b/0x53
[ 776.679239]
[ 776.679239] -> #0 (&mm->mmap_lock){++++}-{4:4}:
[ 776.680253] __lock_acquire+0x18c6/0x2ec0
[ 776.681018] lock_acquire+0x10e/0x2e0
[ 776.681742] down_read+0x95/0x430
[ 776.682395] uverbs_user_mmap_disassociate+0x168/0x780 [ib_uverbs]
[ 776.683436] uverbs_destroy_ufile_hw+0x1ae/0x270 [ib_uverbs]
[ 776.684416] ib_uverbs_remove_one+0x22b/0x420 [ib_uverbs]
[ 776.685371] remove_client_context+0xa6/0xf0 [ib_core]
[ 776.686342] disable_device+0x12b/0x240 [ib_core]
[ 776.687249] __ib_unregister_device+0x269/0x460 [ib_core]
[ 776.688233] ib_unregister_device+0x21/0x30 [ib_core]
[ 776.689140] mlx5r_remove+0xd0/0x170 [mlx5_ib]
[ 776.689999] device_release_driver_internal+0x3b2/0x560
[ 776.694876] bus_remove_device+0x1f5/0x3e0
[ 776.695638] device_del+0x3b9/0x990
[ 776.696329] mlx5_detach_device+0x17e/0x350 [mlx5_core]
[ 776.697429] mlx5_unload_one_devl_locked+0x3f/0xb0 [mlx5_core]
[ 776.698578] mlx5_devlink_reload_down+0x1f9/0x550 [mlx5_core]
[ 776.699712] devlink_reload+0x13e/0x680
[ 776.700456] devlink_nl_reload_doit+0xc29/0x1160
[ 776.701293] genl_family_rcv_msg_doit+0x1c9/0x2a0
[ 776.702135] genl_rcv_msg+0x3f0/0x6b0
[ 776.702854] netlink_rcv_skb+0x11d/0x370
[ 776.703605] genl_rcv+0x24/0x40
[ 776.704236] netlink_unicast+0x5b4/0x970
[ 776.704984] netlink_sendmsg+0x730/0xbf0
[ 776.705748] __sock_sendmsg+0xc5/0x190
[ 776.706461] __sys_sendto+0x201/0x2f0
[ 776.707188] __x64_sys_sendto+0xdc/0x1b0
[ 776.707931] do_syscall_64+0x70/0x12e0
[ 776.708643] entry_SYSCALL_64_after_hwframe+0x4b/0x53
[ 776.709546]
[ 776.709546] other info that might help us debug this:
[ 776.709546]
[ 776.710910] Chain exists of:
[ 776.710910] &mm->mmap_lock --> &mm->mmap_lock/1 --> &file->disassociation_lock
[ 776.710910]
[ 776.712805] Possible unsafe locking scenario:
[ 776.712805]
[ 776.713828] CPU0 CPU1
[ 776.714589] ---- ----
[ 776.715347] lock(&file->disassociation_lock);
[ 776.716097] lock(&mm->mmap_lock/1);
[ 776.717067] lock(&file->disassociation_lock);
[ 776.718199] rlock(&mm->mmap_lock);
[ 776.718857]
[ 776.718857] *** DEADLOCK ***--- drivers/infiniband/core/rdma_core.c | 1 - drivers/infiniband/core/uverbs_main.c | 25 +++++++++++-------------- include/rdma/uverbs_types.h | 2 -- 3 files changed, 11 insertions(+), 17 deletions(-)
drivers/infiniband/core/rdma_core.c +0 -1
@@ -69,7 +69,6 @@ void ib_uverbs_release_file(struct kref *ref)if (file->disassociate_page)__free_pages (file->disassociate_page,0 ); -mutex_destroy (&file->disassociation_lock);mutex_destroy (&file->umap_lock);mutex_destroy (&file->ucontext_lock);kfree (file);
drivers/infiniband/core/uverbs_main.c +11 -14
@@ -644,12 +644,15 @@ static int ib_uverbs_mmap(struct file *filp, struct vm_area_struct *vma) goto out; } -mutex_lock (&file->disassociation_lock); +if (!down_read_trylock (&file->hw_destroy_rwsem)) { + ret = -EIO ; + goto out; + } vma->vm_ops = &rdma_umap_ops; ret = ucontext->device->ops.mmap (ucontext, vma); -mutex_unlock (&file->disassociation_lock); +up_read (&file->hw_destroy_rwsem); out:srcu_read_unlock (&file->device->disassociate_srcu, srcu_key);return ret;
@@ -671,7 +674,6 @@ static void rdma_umap_open(struct vm_area_struct *vma)/* We are racing with disassociation */ if (!down_read_trylock (&ufile->hw_destroy_rwsem)) goto out_zap; -mutex_lock (&ufile->disassociation_lock);/* * Disassociation already completed, the VMA should already be zapped.
@@ -684,12 +686,10 @@ static void rdma_umap_open(struct vm_area_struct *vma) goto out_unlock;rdma_umap_priv_init (priv, vma, opriv->entry); -mutex_unlock (&ufile->disassociation_lock);up_read (&ufile->hw_destroy_rwsem);return ; out_unlock: -mutex_unlock (&ufile->disassociation_lock);up_read (&ufile->hw_destroy_rwsem); out_zap:/*
@@ -773,7 +773,7 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile) {struct rdma_umap_priv *priv, *next_priv; -mutex_lock (&ufile->disassociation_lock); +lockdep_assert_held_write (&ufile->hw_destroy_rwsem);while (1 ) {struct mm_struct *mm =NULL ;
@@ -799,10 +799,8 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)break ; }mutex_unlock (&ufile->umap_lock); -if (!mm) { -mutex_unlock (&ufile->disassociation_lock); +if (!mm)return ; - }/* * The umap_lock is nested under mmap_lock since it used within
@@ -832,8 +830,6 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)mmap_read_unlock (mm);mmput (mm); } - -mutex_unlock (&ufile->disassociation_lock); }/**
@@ -851,8 +847,11 @@ void rdma_user_mmap_disassociate(struct ib_device *device)mutex_lock (&uverbs_dev->lists_mutex);list_for_each_entry (ufile, &uverbs_dev->uverbs_file_list, list) { -if (ufile->ucontext) +if (ufile->ucontext) { +down_write (&ufile->hw_destroy_rwsem);uverbs_user_mmap_disassociate (ufile); +up_write (&ufile->hw_destroy_rwsem); + } }mutex_unlock (&uverbs_dev->lists_mutex); }
@@ -927,8 +926,6 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp)mutex_init (&file->umap_lock);INIT_LIST_HEAD (&file->umaps); -mutex_init (&file->disassociation_lock); - filp->private_data = file;list_add_tail (&file->list, &dev->uverbs_file_list);mutex_unlock (&dev->lists_mutex);
include/rdma/uverbs_types.h +0 -2
@@ -180,8 +180,6 @@ struct ib_uverbs_file {struct page *disassociate_page;struct xarray idr; - -struct mutex disassociation_lock; };extern const struct uverbs_obj_type_class uverbs_idr_class;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 29/438 power: sequencing: Fix build issue with COMPILE_TEST
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Biju Das <[email protected]>
[ Upstream commit 3b54dbd119805361695cb50ca6a875f4c7518b74 ]
The POWER_SEQUENCING_TH1520_GPU driver depends on (ARCH_THEAD && AUXILIARY_BUS) || COMPILE_TEST. This means when COMPILE_TEST=y and ARCH_THEAD is not set, the driver can still be built even though it requires AUXILIARY_BUS, which may not be selected in that configuration, leading to a build failure.
Fix this by dropping AUXILIARY_BUS from the dependency and instead selecting it directly, so the dependency is satisfied regardless of whether COMPILE_TEST or ARCH_THEAD is enabled.
--- drivers/power/sequencing/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/power/sequencing/Kconfig +2 -1
@@ -29,7 +29,8 @@ config POWER_SEQUENCING_QCOM_WCN config POWER_SEQUENCING_TH1520_GPU tristate "T-HEAD TH1520 GPU power sequencing driver" - depends on (ARCH_THEAD && AUXILIARY_BUS) || COMPILE_TEST + depends on ARCH_THEAD || COMPILE_TEST + select AUXILIARY_BUS help Say Y here to enable the power sequencing driver for the TH1520 SoC GPU. This driver handles the complex clock and reset sequence
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 30/438 arm64: dts: renesas: r9a09g057: Switch GBETH TX queue scheduling to WRR
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ovidiu Panait <[email protected]>
[ Upstream commit 33da68f61d25ef8411489d06514ff627c1f88152 ]
The GBETH ethernet nodes don't specify a TX scheduling policy, so stmmac falls back to Strict Priority. In this configuration the queue with the highest priority gets all the traffic, starving the others under load.
Under sustained UDP TX load with multiple data streams, this starvation triggers spurious adapter resets due to TX queue timeouts:
iperf3 -c <ip> -i0 -t60 --bind-dev end0 -u -b0 -P4
end0: NETDEV WATCHDOG: CPU: 1: transmit queue 1 timed out 5228 ms
end0: Reset adapter.
Investigation shows that only the highest priority queue is advancing while the others stall for more than 5 seconds, causing a netdev watchdog reset.
Switch the TX scheduling policy to Weighted-Round-Robin (WRR) so that traffic is processed across all queues, eliminating the stalls.
--- arch/arm64/boot/dts/renesas/r9a09g057.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+)
arch/arm64/boot/dts/renesas/r9a09g057.dtsi +10 -0
@@ -1559,23 +1559,28 @@ queue3 { mtl_tx_setup0: tx-queues-config { snps,tx-queues-to-use = <4>; + snps,tx-sched-wrr; queue0 { + snps,weight = <0x10>; snps,dcb-algorithm; snps,priority = <0x1>; }; queue1 { + snps,weight = <0x12>; snps,dcb-algorithm; snps,priority = <0x2>; }; queue2 { + snps,weight = <0x14>; snps,dcb-algorithm; snps,priority = <0x4>; }; queue3 { + snps,weight = <0x18>; snps,dcb-algorithm; snps,priority = <0x8>; };
@@ -1660,23 +1665,28 @@ queue3 { mtl_tx_setup1: tx-queues-config { snps,tx-queues-to-use = <4>; + snps,tx-sched-wrr; queue0 { + snps,weight = <0x10>; snps,dcb-algorithm; snps,priority = <0x1>; }; queue1 { + snps,weight = <0x12>; snps,dcb-algorithm; snps,priority = <0x2>; }; queue2 { + snps,weight = <0x14>; snps,dcb-algorithm; snps,priority = <0x4>; }; queue3 { + snps,weight = <0x18>; snps,dcb-algorithm; snps,priority = <0x8>; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 31/438 arm64: dts: renesas: r9a09g056: Switch GBETH TX queue scheduling to WRR
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ovidiu Panait <[email protected]>
[ Upstream commit 66fcbdbeca0118b8aeac218b33fa18c394513543 ]
The GBETH ethernet nodes don't specify a TX scheduling policy, so stmmac falls back to Strict Priority. In this configuration the queue with the highest priority gets all the traffic, starving the others under load.
Under sustained UDP TX load with multiple data streams, this starvation triggers spurious adapter resets due to TX queue timeouts:
iperf3 -c <ip> -i0 -t60 --bind-dev end0 -u -b0 -P4
end0: NETDEV WATCHDOG: CPU: 1: transmit queue 1 timed out 5228 ms
end0: Reset adapter.
Investigation shows that only the highest priority queue is advancing while the others stall for more than 5 seconds, causing a netdev watchdog reset.
Switch the TX scheduling policy to Weighted-Round-Robin (WRR) so that traffic is processed across all queues, eliminating the stalls.
--- arch/arm64/boot/dts/renesas/r9a09g056.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+)
arch/arm64/boot/dts/renesas/r9a09g056.dtsi +10 -0
@@ -1569,23 +1569,28 @@ queue3 { mtl_tx_setup0: tx-queues-config { snps,tx-queues-to-use = <4>; + snps,tx-sched-wrr; queue0 { + snps,weight = <0x10>; snps,dcb-algorithm; snps,priority = <0x1>; }; queue1 { + snps,weight = <0x12>; snps,dcb-algorithm; snps,priority = <0x2>; }; queue2 { + snps,weight = <0x14>; snps,dcb-algorithm; snps,priority = <0x4>; }; queue3 { + snps,weight = <0x18>; snps,dcb-algorithm; snps,priority = <0x8>; };
@@ -1670,23 +1675,28 @@ queue3 { mtl_tx_setup1: tx-queues-config { snps,tx-queues-to-use = <4>; + snps,tx-sched-wrr; queue0 { + snps,weight = <0x10>; snps,dcb-algorithm; snps,priority = <0x1>; }; queue1 { + snps,weight = <0x12>; snps,dcb-algorithm; snps,priority = <0x2>; }; queue2 { + snps,weight = <0x14>; snps,dcb-algorithm; snps,priority = <0x4>; }; queue3 { + snps,weight = <0x18>; snps,dcb-algorithm; snps,priority = <0x8>; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 32/438 arm64: dts: renesas: r9a09g047: Switch GBETH TX queue scheduling to WRR
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ovidiu Panait <[email protected]>
[ Upstream commit 63016c3a91f2c458ca75869c8c782e899591f22d ]
The GBETH ethernet nodes don't specify a TX scheduling policy, so stmmac falls back to Strict Priority. In this configuration the queue with the highest priority gets all the traffic, starving the others under load.
Under sustained UDP TX load with multiple data streams, this starvation triggers spurious adapter resets due to TX queue timeouts:
iperf3 -c <ip> -i0 -t60 --bind-dev end0 -u -b0 -P4
end0: NETDEV WATCHDOG: CPU: 1: transmit queue 1 timed out 5228 ms
end0: Reset adapter.
Investigation shows that only the highest priority queue is advancing while the others stall for more than 5 seconds, causing a netdev watchdog reset.
Switch the TX scheduling policy to Weighted-Round-Robin (WRR) so that traffic is processed across all queues, eliminating the stalls.
--- arch/arm64/boot/dts/renesas/r9a09g047.dtsi | 10 ++++++++++ 1 file changed, 10 insertions(+)
arch/arm64/boot/dts/renesas/r9a09g047.dtsi +10 -0
@@ -1394,23 +1394,28 @@ queue3 { mtl_tx_setup0: tx-queues-config { snps,tx-queues-to-use = <4>; + snps,tx-sched-wrr; queue0 { + snps,weight = <0x10>; snps,dcb-algorithm; snps,priority = <0x1>; }; queue1 { + snps,weight = <0x12>; snps,dcb-algorithm; snps,priority = <0x2>; }; queue2 { + snps,weight = <0x14>; snps,dcb-algorithm; snps,priority = <0x4>; }; queue3 { + snps,weight = <0x18>; snps,dcb-algorithm; snps,priority = <0x8>; };
@@ -1494,23 +1499,28 @@ queue3 { mtl_tx_setup1: tx-queues-config { snps,tx-queues-to-use = <4>; + snps,tx-sched-wrr; queue0 { + snps,weight = <0x10>; snps,dcb-algorithm; snps,priority = <0x1>; }; queue1 { + snps,weight = <0x12>; snps,dcb-algorithm; snps,priority = <0x2>; }; queue2 { + snps,weight = <0x14>; snps,dcb-algorithm; snps,priority = <0x4>; }; queue3 { + snps,weight = <0x18>; snps,dcb-algorithm; snps,priority = <0x8>; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 33/438 arm64: dts: renesas: r9a09g077: Switch GBETH TX queue scheduling to WRR
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ovidiu Panait <[email protected]>
[ Upstream commit f9d9a1913c09366bf7b967d39575e06cb80128dc ]
The GBETH ethernet nodes don't specify a TX scheduling policy, so stmmac falls back to Strict Priority. In this configuration the queue with the highest priority gets all the traffic, starving the others under load.
Under sustained UDP TX load with multiple data streams, this starvation triggers spurious adapter resets due to TX queue timeouts:
iperf3 -c <ip> -i0 -t60 --bind-dev end0 -u -b0 -P4
end0: NETDEV WATCHDOG: CPU: 1: transmit queue 1 timed out 5228 ms
end0: Reset adapter.
Investigation shows that only the highest priority queue is advancing while the others stall for more than 5 seconds, causing a netdev watchdog reset.
Switch the TX scheduling policy to Weighted-Round-Robin (WRR) so that traffic is processed across all queues, eliminating the stalls.
--- arch/arm64/boot/dts/renesas/r9a09g077.dtsi | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+)
arch/arm64/boot/dts/renesas/r9a09g077.dtsi +27 -0
@@ -642,36 +642,45 @@ queue7 { mtl_tx_setup0: tx-queues-config { snps,tx-queues-to-use = <8>; + snps,tx-sched-wrr; queue0 { + snps,weight = <0x10>; snps,dcb-algorithm; }; queue1 { + snps,weight = <0x11>; snps,dcb-algorithm; }; queue2 { + snps,weight = <0x12>; snps,dcb-algorithm; }; queue3 { + snps,weight = <0x13>; snps,dcb-algorithm; }; queue4 { + snps,weight = <0x14>; snps,dcb-algorithm; }; queue5 { + snps,weight = <0x15>; snps,dcb-algorithm; }; queue6 { + snps,weight = <0x16>; snps,dcb-algorithm; }; queue7 { + snps,weight = <0x17>; snps,dcb-algorithm; }; };
@@ -788,36 +797,45 @@ queue7 { mtl_tx_setup1: tx-queues-config { snps,tx-queues-to-use = <8>; + snps,tx-sched-wrr; queue0 { + snps,weight = <0x10>; snps,dcb-algorithm; }; queue1 { + snps,weight = <0x11>; snps,dcb-algorithm; }; queue2 { + snps,weight = <0x12>; snps,dcb-algorithm; }; queue3 { + snps,weight = <0x13>; snps,dcb-algorithm; }; queue4 { + snps,weight = <0x14>; snps,dcb-algorithm; }; queue5 { + snps,weight = <0x15>; snps,dcb-algorithm; }; queue6 { + snps,weight = <0x16>; snps,dcb-algorithm; }; queue7 { + snps,weight = <0x17>; snps,dcb-algorithm; }; };
@@ -934,36 +952,45 @@ queue7 { mtl_tx_setup2: tx-queues-config { snps,tx-queues-to-use = <8>; + snps,tx-sched-wrr; queue0 { + snps,weight = <0x10>; snps,dcb-algorithm; }; queue1 { + snps,weight = <0x11>; snps,dcb-algorithm; }; queue2 { + snps,weight = <0x12>; snps,dcb-algorithm; }; queue3 { + snps,weight = <0x13>; snps,dcb-algorithm; }; queue4 { + snps,weight = <0x14>; snps,dcb-algorithm; }; queue5 { + snps,weight = <0x15>; snps,dcb-algorithm; }; queue6 { + snps,weight = <0x16>; snps,dcb-algorithm; }; queue7 { + snps,weight = <0x17>; snps,dcb-algorithm; }; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 34/438 arm64: dts: renesas: r9a09g087: Switch GBETH TX queue scheduling to WRR
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ovidiu Panait <[email protected]>
[ Upstream commit 2ac7bad110be6ebe478d6bd57821f7f5259a1f54 ]
The GBETH ethernet nodes don't specify a TX scheduling policy, so stmmac falls back to Strict Priority. In this configuration the queue with the highest priority gets all the traffic, starving the others under load.
Under sustained UDP TX load with multiple data streams, this starvation triggers spurious adapter resets due to TX queue timeouts:
iperf3 -c <ip> -i0 -t60 --bind-dev end0 -u -b0 -P4
end0: NETDEV WATCHDOG: CPU: 1: transmit queue 1 timed out 5228 ms
end0: Reset adapter.
Investigation shows that only the highest priority queue is advancing while the others stall for more than 5 seconds, causing a netdev watchdog reset.
Switch the TX scheduling policy to Weighted-Round-Robin (WRR) so that traffic is processed across all queues, eliminating the stalls.
--- arch/arm64/boot/dts/renesas/r9a09g087.dtsi | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+)
arch/arm64/boot/dts/renesas/r9a09g087.dtsi +27 -0
@@ -643,36 +643,45 @@ queue7 { mtl_tx_setup0: tx-queues-config { snps,tx-queues-to-use = <8>; + snps,tx-sched-wrr; queue0 { + snps,weight = <0x10>; snps,dcb-algorithm; }; queue1 { + snps,weight = <0x11>; snps,dcb-algorithm; }; queue2 { + snps,weight = <0x12>; snps,dcb-algorithm; }; queue3 { + snps,weight = <0x13>; snps,dcb-algorithm; }; queue4 { + snps,weight = <0x14>; snps,dcb-algorithm; }; queue5 { + snps,weight = <0x15>; snps,dcb-algorithm; }; queue6 { + snps,weight = <0x16>; snps,dcb-algorithm; }; queue7 { + snps,weight = <0x17>; snps,dcb-algorithm; }; };
@@ -790,36 +799,45 @@ queue7 { mtl_tx_setup1: tx-queues-config { snps,tx-queues-to-use = <8>; + snps,tx-sched-wrr; queue0 { + snps,weight = <0x10>; snps,dcb-algorithm; }; queue1 { + snps,weight = <0x11>; snps,dcb-algorithm; }; queue2 { + snps,weight = <0x12>; snps,dcb-algorithm; }; queue3 { + snps,weight = <0x13>; snps,dcb-algorithm; }; queue4 { + snps,weight = <0x14>; snps,dcb-algorithm; }; queue5 { + snps,weight = <0x15>; snps,dcb-algorithm; }; queue6 { + snps,weight = <0x16>; snps,dcb-algorithm; }; queue7 { + snps,weight = <0x17>; snps,dcb-algorithm; }; };
@@ -937,36 +955,45 @@ queue7 { mtl_tx_setup2: tx-queues-config { snps,tx-queues-to-use = <8>; + snps,tx-sched-wrr; queue0 { + snps,weight = <0x10>; snps,dcb-algorithm; }; queue1 { + snps,weight = <0x11>; snps,dcb-algorithm; }; queue2 { + snps,weight = <0x12>; snps,dcb-algorithm; }; queue3 { + snps,weight = <0x13>; snps,dcb-algorithm; }; queue4 { + snps,weight = <0x14>; snps,dcb-algorithm; }; queue5 { + snps,weight = <0x15>; snps,dcb-algorithm; }; queue6 { + snps,weight = <0x16>; snps,dcb-algorithm; }; queue7 { + snps,weight = <0x17>; snps,dcb-algorithm; }; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 35/438 IB/iser: reject a remote invalidation of an unregistered direction
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yehyeong Lee <[email protected]>
[ Upstream commit d85f0f0a7c85756fc992c70d869706f19dac9259 ]
A write command whose data is sent entirely as immediate data is not registered. iser_reg_mem_fastreg() takes the DMA key path and leaves rdma_reg[ISER_DIR_OUT].desc at NULL, while iser_dma_map_task_data() has already set dir[ISER_DIR_OUT].
iser_check_remote_inv() looks at dir[] alone and hands the descriptor to iser_inv_desc(), which reads desc->sig_protected. A target that answers such a command with IB_WR_SEND_WITH_INV faults the initiator. Leaving those commands unregistered is deliberate.
The same function already terminates the connection when a target sends a remote invalidation the initiator did not ask for. A target that invalidates a direction that was never registered is in the same class, so give it the same answer.
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000004: 0000 [#1] SMP KASAN NOPTI KASAN: null-ptr-deref in range [0x0000000000000020-0x0000000000000027] CPU: 0 UID: 0 PID: 40 Comm: kworker/u8:2 Not tainted 7.2.0-rc5-ISERHOST-gf5098b6bae76-dirty #3 PREEMPT(lazy) Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 Workqueue: rxe_wq do_work RIP: 0010:iser_task_rsp+0x6d6/0xec0 Code: 48 c1 ea 03 80 3c 02 00 0f 85 ba 06 00 00 48 8b 9b 78 01 00 00 48 b8 00 00 00 00 00 fc ff df 48 8d 7b 20 48 89 fa 48 c1 ea 03 <0f> b6 04 02 84 c0 74 06 0f 8e 76 06 00 00 80 7b 20 00 0f 84 3d 04 RSP: 0018:ffff88811b008db8 EFLAGS: 00010202 RAX: dffffc0000000000 RBX: 0000000000000000 RCX: 0000000000001848 RDX: 0000000000000004 RSI: 1ffff11021587b12 RDI: 0000000000000020 RBP: ffff88810adc1ae4 R08: ffff888109b7f860 R09: ffffffff90a922c0 R10: ffff88810adc1a1c R11: 000000000000003c R12: ffff888109b7f800 R13: ffff88810adc1acc R14: ffff888109b7f820 R15: 0000000000000000 FS: 0000000000000000(0000) GS:ffff88818a676000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000005afe2b CR3: 000000010af23005 CR4: 0000000000770ef0 PKRU: 55555554 Call Trace: <IRQ> __ib_process_cq+0xe1/0x390 ib_poll_handler+0x6e/0x200 irq_poll_softirq+0x1df/0x480 ? clockevents_program_event+0x2ba/0x860 ? __pfx_irq_poll_softirq+0x10/0x10 handle_softirqs+0x18e/0x590 ? __pfx_handle_softirqs+0x10/0x10 ? __hrtimer_rearm_deferred+0x156/0x450 do_softirq+0x3b/0x60 </IRQ> <TASK> __local_bh_enable_ip+0x61/0x70 __alloc_skb+0x732/0x890 ? _raw_spin_lock_irqsave+0x85/0xe0 ? __pfx___alloc_skb+0x10/0x10 ? _raw_read_unlock_irqrestore+0x16/0x50 rxe_init_packet+0x16b/0x4f0 prepare_ack_packet+0xb8/0x830 rxe_receiver+0x499/0x9980 ? __pfx_rxe_receiver+0x10/0x10 ? rxe_completer+0x29e5/0x38c0 ? hrtimer_start_range_ns_common+0x75f/0x1730 ? hrtimer_start_range_ns+0xa6/0x2c0 ? __pfx__raw_spin_lock_irqsave+0x10/0x10 ? __pfx_rxe_receiver+0x10/0x10 do_work+0x144/0x470 process_one_work+0x633/0x1030 ? assign_work+0x11d/0x370 worker_thread+0x45b/0xd10 ? __pfx_worker_thread+0x10/0x10 kthread+0x2c6/0x3b0 ? recalc_sigpending+0x15c/0x1e0 ? __pfx_kthread+0x10/0x10 ret_from_fork+0x36e/0x5a0 ? __pfx_ret_from_fork+0x10/0x10 ? __switch_to+0x572/0xdd0 ? __pfx_kthread+0x10/0x10 ret_from_fork_asm+0x1a/0x30 </TASK> Modules linked in: ---[ end trace 0000000000000000 ]---
--- drivers/infiniband/ulp/iser/iser_initiator.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
drivers/infiniband/ulp/iser/iser_initiator.c +11 -5
@@ -598,11 +598,8 @@ static int iser_check_remote_inv(struct iser_conn *iser_conn, struct ib_wc *wc,iser_dbg ("conn %p: remote invalidation for rkey %#x\n" , iser_conn, rkey); -if (unlikely (!iser_conn->snd_w_inv)) { -iser_err ("conn %p: unexpected remote invalidation, terminating connection\n" , - iser_conn); -return -EPROTO ; - } +if (unlikely (!iser_conn->snd_w_inv)) + goto bad_inv; task =iscsi_itt_to_ctask (iser_conn->iscsi_conn, hdr->itt);if (likely (task)) {
@@ -611,12 +608,16 @@ static int iser_check_remote_inv(struct iser_conn *iser_conn, struct ib_wc *wc,if (iser_task->dir[ISER_DIR_IN ]) { desc = iser_task->rdma_reg[ISER_DIR_IN ].desc; +if (unlikely (!desc)) + goto bad_inv;if (unlikely (iser_inv_desc (desc, rkey)))return -EINVAL ; }if (iser_task->dir[ISER_DIR_OUT ]) { desc = iser_task->rdma_reg[ISER_DIR_OUT ].desc; +if (unlikely (!desc)) + goto bad_inv;if (unlikely (iser_inv_desc (desc, rkey)))return -EINVAL ; }
@@ -627,6 +628,11 @@ static int iser_check_remote_inv(struct iser_conn *iser_conn, struct ib_wc *wc, }return 0 ; + +bad_inv: +iser_err ("conn %p: unexpected remote invalidation, terminating connection\n" , + iser_conn); +return -EPROTO ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 36/438 IB/isert: wait for deferred control PDU completions before releasing the connection
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yehyeong Lee <[email protected]>
[ Upstream commit a8fe3dfce8c0d8a76dc3d8486a5bff5feebe156f ]
isert_send_done() hands ISTATE_SEND_TASKMGTRSP, ISTATE_SEND_REJECT and ISTATE_SEND_TEXTRSP completions off to isert_comp_wq and returns. The work item then runs isert_completion_put() -> isert_put_cmd(), which reads isert_conn->conn and takes conn->cmd_lock.
Nothing orders that work item against teardown. isert_wait_conn() queues isert_release_work, which frees isert_conn, and iscsit_close_connection() frees the iscsit_conn right after it returns, so the queued work can run against freed memory.
Count the deferred control PDU completions per connection and let isert_wait_conn() wait for them before the release work is queued.
ISTATE_SEND_LOGOUTRSP is deliberately not counted: that branch runs iscsit_logout_post_handler(), which ends up waiting for conn->conn_wait_comp, and that completion is only sent by iscsit_close_connection() after it has called iscsit_wait_conn(). Waiting for it here would deadlock. Its wait stays the existing isert_wait4logout().
The splat below is from a kernel with tracing printk()s and an msleep(200) injected into isert_do_control_comp() to widen the window:
BUG: KASAN: slab-use-after-free in isert_put_cmd+0x53d/0x620 Read of size 8 at addr ffff8881054f1038 by task kworker/u17:1/182 CPU: 0 UID: 0 PID: 182 Comm: kworker/u17:1 Tainted: G B 7.2.0-rc5-TWIDE-gb8babf08acc7 #1 PREEMPT(lazy) Tainted: [B]=BAD_PAGE Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 Workqueue: isert_comp_wq isert_do_control_comp Call Trace: <TASK> dump_stack_lvl+0x53/0x70 print_report+0xd0/0x630 ? __pfx__raw_spin_lock_irqsave+0x10/0x10 ? _raw_spin_unlock_irqrestore+0x3e/0x70 ? isert_put_cmd+0x53d/0x620 kasan_report+0xce/0x100 ? isert_put_cmd+0x53d/0x620 isert_put_cmd+0x53d/0x620 ? isert_completion_put+0x305/0x330 ? isert_do_control_comp+0x2ef/0x310 process_one_work+0x633/0x1030 ? assign_work+0x11d/0x370 worker_thread+0x45b/0xd10 ? __pfx_worker_thread+0x10/0x10 ? __pfx_worker_thread+0x10/0x10 kthread+0x2c6/0x3b0 ? recalc_sigpending+0x15c/0x1e0 ? __pfx_kthread+0x10/0x10 ret_from_fork+0x36e/0x5a0 ? __pfx_ret_from_fork+0x10/0x10 ? __switch_to+0x572/0xdd0 ? __pfx_kthread+0x10/0x10 ret_from_fork_asm+0x1a/0x30 </TASK> Allocated by task 48: kasan_save_stack+0x33/0x60 kasan_save_track+0x14/0x30 __kasan_kmalloc+0x8f/0xa0 __kmalloc_cache_noprof+0x158/0x370 isert_cma_handler+0x1e3/0x2ae0 cma_cm_event_handler+0x3e/0x240 cma_ib_req_handler+0x17d9/0x4490 cm_process_work+0x41/0x330 cm_work_handler+0x5727/0xc160 process_one_work+0x633/0x1030 worker_thread+0x45b/0xd10 kthread+0x2c6/0x3b0 ret_from_fork+0x36e/0x5a0 ret_from_fork_asm+0x1a/0x30 Freed by task 184: kasan_save_stack+0x33/0x60 kasan_save_track+0x14/0x30 kasan_save_free_info+0x3b/0x60 __kasan_slab_free+0x43/0x70 kfree+0x121/0x380 iscsit_close_connection+0x7cf/0x1e60 iscsit_take_action_for_connection_exit+0x1b6/0x360 iscsi_target_tx_thread+0x472/0x690 kthread+0x2c6/0x3b0 ret_from_fork+0x36e/0x5a0 ret_from_fork_asm+0x1a/0x30
--- drivers/infiniband/ulp/isert/ib_isert.c | 22 ++++++++++++++++++++++ drivers/infiniband/ulp/isert/ib_isert.h | 2 ++ 2 files changed, 24 insertions(+)
drivers/infiniband/ulp/isert/ib_isert.c +22 -0
@@ -21,6 +21,7 @@#include <target/target_core_fabric.h> #include <target/iscsi/iscsi_transport.h> #include <linux/semaphore.h> +#include <linux/wait_bit.h> #include "ib_isert.h"
@@ -310,6 +311,7 @@ isert_init_conn(struct isert_conn *isert_conn)init_completion (&isert_conn->login_req_comp);init_waitqueue_head (&isert_conn->rem_wait);kref_init (&isert_conn->kref); +atomic_set (&isert_conn->ctrl_comp_cnt,0 );mutex_init (&isert_conn->mutex);INIT_WORK (&isert_conn->release_work, isert_release_work); }
@@ -1695,6 +1697,8 @@ isert_do_control_comp(struct work_struct *work)struct isert_conn *isert_conn = isert_cmd->conn;struct ib_device *ib_dev = isert_conn->cm_id->device;struct iscsit_cmd *cmd = isert_cmd->iscsit_cmd; +/* The switch below may free isert_cmd. */ +bool counted = isert_cmd->ctrl_counted;isert_dbg ("Cmd %p i_state %d\n" , isert_cmd, cmd->i_state);
@@ -1716,6 +1720,14 @@ isert_do_control_comp(struct work_struct *work)dump_stack ();break ; } + +/* +* The count is what keeps isert_conn alive, so drop it last. The wait +* queue lives in the global hash table, not in isert_conn, so this is +* safe even if the waiter has already freed the connection. +*/ +if (counted &&atomic_dec_and_test (&isert_conn->ctrl_comp_cnt)) +wake_up_var (&isert_conn->ctrl_comp_cnt); } static void
@@ -1759,6 +1771,12 @@ isert_send_done(struct ib_cq *cq, struct ib_wc *wc)case ISTATE_SEND_TEXTRSP :isert_unmap_tx_desc (tx_desc, ib_dev); +/* Paired with the wait in isert_wait_conn(). */ + isert_cmd->ctrl_counted = + isert_cmd->iscsit_cmd->i_state !=ISTATE_SEND_LOGOUTRSP ; +if (isert_cmd->ctrl_counted) +atomic_inc (&isert_conn->ctrl_comp_cnt); +INIT_WORK (&isert_cmd->comp_work, isert_do_control_comp);queue_work (isert_comp_wq, &isert_cmd->comp_work);return ;
@@ -2603,6 +2621,10 @@ static void isert_wait_conn(struct iscsit_conn *conn)isert_wait4cmds (conn);isert_wait4logout (isert_conn); +/* Paired with the count taken in isert_send_done(). */ +wait_var_event (&isert_conn->ctrl_comp_cnt, + !atomic_read (&isert_conn->ctrl_comp_cnt)); +queue_work (isert_release_wq, &isert_conn->release_work); }
drivers/infiniband/ulp/isert/ib_isert.h +2 -0
@@ -153,6 +153,7 @@ struct isert_cmd {struct work_struct comp_work;struct scatterlist sg;bool ctx_init_done; +bool ctrl_counted; };static inline struct isert_cmd *tx_desc_to_cmd (struct iser_tx_desc *desc)
@@ -187,6 +188,7 @@ struct isert_conn {struct mutex mutex;struct kref kref;struct work_struct release_work; +atomic_t ctrl_comp_cnt;bool logout_posted;bool snd_w_inv;wait_queue_head_t rem_wait;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 37/438 RDMA/bnxt_re: check create_singlethread_workqueue() in DCB setup
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linkai Gong <[email protected]>
[ Upstream commit 6c368f7baaea63c1c7c28c6df271511f2a1562c9 ]
bnxt_re_init_dcb_wq() ignores a failed allocation. The async DCB handler later calls queue_work() on the NULL pointer.
--- drivers/infiniband/hw/bnxt_re/main.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
drivers/infiniband/hw/bnxt_re/main.c +8 -2
@@ -356,9 +356,13 @@ static int bnxt_re_update_qp1_tos_dscp(struct bnxt_re_dev *rdev)return bnxt_qplib_modify_qp (&rdev->qplib_res, &qp->qplib_qp); } -static void bnxt_re_init_dcb_wq (struct bnxt_re_dev *rdev) +static int bnxt_re_init_dcb_wq (struct bnxt_re_dev *rdev) { rdev->dcb_wq =create_singlethread_workqueue ("bnxt_re_dcb_wq" ); +if (!rdev->dcb_wq) +return -ENOMEM ; + +return 0 ; }static void bnxt_re_uninit_dcb_wq (struct bnxt_re_dev *rdev)
@@ -2343,7 +2347,9 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 op_type)bnxt_re_debugfs_add_pdev (rdev); -bnxt_re_init_dcb_wq (rdev); + rc =bnxt_re_init_dcb_wq (rdev); +if (rc) + goto fail;bnxt_re_net_register_async_event (rdev);if (!rdev->is_virtfn)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 38/438 RDMA/rtrs: guard against null kobj name
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryan Mehri <[email protected]>
[ Upstream commit 99c24a8968ebef0573825b5cb89d5985d51635b9 ]
In the client, if init_path() errors, the callee tries to clean up with rtrs_clt_close_conns(). However, this can lead to calling the event tracing code with clt_path->kobj->name being NULL and thus causing a null pointer dereference when trying to copy from it.
This just adds a guard to check that the name is not NULL before copying from it. The server appears to have a similar pattern.
--- drivers/infiniband/ulp/rtrs/rtrs-clt-trace.h | 2 +- drivers/infiniband/ulp/rtrs/rtrs-srv-trace.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/infiniband/ulp/rtrs/rtrs-clt-trace.h +1 -1
@@ -55,7 +55,7 @@ DECLARE_EVENT_CLASS(rtrs_clt_conn_class, __entry->max_reconnect_attempts = clt->max_reconnect_attempts; __entry->fail_cnt = clt_path->stats->reconnects.fail_cnt; __entry->success_cnt = clt_path->stats->reconnects.successful_cnt; -memcpy (__entry->sessname,kobject_name (&clt_path->kobj),NAME_MAX ); +strscpy (__entry->sessname,kobject_name (&clt_path->kobj) ?:"" ,NAME_MAX ); ), TP_printk("RTRS-CLT: sess='%s' state=%s attempts='%d' max-attempts='%d' fail='%d' success='%d'",
drivers/infiniband/ulp/rtrs/rtrs-srv-trace.h +1 -1
@@ -61,7 +61,7 @@ TRACE_EVENT(send_io_resp_imm, __entry->msg_id = id->msg_id; __entry->wr_cnt =atomic_read (&con->c.wr_cnt); __entry->signal_interval = s->signal_interval; -memcpy (__entry->sessname,kobject_name (&srv_path->kobj),NAME_MAX ); +strscpy (__entry->sessname,kobject_name (&srv_path->kobj) ?:"" ,NAME_MAX ); ), TP_printk("sess='%s' state='%s' dir=%s err='%d' inval='%d' glob-inval='%d' msgid='%u' wrcnt='%d' sig-interval='%u'",
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 39/438 RDMA/bnxt_re: Avoid exposing umdbr to userspace
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sriharsha Basavapatna <[email protected]>
[ Upstream commit 23d7e03a52ece66b992620aa9b8fa5f164077c0f ]
The umdbr field in struct bnxt_re_db_region returns the raw unmapped PCI BAR address of the doorbell region. Avoid sharing this field to the userspace. Change this to a reserved field and stop populating it, keeping the ABI layout and size unchanged for existing binaries.
--- drivers/infiniband/hw/bnxt_re/uapi.c | 6 ++---- include/uapi/rdma/bnxt_re-abi.h | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-)
drivers/infiniband/hw/bnxt_re/uapi.c +2 -4
@@ -409,7 +409,6 @@ static int UVERBS_HANDLER(BNXT_RE_METHOD_DBR_ALLOC)(struct uverbs_attr_bundle *a uobj->object = obj;uverbs_finalize_uobj_create (attrs,BNXT_RE_ALLOC_DBR_HANDLE ); - dbr.umdbr = dpi->umdbr; dbr.dpi = dpi->dpi; ret =uverbs_copy_to_struct_or_zero (attrs,BNXT_RE_ALLOC_DBR_ATTR , &dbr,sizeof (dbr));
@@ -472,7 +471,6 @@ static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_DEFAULT_DBR)(struct uverbs_attr_bunreturn PTR_ERR (ib_uctx); uctx = container_of(ib_uctx, struct bnxt_re_ucontext, ib_uctx); - dpi.umdbr = uctx->dpi.umdbr; dpi.dpi = uctx->dpi.dpi; ret = uverbs_copy_to_struct_or_zero(attrs, BNXT_RE_DEFAULT_DBR_ATTR,
@@ -490,7 +488,7 @@ DECLARE_UVERBS_NAMED_METHOD(BNXT_RE_METHOD_DBR_ALLOC, UA_MANDATORY),UVERBS_ATTR_PTR_OUT (BNXT_RE_ALLOC_DBR_ATTR , UVERBS_ATTR_STRUCT(struct bnxt_re_db_region, - umdbr), + reserved2),UA_MANDATORY ), UVERBS_ATTR_PTR_OUT(BNXT_RE_ALLOC_DBR_OFFSET, UVERBS_ATTR_TYPE(u64),
@@ -510,7 +508,7 @@ DECLARE_UVERBS_NAMED_OBJECT(BNXT_RE_OBJECT_DBR,DECLARE_UVERBS_NAMED_METHOD (BNXT_RE_METHOD_GET_DEFAULT_DBR ,UVERBS_ATTR_PTR_OUT (BNXT_RE_DEFAULT_DBR_ATTR , UVERBS_ATTR_STRUCT(struct bnxt_re_db_region, - umdbr), + reserved2),UA_MANDATORY )); DECLARE_UVERBS_GLOBAL_METHODS(BNXT_RE_OBJECT_DEFAULT_DBR,
include/uapi/rdma/bnxt_re-abi.h +1 -1
@@ -247,7 +247,7 @@ struct bnxt_re_query_device_ex_resp {struct bnxt_re_db_region {__u32 dpi;__u32 reserved; -__aligned_u64 umdbr; +__aligned_u64 reserved2; };enum bnxt_re_obj_dbr_alloc_attrs {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 40/438 RDMA/uverbs: Fix potential leak of resources->collection in flow_resources_alloc()
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li RongQing <[email protected]>
[ Upstream commit 08d4d9802d58bf032099091e6acf719f3298f28e ]
The two array allocations are done unconditionally and only checked afterwards, so if the counters allocation fails while the collection allocation succeeds, the error path frees counters and the containing struct but never frees resources->collection, losing the only pointer to it.
--- drivers/infiniband/core/uverbs_flow.c | 1 + 1 file changed, 1 insertion(+)
drivers/infiniband/core/uverbs_flow.c +1 -0
@@ -26,6 +26,7 @@ struct ib_uflow_resources *flow_resources_alloc(size_t num_specs)return resources; err: +kfree (resources->collection);kfree (resources->counters);kfree (resources);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 41/438 RDMA/mad: Fix receive buffer leak when PKey enforcement fails
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li RongQing <[email protected]>
[ Upstream commit 3476c28c9addfa253f505e6bd87f1f5598b961d0 ]
ib_mad_complete_recv() initializes mad_recv_wc->rmpp_list and then runs ib_mad_enforce_security() before linking recv_buf onto that list. On failure it calls ib_free_recv_mad(), which only walks rmpp_list and frees the ib_mad_private of every buffer found there. As the list is still empty at that point, nothing is freed at all.
The caller cannot clean up either: ib_mad_recv_done() sets recv to NULL right after ib_mad_complete_recv() returns, assuming the MAD layer took ownership of the buffer. Every MAD that fails the PKey check therefore leaks one ib_mad_private (about 300 bytes per IB port MAD, ~2K for OPA), and a remote node can trigger this repeatedly by sending MADs with a wrong PKey.
Link recv_buf onto rmpp_list right after the list is initialized, so the error path has something to free.
--- drivers/infiniband/core/mad.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/infiniband/core/mad.c +2 -1
@@ -2059,6 +2059,8 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,int ret;INIT_LIST_HEAD (&mad_recv_wc->rmpp_list); +list_add (&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list); + ret =ib_mad_enforce_security (mad_agent_priv, mad_recv_wc->wc->pkey_index);if (ret) {
@@ -2067,7 +2069,6 @@ static void ib_mad_complete_recv(struct ib_mad_agent_private *mad_agent_priv,return ; } -list_add (&mad_recv_wc->recv_buf.list, &mad_recv_wc->rmpp_list);if (is_kernel_rmpp_data_response (mad_agent_priv, mad_recv_wc)) {spin_lock_irqsave (&mad_agent_priv->lock, flags); mad_send_wr =ib_find_send_mad (mad_agent_priv, mad_recv_wc);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 42/438 RDMA/erdma: Use IRQ-safe XArray helpers for QP and CQ tables
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cheng Xu <[email protected]>
[ Upstream commit 00baeade709fb66da647e8327e8398bb532e30f7 ]
Locked QP and CQ lookups from EQ interrupts can deadlock with create-path XArray updates. If an interrupt arrives while the create path holds the plain xa_lock, the lookup spins forever trying to acquire the same lock.
Use IRQ-safe XArray helpers for all QP and CQ create-path updates, including the GSI QP store and error paths. Initialize both arrays with XA_FLAGS_LOCK_IRQ so sleeping allocations preserve interrupt state.
--- drivers/infiniband/hw/erdma/erdma_main.c | 4 ++-- drivers/infiniband/hw/erdma/erdma_verbs.c | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-)
drivers/infiniband/hw/erdma/erdma_main.c +2 -2
@@ -572,8 +572,8 @@ static int erdma_ib_device_add(struct pci_dev *pdev)INIT_LIST_HEAD (&dev->cep_list);spin_lock_init (&dev->lock); -xa_init_flags (&dev->qp_xa,XA_FLAGS_ALLOC1 ); -xa_init_flags (&dev->cq_xa,XA_FLAGS_ALLOC1 ); +xa_init_flags (&dev->qp_xa,XA_FLAGS_ALLOC1 |XA_FLAGS_LOCK_IRQ ); +xa_init_flags (&dev->cq_xa,XA_FLAGS_ALLOC1 |XA_FLAGS_LOCK_IRQ ); dev->next_alloc_cqn =1 ; dev->next_alloc_qpn =1 ;
drivers/infiniband/hw/erdma/erdma_verbs.c +9 -9
@@ -1023,15 +1023,15 @@ int erdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,init_completion (&qp->safe_free);if (qp->ibqp.qp_type ==IB_QPT_GSI ) { - old_entry =xa_store (&dev->qp_xa,1 , qp,GFP_KERNEL ); + old_entry =xa_store_irq (&dev->qp_xa,1 , qp,GFP_KERNEL );if (xa_is_err (old_entry)) ret =xa_err (old_entry);else qp->ibqp.qp_num =1 ; }else { - ret =xa_alloc_cyclic (&dev->qp_xa, &qp->ibqp.qp_num, qp, -XA_LIMIT (1 , dev->attrs.max_qp -1 ), - &dev->next_alloc_qpn,GFP_KERNEL ); + ret =xa_alloc_cyclic_irq (&dev->qp_xa, &qp->ibqp.qp_num, qp, +XA_LIMIT (1 , dev->attrs.max_qp -1 ), + &dev->next_alloc_qpn,GFP_KERNEL ); }if (ret <0 ) {
@@ -1091,7 +1091,7 @@ int erdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,else free_kernel_qp (qp); err_out_xa: -xa_erase (&dev->qp_xa,QP_ID (qp)); +xa_erase_irq (&dev->qp_xa,QP_ID (qp)); err_out:return ret; }
@@ -1995,9 +1995,9 @@ int erdma_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,refcount_set (&cq->refcount,1 );init_completion (&cq->free); - ret =xa_alloc_cyclic (&dev->cq_xa, &cq->cqn, cq, -XA_LIMIT (1 , dev->attrs.max_cq -1 ), - &dev->next_alloc_cqn,GFP_KERNEL ); + ret =xa_alloc_cyclic_irq (&dev->cq_xa, &cq->cqn, cq, +XA_LIMIT (1 , dev->attrs.max_cq -1 ), + &dev->next_alloc_cqn,GFP_KERNEL );if (ret <0 )return ret;
@@ -2043,7 +2043,7 @@ int erdma_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr, } err_out_xa: -xa_erase (&dev->cq_xa, cq->cqn); +xa_erase_irq (&dev->cq_xa, cq->cqn);return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 43/438 RDMA/irdma: Enforce local fence for IB_WR_REG_MR
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jacob Moroni <[email protected]>
[ Upstream commit 3fb905f07ea45b31c8f67ba6e4668de46f527e65 ]
Enforce local fence for IB_WR_REG_MR to avoid spurious FASTREG_VALID_MKEY async events during heavy invalidation and registration activity.
Commit 69e8e429bca2 ("RDMA/irdma: Enforce local fence for LOCAL_INV WRs") was very similar, but was not sufficient to prevent all occurrences of these async events.
--- drivers/infiniband/hw/irdma/verbs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/hw/irdma/verbs.c +1 -1
@@ -4244,7 +4244,7 @@ static int irdma_post_send(struct ib_qp *ibqp, stag_info.total_len = iwmr->ibmr.length; stag_info.reg_addr_pa = *palloc->level1.addr; stag_info.first_pm_pbl_index = palloc->level1.idx; - stag_info.local_fence = ib_wr->send_flags &IB_SEND_FENCE ; + stag_info.local_fence = true;if (iwmr->npages >IRDMA_MIN_PAGES_PER_FMR ) stag_info.chunk_size =1 ; err = irdma_sc_mr_fast_register(&iwqp->sc_qp, &stag_info,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 44/438 RDMA/rtrs-clt: Fix CQ pool leak when connect is interrupted
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Quanye Yang <[email protected]>
[ Upstream commit 2ae16aaa78b5edc6e6d0904c84fd9cdfb762bcda ]
The client borrows shared CQ credits in the ADDR_RESOLVED handler via ib_cq_pool_get(), before the peer is connected. create_cm() can return -ERESTARTSYS from wait_event_interruptible_timeout() without destroying the CM ID. The init_conns() and stop-and-destroy paths then call destroy_con_cq_qp() while cq is still NULL (no PUT) and only afterwards rdma_destroy_id().
CMA serializes the handler against rdma_destroy_id() with handler_mutex, but that does not order the GET against destroy_con_cq_qp(). If ADDR_RESOLVED has already passed the DESTROYING check, it can take con_mutex, GET credits, and then lose the con to kfree. Device unregister later hits WARN_ON(cq->cqe_used) in ib_cq_pool_cleanup().
Set a per-connection flag under con_mutex before CQ/QP teardown so a racing ADDR_RESOLVED cannot borrow credits after teardown has begun.
--- drivers/infiniband/ulp/rtrs/rtrs-clt.c | 8 ++++++++ drivers/infiniband/ulp/rtrs/rtrs-clt.h | 2 ++ 2 files changed, 10 insertions(+)
drivers/infiniband/ulp/rtrs/rtrs-clt.c +8 -0
@@ -1735,6 +1735,8 @@ static void destroy_con_cq_qp(struct rtrs_clt_con *con)/* * Be careful here: destroy_con_cq_qp() can be called even * create_con_cq_qp() failed, see comments there. +* Caller must set con->destroyed under this lock first so a +* racing ADDR_RESOLVED cannot ib_cq_pool_get() after we PUT/SKIP. */ lockdep_assert_held (&con->con_mutex);rtrs_cq_qp_destroy (&con->c);
@@ -1769,6 +1771,10 @@ static int rtrs_rdma_addr_resolved(struct rtrs_clt_con *con)int err;mutex_lock (&con->con_mutex); +if (con->destroyed) { +mutex_unlock (&con->con_mutex); +return -ECONNABORTED ; + } err =create_con_cq_qp (con);mutex_unlock (&con->con_mutex);if (err) {
@@ -2224,6 +2230,7 @@ static void rtrs_clt_stop_and_destroy_conns(struct rtrs_clt_path *clt_path)break ; con =to_clt_con (clt_path->s.con[cid]);mutex_lock (&con->con_mutex); + con->destroyed = true;destroy_con_cq_qp (con);mutex_unlock (&con->con_mutex);destroy_cm (con);
@@ -2390,6 +2397,7 @@ static int init_conns(struct rtrs_clt_path *clt_path)if (con->c.cm_id) {stop_cm (con);mutex_lock (&con->con_mutex); + con->destroyed = true;destroy_con_cq_qp (con);mutex_unlock (&con->con_mutex);destroy_cm (con);
drivers/infiniband/ulp/rtrs/rtrs-clt.h +2 -0
@@ -75,6 +75,8 @@ struct rtrs_clt_con {unsigned int cpu;struct mutex con_mutex;int cm_err; +/* Set under con_mutex before CQ/QP teardown. */ +bool destroyed; };/**
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 45/438 dmaengine: mmp_pdma: fix wrong extended DRCMR base for SpacemiT K3
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Troy Mitchell <[email protected]>
[ Upstream commit d1fc569fcbc7be6de06b034cf954a95e30ca1fb2 ]
The extended DRCMR window on SpacemiT K3 starts at 0x1100. Commit 6587b8661a0b ("dmaengine: mmp_pdma: add SpacemiT K3 support") incorrectly set it to 0x1000, causing DRCMR accesses for request IDs >= 64 to target offsets 0x100 too low.
The 0x1100 base has been verified on K3 silicon using real SPI and QSPI DMA transactions. The K3 DMA documentation [1] was updated on June 24, 2026, to reflect the corrected register addresses.
Drop the bogus DRCMR_EXT_BASE_K3 macro and reuseDRCMR_EXT_BASE_DEFAULT for the K3 ops.
--- drivers/dma/mmp_pdma.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/dma/mmp_pdma.c +1 -2
@@ -52,7 +52,6 @@#define DCSR_EORINTR BIT(9)/* The end of Receive */ #define DRCMR_BASE 0x0100 -#define DRCMR_EXT_BASE_K3 0x1000#define DRCMR_EXT_BASE_DEFAULT 0x1100#define DRCMR_REQ_LIMIT 64#define DRCMR_MAPVLD BIT(7)/* Map Valid (read / write) */
@@ -1219,7 +1218,7 @@ static const struct mmp_pdma_ops spacemit_k3_pdma_ops = { .get_desc_dst_addr = get_desc_dst_addr_64, .run_bits = (DCSR_RUN | DCSR_LPAEEN | DCSR_EORIRQEN | DCSR_EORSTOPEN), .dma_width = 64, - .drcmr_ext_base = DRCMR_EXT_BASE_K3, + .drcmr_ext_base = DRCMR_EXT_BASE_DEFAULT, };static const struct of_device_id mmp_pdma_dt_ids[] = {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 46/438 dmaengine: sprd: Fix runtime PM reference leak in probe
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <[email protected]>
[ Upstream commit a7df136ec529ee49a789c5029bc37b98b0d4bedd ]
pm_runtime_get_sync() increments a device's usage counter even when it fails. sprd_dma_probe() currently jumps directly to controller clock cleanup on that error, bypassing both pm_runtime_put_noidle() and pm_runtime_disable(). This can happen if the preceding unchecked pm_runtime_set_active() fails and the following runtime-resume attempt also returns an error.
Enter the existing runtime-PM unwind path instead. This drops the reference without idling the partially initialized device, disables runtime PM, and then releases the controller clocks. The success path and propagated error code are unchanged.
This issue was found by a static analysis checker and confirmed by manual source review.
--- drivers/dma/sprd-dma.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/dma/sprd-dma.c +1 -2
@@ -1212,7 +1212,7 @@ static int sprd_dma_probe(struct platform_device *pdev) ret =pm_runtime_get_sync (&pdev->dev);if (ret <0 ) - goto err_rpm; + goto err_register; ret =dma_async_device_register (&sdev->dma_dev);if (ret <0 ) {
@@ -1234,7 +1234,6 @@ static int sprd_dma_probe(struct platform_device *pdev) err_register:pm_runtime_put_noidle (&pdev->dev);pm_runtime_disable (&pdev->dev); -err_rpm:sprd_dma_disable (sdev);return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 47/438 wifi: mac80211: include TIM bitmap control for buffered S1G mcast traffic
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lachlan Hodges <[email protected]>
[ Upstream commit af72b5946d493cecced27d0951ea37c1d178601e ]
Currently when building the S1G TIM element, we only build the bitmap control if we have buffered unicast traffic. Since AID 0 sits within the bitmap control if we have buffered multicast traffic with no buffered unicast traffic the bitmap control won't be emitted and dozing stations will be unaware of buffered multicast.
To fix, only exclude the bitmap control byte when we don't have both buffered unicast and multicast traffic.
--- net/mac80211/tx.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-)
net/mac80211/tx.c +22 -19
@@ -5063,10 +5063,18 @@ static void ieee80211_beacon_add_tim_pvb(struct ps_data *ps,*/ static void ieee80211_s1g_beacon_add_tim_pvb (struct ps_data *ps,struct sk_buff *skb, -bool mcast_traffic) +bool mcast_traffic, +bool ucast_traffic) {int blk; +/* +* if no unicast and multicast traffic don't emit a bitmap control +* or pvb +*/ +if (!mcast_traffic && !ucast_traffic) +return ; +/* * Emit a bitmap control block with a page slice number of 31 and a * page index of 0 which indicates as per IEEE80211-2024 9.4.2.5.1
@@ -5075,6 +5083,10 @@ static void ieee80211_s1g_beacon_add_tim_pvb(struct ps_data *ps,*/ skb_put_u8 (skb, mcast_traffic | (31 <<1 )); +/* If there's no unicast traffic we don't need to include a PVB. */ +if (!ucast_traffic) +return ; +/* Emit an encoded block for each non-zero sub-block */ for (blk =0 ; blk <IEEE80211_MAX_SUPPORTED_S1G_TIM_BLOCKS ; blk++) {u8 blk_bmap =0 ;
@@ -5156,25 +5168,16 @@ static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, ps->dtim_bc_mc = mcast_traffic; -if (have_bits) { -if (s1g) -ieee80211_s1g_beacon_add_tim_pvb (ps, skb, - mcast_traffic); -else -ieee80211_beacon_add_tim_pvb (ps, skb, mcast_traffic); +if (s1g) { +ieee80211_s1g_beacon_add_tim_pvb (ps, skb, mcast_traffic, + have_bits); + }else if (have_bits) { +ieee80211_beacon_add_tim_pvb (ps, skb, mcast_traffic); }else { -/* -* If there is no buffered unicast traffic for an S1G -* interface, we can exclude the bitmap control. This is in -* contrast to other phy types as they do include the bitmap -* control and pvb even when there is no buffered traffic. -*/ -if (!s1g) { -/* Bitmap control */ -skb_put_u8 (skb, mcast_traffic); -/* Part Virt Bitmap */ -skb_put_u8 (skb,0 ); - } +/* Bitmap control */ +skb_put_u8 (skb, mcast_traffic); +/* Part Virt Bitmap */ +skb_put_u8 (skb,0 ); } tim->datalen =skb_tail_pointer (skb) - tim->data;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 48/438 wifi: virt_wifi: free skb when disconnected
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mariano Baragiola <[email protected]>
[ Upstream commit f9edf7cf63b96d2b776fca8d258d3c5256e40c8e ]
When the simulated link is disconnected, virt_wifi_start_xmit() returns NET_XMIT_DROP without freeing the skb. dev_hard_start_xmit() treats this return value as consumed, so every packet sent while disconnected leaks its skb.
Free the skb before returning the drop status.
--- drivers/net/wireless/virtual/virt_wifi.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/wireless/virtual/virt_wifi.c +1 -0
@@ -434,6 +434,7 @@ static netdev_tx_t virt_wifi_start_xmit(struct sk_buff *skb, priv->tx_packets++;if (!priv->is_connected) { priv->tx_failed++; +dev_kfree_skb_any (skb);return NET_XMIT_DROP ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 49/438 wifi: mwifiex: fix IRQ leak using wrong index in MSI-X error path
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peng Hao <[email protected]>
[ Upstream commit a3d722190cdef18da4878b5efc27c3c386dda248 ]
mwifiex_pcie_request_irq() registers each MSI-X vector with a per-index dev_id (&card->msix_ctx[i]). On a request_irq() failure the cleanup loop "for (j = 0; j < i; j++)" frees msix_entries[j].vector but passes the failed index's &card->msix_ctx[i] as the dev_id. free_irq() matches on (irq, dev_id), so it fails to find the action registered with &card->msix_ctx[j]: the already-requested IRQ j is not freed (leaked) and free_irq() warns about freeing a non-existent IRQ. Use &card->msix_ctx[j].
--- drivers/net/wireless/marvell/mwifiex/pcie.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/marvell/mwifiex/pcie.c +1 -1
@@ -3068,7 +3068,7 @@ static int mwifiex_pcie_request_irq(struct mwifiex_adapter *adapter) ret);for (j =0 ; j < i; j++)free_irq (card->msix_entries[j].vector, - &card->msix_ctx[i]); + &card->msix_ctx[j]);pci_disable_msix (pdev); }else {mwifiex_dbg (adapter,MSG ,"MSIx enabled!" );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 50/438 wifi: brcmfmac: cyw: pass PMKID to firmware if present
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bogdan Nicolae <[email protected]>
[ Upstream commit e2de8d5eb2984416affdd9559e55f37c7f1bbf47 ]
Zero out auth_status on initialization. Otherwise, garbage will leak from the stack to the firmware (when ssid is less than 32 bytes and/or when params->pmkid is set). Then, pass the params->pmkid to the firmware (without it, the firmware caches a garbage PMKID on successful authentication and denies a subsequent association request that includes the PMKID).
--- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/core.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/core.c +4 -1
@@ -200,7 +200,7 @@ brcmf_cyw_external_auth(struct wiphy *wiphy, struct net_device *dev, {struct brcmf_if *ifp;struct brcmf_pub *drvr; -struct brcmf_auth_req_status_le auth_status; +struct brcmf_auth_req_status_le auth_status = {};int ret =0 ;brcmf_dbg (TRACE ,"Enter\n" );
@@ -208,6 +208,9 @@ brcmf_cyw_external_auth(struct wiphy *wiphy, struct net_device *dev, ifp =netdev_priv (dev); drvr = ifp->drvr;if (params->status ==WLAN_STATUS_SUCCESS ) { +if (params->pmkid) +memcpy (auth_status.pmkid, params->pmkid, +WLAN_PMKID_LEN ); auth_status.flags =cpu_to_le16 (BRCMF_EXTAUTH_SUCCESS ); }else { bphy_err(drvr, "External authentication failed: status=%d\n",
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 51/438 wifi: libipw: reject too-short beacon and probe responses
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shmulik Cohen <[email protected]>
[ Upstream commit 5ce5721e8cbe3e80db8f43851cc2a2a92485ef4b ]
libipw_process_probe_response() and the libipw_network_init() call it makes assume the frame contains the full 36-byte beacon and probe response prefix, but the ipw2100 and ipw2200 receive paths only establish that a management frame carries the generic 24-byte three-address header.
libipw_network_init() then computes the information element length as
stats->len - sizeof(*beacon)
stats->len is a u16 and sizeof() has type size_t, so the subtraction is evaluated as size_t and wraps instead of going negative. Truncating that to the u16 length parameter of libipw_parse_info_param() yields 65524 for a 24-byte beacon, and the parser then walks the receive buffer as if it held almost 64 KiB of information elements, reading past the allocation.
Reject the frame before any fixed field is touched.
Found by an AI-assisted review of length arithmetic in management frame parsers. Verified with a KUnit case under Generic KASAN on arm64 under QEMU; I do not have the hardware, so it is not tested on a real device.
--- drivers/net/wireless/intel/ipw2x00/libipw_rx.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/wireless/intel/ipw2x00/libipw_rx.c +3 -0
@@ -1421,6 +1421,9 @@ static void libipw_process_probe_response(struct libipw_device#endif unsigned long flags; +if (stats->len <sizeof (*beacon)) +return ; + LIBIPW_DEBUG_SCAN("'%*pE' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n", info_element->len, info_element->data, beacon->header.addr3,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 52/438 wifi: libipw: reject too-short association responses
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shmulik Cohen <[email protected]>
[ Upstream commit adb7118b7d2cfd7e8213c17d7d2829f353017754 ]
libipw_handle_assoc_resp() reads the capability, status and aid fields of the 30-byte association response prefix and then computes the information element length as
stats->len - sizeof(*frame)
stats->len is a u16 and sizeof() has type size_t, so the subtraction is evaluated as size_t and wraps instead of going negative. Truncating that to the u16 length parameter of libipw_parse_info_param() turns a frame shorter than the fixed fields into a length near 64 KiB, and the parser then reads past the receive buffer.
Both the ipw2100 and ipw2200 management receive paths reach this function having established only that the frame carries the generic 24-byte three-address header.
Reject the frame before any fixed field is touched.
Found by an AI-assisted review of length arithmetic in management frame parsers. Verified with a KUnit case under Generic KASAN on arm64 under QEMU; I do not have the hardware, so it is not tested on a real device.
--- drivers/net/wireless/intel/ipw2x00/libipw_rx.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/wireless/intel/ipw2x00/libipw_rx.c +3 -0
@@ -1209,6 +1209,9 @@ static int libipw_handle_assoc_resp(struct libipw_device *ieee, struct libipw_asstruct libipw_network *network = &network_resp;struct net_device *dev = ieee->dev; +if (stats->len <sizeof (*frame)) +return 1 ; + network->flags =0 ; network->qos_data.active =0 ; network->qos_data.supported =0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 53/438 IB/IPoIB: Avoid restoring OPER_UP after multicast flush
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Carolina Jubran <[email protected]>
[ Upstream commit 9a141d3dc869d18b2eab35e999f4790a9b84e40f ]
ipoib_ib_dev_flush_light() temporarily clears IPOIB_FLAG_OPER_UP to prevent multicast joins while ipoib_mcast_dev_flush() is running, and restores the flag afterwards if it was previously set.
This restore races with ipoib_ib_dev_down(). If the interface is brought down while the flush is in progress, ipoib_ib_dev_down() clears IPOIB_FLAG_OPER_UP, but the flush path may set it again after the device has already gone down.
Since commit 894021a75291 ("IB/ipoib: Make the carrier_on_task race aware"), ipoib_mcast_carrier_on_task() relies on IPOIB_FLAG_OPER_UP being cleared to terminate its rtnl_trylock() retry loop. If the flag is left set after shutdown, the workqueue retries forever, causing teardown to deadlock when ipoib_ndo_uninit() waits in destroy_workqueue() while holding RTNL.
Instead of overloading IPOIB_FLAG_OPER_UP to block multicast joins during a light flush, introduce a dedicated IPOIB_FLAG_MCAST_FLUSH flag. Use it together with IPOIB_FLAG_OPER_UP to determine whether multicast joins are allowed, avoiding the race with device shutdown.
--- drivers/infiniband/ulp/ipoib/ipoib.h | 7 +++++++ drivers/infiniband/ulp/ipoib/ipoib_ib.c | 12 +++++++----- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 16 ++++++++-------- 3 files changed, 22 insertions(+), 13 deletions(-)
drivers/infiniband/ulp/ipoib/ipoib.h +7 -0
@@ -87,6 +87,7 @@ enum {IPOIB_FLAG_INITIALIZED =1 ,IPOIB_FLAG_ADMIN_UP =2 ,IPOIB_PKEY_ASSIGNED =3 , +IPOIB_FLAG_MCAST_FLUSH =4 ,IPOIB_FLAG_SUBINTERFACE =5 ,IPOIB_STOP_REAPER =7 , IPOIB_FLAG_ADMIN_CM = 9,
@@ -414,6 +415,12 @@ struct ipoib_dev_priv {const struct net_device_ops *rn_ops; }; +static inline bool ipoib_mcast_allowed (struct ipoib_dev_priv *priv) +{ +return test_bit (IPOIB_FLAG_OPER_UP , &priv->flags) && + !test_bit (IPOIB_FLAG_MCAST_FLUSH , &priv->flags); +} +struct ipoib_ah {struct net_device *dev;struct ib_ah *ah;
drivers/infiniband/ulp/ipoib/ipoib_ib.c +7 -5
@@ -1227,17 +1227,19 @@ static void __ipoib_ib_dev_flush(struct ipoib_dev_priv *priv, }if (level ==IPOIB_FLUSH_LIGHT ) { -int oper_up;ipoib_mark_paths_invalid (dev); -/* Set IPoIB operation as down to prevent races between: +/* Set MCAST_FLUSH to prevent races between: * the flush flow which leaves MCG and on the fly joins * which can happen during that time. mcast restart task * should deal with join requests we missed. +* +* Do not clear OPER_UP for this; restoring it races with +* ipoib_ib_dev_down() and can leave OPER_UP set after the +* device is down. */ - oper_up =test_and_clear_bit (IPOIB_FLAG_OPER_UP , &priv->flags); +set_bit (IPOIB_FLAG_MCAST_FLUSH , &priv->flags);ipoib_mcast_dev_flush (dev); -if (oper_up) -set_bit (IPOIB_FLAG_OPER_UP , &priv->flags); +clear_bit (IPOIB_FLAG_MCAST_FLUSH , &priv->flags);ipoib_reap_dead_ahs (priv); }
drivers/infiniband/ulp/ipoib/ipoib_multicast.c +8 -8
@@ -74,7 +74,7 @@ static void __ipoib_mcast_schedule_join_thread(struct ipoib_dev_priv *priv, struct ipoib_mcast *mcast, bool delay) { -if (!test_bit (IPOIB_FLAG_OPER_UP , &priv->flags)) +if (!ipoib_mcast_allowed (priv))return ;/*
@@ -469,7 +469,7 @@ static int ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast)int ret =0 ;if (!priv->broadcast || - !test_bit (IPOIB_FLAG_OPER_UP , &priv->flags)) + !ipoib_mcast_allowed (priv))return -EINVAL ;init_completion (&mcast->done);
@@ -555,7 +555,7 @@ void ipoib_mcast_join_task(struct work_struct *work)unsigned long delay_until =0 ;struct ipoib_mcast *mcast =NULL ; -if (!test_bit (IPOIB_FLAG_OPER_UP , &priv->flags)) +if (!ipoib_mcast_allowed (priv))return ;if (ib_query_port (priv->ca, priv->port, &port_attr)) {
@@ -577,7 +577,7 @@ void ipoib_mcast_join_task(struct work_struct *work)netif_addr_unlock_bh (dev);spin_lock_irq (&priv->lock); -if (!test_bit (IPOIB_FLAG_OPER_UP , &priv->flags)) +if (!ipoib_mcast_allowed (priv)) goto out;if (!priv->broadcast) {
@@ -749,7 +749,7 @@ void ipoib_mcast_send(struct net_device *dev, u8 *daddr, struct sk_buff *skb)spin_lock_irqsave (&priv->lock, flags); -if (!test_bit (IPOIB_FLAG_OPER_UP , &priv->flags) || +if (!ipoib_mcast_allowed (priv) || !priv->broadcast || !test_bit (IPOIB_MCAST_FLAG_ATTACHED , &priv->broadcast->flags)) { ++dev->stats.tx_dropped;
@@ -871,7 +871,7 @@ void ipoib_mcast_restart_task(struct work_struct *work)LIST_HEAD (remove_list);struct ib_sa_mcmember_rec rec; -if (!test_bit (IPOIB_FLAG_OPER_UP , &priv->flags)) +if (!ipoib_mcast_allowed (priv))/* * shortcut...on shutdown flush is called next, just * let it do all the work
@@ -965,9 +965,9 @@ void ipoib_mcast_restart_task(struct work_struct *work)ipoib_mcast_remove_list (&remove_list);/* -* Double check that we are still up +* Double check that we are still up and not flushing */ -if (test_bit (IPOIB_FLAG_OPER_UP , &priv->flags)) { +if (ipoib_mcast_allowed (priv)) {spin_lock_irq (&priv->lock);__ipoib_mcast_schedule_join_thread (priv,NULL ,0 );spin_unlock_irq (&priv->lock);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 54/438 wifi: cfg80211: dont get the radio mask for netdev-less wdevs
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit a7783e585360ee05dfe21d3173dbbe985c94f29e ]
cfg80211_calculate_bi_data() calls rdev_get_radio_mask() with wdev->netdev, which can be NULL and then crashes in mac80211.
To avoid that, invert the order of checks since wdev->netdev is always valid for beaconing interfaces.
--- net/wireless/util.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
net/wireless/util.c +4 -5
@@ -2426,16 +2426,15 @@ static void cfg80211_calculate_bi_data(struct wiphy *wiphy, u32 new_beacon_int,if (wdev->valid_links)continue ; + wdev_bi =cfg80211_wdev_bi (wdev); +if (!wdev_bi) +continue ; +/* skip wdevs not active on the given wiphy radio */ if (radio_idx >=0 && !(rdev_get_radio_mask (rdev, wdev->netdev) &BIT (radio_idx)))continue ; - wdev_bi =cfg80211_wdev_bi (wdev); - -if (!wdev_bi) -continue ; -if (!*beacon_int_gcd) { *beacon_int_gcd = wdev_bi;continue ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 55/438 wifi: cfg80211: check IP header size in cfg80211_classify8021d()
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 48b2c5c628b09cf36cbeca53e0432fc2a7518be7 ]
A frame that looks like IP can be transmitted, but be too short, so the DS field is read incorrectly:
BUG: KMSAN: uninit-value in cfg80211_classify8021d+0x99d/0x12b0 net/wireless/util.c:1027 cfg80211_classify8021d+0x99d/0x12b0 net/wireless/util.c:1027 ieee80211_select_queue+0x37a/0x9e0 net/mac80211/wme.c:180 __ieee80211_subif_start_xmit+0x60f/0x1d90 net/mac80211/tx.c:4304 ieee80211_subif_start_xmit+0xa8/0x6d0 net/mac80211/tx.c:4538 ... packet_sendmsg+0x9173/0xa2a0 net/packet/af_packet.c:3108
Use skb_header_pointer() like the MPLS case.
--- net/wireless/util.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-)
net/wireless/util.c +22 -4
@@ -988,12 +988,30 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb, }switch (skb->protocol) { -case htons (ETH_P_IP ): - dscp =ipv4_get_dsfield (ip_hdr (skb)) &0xfc ; +case htons (ETH_P_IP ): { +const struct iphdr *iph; +struct iphdr _iph; + + iph =skb_header_pointer (skb,sizeof (struct ethhdr ), +sizeof (*iph), &_iph); +if (!iph) +return 0 ; + + dscp =ipv4_get_dsfield (iph) &0xfc ;break ; -case htons (ETH_P_IPV6 ): - dscp =ipv6_get_dsfield (ipv6_hdr (skb)) &0xfc ; + } +case htons (ETH_P_IPV6 ): { +const struct ipv6hdr *ip6h; +struct ipv6hdr _ip6h; + + ip6h =skb_header_pointer (skb,sizeof (struct ethhdr ), +sizeof (*ip6h), &_ip6h); +if (!ip6h) +return 0 ; + + dscp =ipv6_get_dsfield (ip6h) &0xfc ;break ; + }case htons (ETH_P_MPLS_UC ):case htons (ETH_P_MPLS_MC ): {struct mpls_label mpls_tmp, *mpls;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 56/438 soundwire: cadence_master: wait and cancel cdns->work before clock stop
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bard Liao <[email protected]>
[ Upstream commit aba7b41faeecb7692458095ce6fafc341fe0b80e ]
A peripheral event could happen during the clock stop process. We need to wait for the event be handled before stopping the bus clock. Otherwise, we will get the IO transfer timed out issue.
--- drivers/soundwire/cadence_master.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/soundwire/cadence_master.c +7 -0
@@ -1701,6 +1701,13 @@ int sdw_cdns_clock_stop(struct sdw_cdns *cdns, bool block_wake)return 0 ; } +/* +* wait for any in-flight peripheral event handling to complete before stopping the clock. +* No need to disable peripheral interrupts before canceling the work, as the peripheral +* interrupts are already masked before the work is scheduled. +*/ +cancel_work_sync (&cdns->work); +/* * Before entering clock stop we mask the Slave * interrupts. This helps avoid having to deal with e.g. a
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 57/438 mips: econet: fix unmet dependencies for ECONET
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Julian Braha <[email protected]>
[ Upstream commit fb5a08026a68be0ec5f660588311fb1091bf5d58 ]
ECONET selects EARLY_PRINTK_8250, SERIAL_OF_PLATFORM, and SERIAL_8250 without ensuring their dependencies, EARLY_PRINTK and TTY are met. This causes unmet dependencies:
WARNING: unmet direct dependencies detected for SERIAL_8250
Depends on [n]: TTY [=n] && HAS_IOMEM [=y] && !S390 Selected by [y]:
- ECONET [=y]
WARNING: unmet direct dependencies detected for EARLY_PRINTK_8250
Depends on [n]: EARLY_PRINTK [=n] && USE_GENERIC_EARLY_PRINTK_8250 [=y] Selected by [y]:
- ECONET [=y]
WARNING: unmet direct dependencies detected for SERIAL_OF_PLATFORM
Depends on [n]: TTY [=n] && HAS_IOMEM [=y] && SERIAL_8250 [=y] && OF [=y] Selected by [y]:
- ECONET [=y]
However, in the discussion of v1 of this patch, Arnd pointed out that these selects don't belong here in the first place. [1]
Let's remove them to resolve the unmet dependencies.
These unmet dependencies were found by kconfirm, a static analysis tool for Kconfig.
--- arch/mips/Kconfig | 3 --- 1 file changed, 3 deletions(-)
arch/mips/Kconfig +0 -3
@@ -397,10 +397,7 @@ config ECONET select BOOT_RAW select CPU_BIG_ENDIAN select DEBUG_ZBOOT if DEBUG_KERNEL - select EARLY_PRINTK_8250 select ECONET_EN751221_TIMER - select SERIAL_8250 - select SERIAL_OF_PLATFORM select SYS_SUPPORTS_BIG_ENDIAN select SYS_HAS_CPU_MIPS32_R1 select SYS_HAS_CPU_MIPS32_R2
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 58/438 MIPS: Octeon: apply USB FDT fixups also when USB is modular
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Orgad Shaneh <[email protected]>
[ Upstream commit 126f16e0a1b353c2ba5c7e2c8626cfa865934f9f ]
The uctl/usbn device-tree fixups in octeon_prune_device_tree() - which set the board's USB reference-clock frequency and type from __cvmx_helper_board_usb_get_clock_type() - are guarded by "#ifdef CONFIG_USB", which is false when USB is built as a module. The fixups then silently disappear and octeon-hcd sees whatever default the DTS carries (12MHz crystal in octeon_3xxx.dts), leaving the PHY dead or the bus erroring on boards with a different reference clock.
Use IS_ENABLED() so USB=m gets the same fixups as USB=y.
--- arch/mips/cavium-octeon/octeon-platform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/mips/cavium-octeon/octeon-platform.c +2 -2
@@ -18,7 +18,7 @@#include <asm/octeon/octeon.h> #include <asm/octeon/cvmx-helper-board.h> -#ifdef CONFIG_USB +#if IS_ENABLED (CONFIG_USB )#include <linux/usb/ehci_def.h> #include <linux/usb/ehci_pdriver.h> #include <linux/usb/ohci_pdriver.h>
@@ -1080,7 +1080,7 @@ int __init octeon_prune_device_tree(void) ; } -#ifdef CONFIG_USB +#if IS_ENABLED (CONFIG_USB )/* OHCI/UHCI USB */ alias_prop =fdt_getprop (initial_boot_params, aliases,"uctl" ,NULL );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 59/438 dma-coherent: report a failed reserved memory assignment
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Donggeun Yoo <[email protected]>
[ Upstream commit 504981db4f69bdd28054fb98c96a3a67f7248dde ]
rmem_dma_device_init() drops the return value of dma_assign_coherent_memory() and always reports success. That call fails with -EBUSY when the device already has a coherent pool, and the file allows only "*one* such region of memory" per device.
of_reserved_mem_device_init_by_idx() reads the zero as success. It logs "assigned reserved memory node" for a region that was not assigned and records the pairing, so of_reserved_mem_device_release() later runs rmem_dma_device_release() for it. That clears dev->dma_mem without looking at which region it was called for, dropping the pool the device did get and leaving it on ordinary memory.
dma_declare_coherent_memory() checks the same call and releases the memory on failure, and rmem_swiotlb_device_init() propagates its own errors. Return the error here as well, so a device tree that assigns two pools to one device fails the probe instead of half working.
--- kernel/dma/coherent.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
kernel/dma/coherent.c +1 -2
@@ -351,8 +351,7 @@ static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev) min_not_zero(dev->coherent_dma_mask, dev->bus_dma_limit))dev_warn (dev,"reserved memory is beyond device's set DMA address range\n" ); -dma_assign_coherent_memory (dev, mem); -return 0 ; +return dma_assign_coherent_memory (dev, mem); } static void rmem_dma_device_release(struct reserved_mem *rmem,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 60/438 dma-mapping: dont trace the DMA address when the allocation fails
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Donggeun Yoo <[email protected]>
[ Upstream commit 92c6a8d6470f7e7aa86c1f144818d8fa4fcbd5aa ]
dma_alloc_attrs() passes *dma_handle to trace_dma_alloc() without checking whether the allocation succeeded. No backend writes it on
failure: dma_direct_alloc(), iommu_dma_alloc() and the dma_map_ops instances assign it only on the path that returns a buffer. Callers usually pass an uninitialized automatic variable, so a failed allocation records whatever the stack held, next to the virt_addr=(null) that marks the record as an error:
dma_alloc: dmatrace dir=BIDIRECTIONAL dma_addr=deadbeefdeadbeef size=1099511627776 virt_addr=0000000000000000
The device coherent pool path reaches the same call: a non-zero return from dma_alloc_from_dev_coherent() means the request was handled, not that it succeeded, so cpu_addr is NULL and dma_handle is untouched once the pool runs out.
For an allocation event a NULL virt_addr already means the request failed, so the address field carries nothing. Report 0 for it in the event class rather than at each call site, which covers dma_alloc_pages() and dma_alloc_sgt_err() as well.
--- include/trace/events/dma.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/trace/events/dma.h +1 -1
@@ -133,7 +133,7 @@ DECLARE_EVENT_CLASS(dma_alloc_class,TP_fast_assign ( __assign_str(device); __entry->virt_addr = virt_addr; - __entry->dma_addr = dma_addr; + __entry->dma_addr = virt_addr ? dma_addr :0 ; __entry->size = size; __entry->flags = flags; __entry->dir = dir;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 61/438 dmaengine: Fix device kref underflow in dma_chan_put()
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shivank Garg <[email protected]>
[ Upstream commit 44dab659064eb5c10adb0306510eebe848ed592d ]
dma_chan_get() takes chan->device->ref only on the slow path:
/* no kref on fast path */
if (chan->client_count) {
__module_get(owner);
chan->client_count++;
return 0;
}
if (!try_module_get(owner))
return -ENODEV;
if (!dma_device_get(chan->device)) { // calls kref_get_unless_zero()dma_chan_put() drops the ref unconditionally, so every fast-path get/put pair drops one extra device reference.
The bug fires when two conditions hold together: a non-private provider has a persistent client holding chan->client_count > 0 and another client cycles dmaengine_get()/dmaengine_put(). When the kref hits zero, the subsequent dma_find_channel() returns NULL even though the provider module is still loaded.
Fix this by dropping device->ref only on the last put, matching the single slow-path get.
--- drivers/dma/dmaengine.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/dma/dmaengine.c +3 -1
@@ -515,7 +515,9 @@ static void dma_chan_put(struct dma_chan *chan) chan->route_data =NULL ; } -dma_device_put (chan->device); +/* This channel is not in use anymore, drop the device ref */ +if (!chan->client_count) +dma_device_put (chan->device);module_put (dma_chan_to_owner (chan)); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 62/438 dmaengine: fix use-after-free in dma_chan_put() and dma_release_channel()
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shivank Garg <[email protected]>
[ Upstream commit e873c74132f0c5f1452816cd9bb26208f0bba1e1 ]
When dma_device_put() drops the last reference on chan->device->ref, dma_device_release() runs and may free the dma_device along with its channels.
dma_chan_put() then still reads chan->device->owner via dma_chan_to_owner() for the trailing module_put(). KASAN catches it:
slab-use-after-free in dma_chan_put+0x3e6/0x4c0 Read of size 8 by task insmod/6319 Freed by task 6319: kfree+0x225/0x470 dma_chan_put+0x395/0x4c0 dmaengine_put+0xf8/0x160
Cache the module owner in dma_chan_put() before the put so the trailing module_put() does not need chan->device.
--- drivers/dma/dmaengine.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/dma/dmaengine.c +4 -1
@@ -495,10 +495,13 @@ static int dma_chan_get(struct dma_chan *chan)*/ static void dma_chan_put (struct dma_chan *chan) { +struct module *owner; +/* This channel is not in use, bail out */ if (!chan->client_count)return ; + owner =dma_chan_to_owner (chan); chan->client_count--;/* This channel is not in use anymore, free it */
@@ -518,7 +521,7 @@ static void dma_chan_put(struct dma_chan *chan)/* This channel is not in use anymore, drop the device ref */ if (!chan->client_count)dma_device_put (chan->device); -module_put (dma_chan_to_owner (chan)); +module_put (owner); }enum dma_status dma_sync_wait (struct dma_chan *chan,dma_cookie_t cookie)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 63/438 dmaengine: wait for RCU readers before releasing dma_device
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shivank Garg <[email protected]>
[ Upstream commit dc750422170a563c7a81f6e49d36bb02c62ae37f ]
dma_issue_pending_all() walks the dma_device_list with list_for_each_entry_rcu() under rcu_read_lock(). dma_device_release() unlinks the device with list_del_rcu() and then calls device->device_release() (which in many drivers, such as plx_dma.c, directly calls kfree()).
Because there is no grace period between unlinking the device and freeing it, concurrent RCU readers in dma_issue_pending_all() can access the device after it has been freed.
The lockless walk originally relied on clients holding a dmaengine reference to pin the provider module, and therefore the device, for as long as they might traverse the list. Commit 8ad342a86359 ("dmaengine:
Add reference counting to dma_device struct") decoupled the dma_device lifetime from the module reference, so the device can now be released while a reader is still walking the list.
Add synchronize_rcu() before the device is freed, so RCU readers are guaranteed to have finished. Keep it unconditional: providers that do not implement device_release() free the device themselves once dma_async_device_unregister() returns. This call will delay for a grace period with dma_list_mutex held, which is safe and only teardown path is delayed.
--- drivers/dma/dmaengine.c | 1 + 1 file changed, 1 insertion(+)
drivers/dma/dmaengine.c +1 -0
@@ -428,6 +428,7 @@ static void dma_device_release(struct kref *ref)list_del_rcu (&device->global_node);dma_channel_rebalance (); +synchronize_rcu ();if (device->device_release) device->device_release (device);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 64/438 wifi: cfg80211: dont free driver-owned scan requests
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit dab68a74e90b8e07f08ed9deaa5884857a3cfe89 ]
When an interface goes down while a scan is running, cfg80211 completes the scan towards userspace and frees the scan request. However, the driver can be convinced that it owns the request, since the cancellation is (intended to be) asynchronous.
The WARN_ON() in the netdev notifier was meant to catch this, but it's not actually avoidable, so it triggers and we get a UAF in scan_done().
There doesn't seem to be a great way around it, so just track that the driver is still convinced it owns the request, and then just free it on completion if it was already cancelled. Also remove the warnings since they can trigger in the intended architecture.
--- net/wireless/core.c | 11 +++++------ net/wireless/core.h | 10 ++++++++++ net/wireless/rdev-ops.h | 3 +++ net/wireless/scan.c | 31 +++++++++++++++++++++++++++++-- 4 files changed, 47 insertions(+), 8 deletions(-)
net/wireless/core.c +5 -6
@@ -244,9 +244,8 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, rdev->opencount--;if (rdev->scan_req && rdev->scan_req->req.wdev == wdev) { -if (WARN_ON (!rdev->scan_req->notified && - (!rdev->int_scan_req || - !rdev->int_scan_req->notified))) +if (!rdev->scan_req->notified && + (!rdev->int_scan_req || !rdev->int_scan_req->notified)) rdev->scan_req->info.aborted = true;___cfg80211_scan_done (rdev, false); }
@@ -1758,9 +1757,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,wiphy_lock (&rdev->wiphy);cfg80211_update_iface_num (rdev, wdev->iftype,-1 );if (rdev->scan_req && rdev->scan_req->req.wdev == wdev) { -if (WARN_ON (!rdev->scan_req->notified && - (!rdev->int_scan_req || - !rdev->int_scan_req->notified))) +if (!rdev->scan_req->notified && + (!rdev->int_scan_req || + !rdev->int_scan_req->notified)) rdev->scan_req->info.aborted = true;___cfg80211_scan_done (rdev, false); }
net/wireless/core.h +10 -0
@@ -24,6 +24,16 @@struct cfg80211_scan_request_int {struct cfg80211_scan_info info;bool notified; +/* +* set while the request is handed to the driver, i.e. between +* rdev_scan() and cfg80211_scan_done() +*/ +bool driver_owns; +/* +* set when cfg80211 is done with the request but the driver still +* owns it, so that cfg80211_scan_done() knows to just free it +*/ +bool stale;/* must be last - variable members */ struct cfg80211_scan_request req; };
net/wireless/rdev-ops.h +3 -0
@@ -464,7 +464,10 @@ static inline int rdev_scan(struct cfg80211_registered_device *rdev,return -EINVAL ;trace_rdev_scan (&rdev->wiphy, request); + request->driver_owns = true; ret = rdev->ops->scan (&rdev->wiphy, &request->req); +if (ret) + request->driver_owns = false;trace_rdev_return_int (&rdev->wiphy, ret);return ret; }
net/wireless/scan.c +29 -2
@@ -1114,6 +1114,21 @@ int cfg80211_scan(struct cfg80211_registered_device *rdev)return 0 ; } +/* +* Release the scan request, but free it only if the driver is also done, +* e.g. mac80211 may cancel it asynchronously and still use it. +*/ +static void cfg80211_put_scan_req (struct cfg80211_scan_request_int *req) +{ +if (!req) +return ; + +if (req->driver_owns) + req->stale = true; +else +kfree (req); +} +void ___cfg80211_scan_done (struct cfg80211_registered_device *rdev,bool send_message) {
@@ -1173,10 +1188,10 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev,dev_put (wdev->netdev); -kfree (rdev->int_scan_req); +cfg80211_put_scan_req (rdev->int_scan_req); rdev->int_scan_req =NULL ; -kfree (rdev->scan_req); +cfg80211_put_scan_req (rdev->scan_req); rdev->scan_req =NULL ;if (!send_message)
@@ -1199,6 +1214,18 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request,struct cfg80211_scan_info old_info = intreq->info;trace_cfg80211_scan_done (intreq, info); + + intreq->driver_owns = false; + +if (intreq->stale) { +/* +* The scan is already completed as far as we're concerned, +* it was just kept around for the driver - done now, free it. +*/ +kfree (intreq); +return ; + } +WARN_ON (intreq != rdev->scan_req && intreq != rdev->int_scan_req);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 65/438 wifi: cfg80211: only group hidden BSSes with beacon entries
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 068843ed0902c552a13860c5ec6b2ca65b57a065 ]
When a probe response for an unknown BSS comes in, __cfg80211_bss_update() looks for an existing entry with the same BSSID and a hidden (zero-length or NUL-filled) SSID, and if it finds one it groups them, using the beacon IEs from the existing entry.
But that could find another entry without a beacon, if it was also from a probe response (with SSID), so there's a group without beacon elements.
If a beacon with a hidden SSID for that BSSID arrives later, cfg80211_combine_bsses() goes looking for the probe response entries that belong to it - i.e. entries with the same BSSID and channel that have no beacon IEs - and finds those two. They are already grouped with each other, so it hits its
WARN_ON_ONCE(bss->pub.hidden_beacon_bss)
WARN_ON_ONCE(!list_empty(&bss->hidden_list))
which are there because an entry without beacon elements is not supposed to be part of a group yet.
Only combine entries when a beacon was already received, ones that are kept separate will be combined when a beacon arrives.
--- net/wireless/scan.c | 7 +++++++ 1 file changed, 7 insertions(+)
net/wireless/scan.c +7 -0
@@ -2049,6 +2049,13 @@ __cfg80211_bss_update(struct cfg80211_registered_device *rdev,if (!hidden) hidden =rb_find_bss (rdev, tmp,BSS_CMP_HIDE_NUL ); +/* +* Only group with an entry with beacon data, otherwise +* beacon data can never be filled/updated. +*/ +if (hidden && + !rcu_access_pointer (hidden->pub.beacon_ies)) + hidden =NULL ;if (hidden) { new->pub.hidden_beacon_bss = &hidden->pub; list_add(&new->hidden_list,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 66/438 wifi: cfg80211: dont filter by BSS type when removing stale entries
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit b377e1000d963e7182a987082b4b06580bd7ac84 ]
When an assoc AP switches to a channel that already has a BSS entry, cfg80211_update_assoc_bss_entry() removes that entry before rehashing the real one, since the two would otherwise collide in the BSS rbtree.
The lookup for that entry also required it to match the connection's BSS type, so an entry advertising e.g. the IBSS capability bit was left in place, and the following cfg80211_rehash_bss() then ran into it:
WARN_ON(!cmp)
Changing the type shouldn't really happen, but can be triggered by a rogue AP/device, so drop the check and remove any entries matching the comparison.
--- net/wireless/scan.c | 5 ----- 1 file changed, 5 deletions(-)
net/wireless/scan.c +0 -5
@@ -3477,11 +3477,6 @@ void cfg80211_update_assoc_bss_entry(struct wireless_dev *wdev, cbss->pub.channel = chan;list_for_each_entry (bss, &rdev->bss_list, list) { -if (!cfg80211_bss_type_match (bss->pub.capability, - bss->pub.channel->band, - wdev->conn_bss_type)) -continue ; -if (bss == cbss)continue ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 67/438 wifi: cfg80211: ibss: ref BSS entry for joined event
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 708f9d43d6a2eb9c6b83fe62af628de9dffd9314 ]
When the IBSS is joined, we only record the BSSID/channel in the event and look up the BSS entry when processing it. However, that's racy, e.g. a new scan with NL80211_SCAN_FLAG_FLUSH can remove it, causing a warning in the event work:
!bss
WARNING: net/wireless/ibss.c:37 at __cfg80211_ibss_joined+0x3d3/0x440 Workqueue: cfg80211 cfg80211_event_work cfg80211_process_wdev_events+0x39f/0x5b0 net/wireless/util.c:1144 cfg80211_process_rdev_events+0xa1/0x110 net/wireless/util.c:1179 cfg80211_event_work+0x2f/0x40 net/wireless/core.c:393
Do the lookup early (the driver is expected to only join an IBSS that has a BSS entry) and keep a reference to it.
--- net/wireless/core.h | 6 ++---- net/wireless/ibss.c | 36 ++++++++++++++++++++---------------- net/wireless/util.c | 3 +-- 3 files changed, 23 insertions(+), 22 deletions(-)
net/wireless/core.h +2 -4
@@ -290,8 +290,7 @@ struct cfg80211_event {bool locally_generated; } dc;struct { -u8 bssid[ETH_ALEN ]; -struct ieee80211_channel *channel; +struct cfg80211_bss *bss; } ij;struct {u8 peer_addr[ETH_ALEN ];
@@ -354,8 +353,7 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,void cfg80211_clear_ibss (struct net_device *dev,bool nowext);int cfg80211_leave_ibss (struct cfg80211_registered_device *rdev,struct net_device *dev,bool nowext); -void __cfg80211_ibss_joined (struct net_device *dev,const u8 *bssid, -struct ieee80211_channel *channel); +void __cfg80211_ibss_joined (struct net_device *dev,struct cfg80211_bss *bss);int cfg80211_ibss_wext_join (struct cfg80211_registered_device *rdev,struct wireless_dev *wdev);
net/wireless/ibss.c +20 -16
@@ -16,26 +16,18 @@#include "rdev-ops.h" -void __cfg80211_ibss_joined (struct net_device *dev,const u8 *bssid, -struct ieee80211_channel *channel) +void __cfg80211_ibss_joined (struct net_device *dev,struct cfg80211_bss *bss) {struct wireless_dev *wdev = dev->ieee80211_ptr; -struct cfg80211_bss *bss;#ifdef CONFIG_CFG80211_WEXT union iwreq_data wrqu;#endif if (WARN_ON (wdev->iftype !=NL80211_IFTYPE_ADHOC )) -return ; + goto put_bss;if (!wdev->u.ibss.ssid_len) -return ; - - bss =cfg80211_get_bss (wdev->wiphy, channel, bssid,NULL ,0 , -IEEE80211_BSS_TYPE_IBSS ,IEEE80211_PRIVACY_ANY ); - -if (WARN_ON (!bss)) -return ; + goto put_bss;if (wdev->u.ibss.current_bss) {cfg80211_unhold_bss (wdev->u.ibss.current_bss);
@@ -43,17 +35,22 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, }cfg80211_hold_bss (bss_from_pub (bss)); +/* the reference from the event is transferred to current_bss */ wdev->u.ibss.current_bss =bss_from_pub (bss);cfg80211_upload_connect_keys (wdev); -nl80211_send_ibss_bssid (wiphy_to_rdev (wdev->wiphy), dev, bssid, +nl80211_send_ibss_bssid (wiphy_to_rdev (wdev->wiphy), dev, bss->bssid,GFP_KERNEL );#ifdef CONFIG_CFG80211_WEXT memset (&wrqu,0 ,sizeof (wrqu)); -memcpy (wrqu.ap_addr.sa_data, bssid,ETH_ALEN ); +memcpy (wrqu.ap_addr.sa_data, bss->bssid,ETH_ALEN );wireless_send_event (dev,SIOCGIWAP , &wrqu,NULL );#endif +return ; + +put_bss: +cfg80211_put_bss (wdev->wiphy, bss); } void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
@@ -62,6 +59,7 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,struct wireless_dev *wdev = dev->ieee80211_ptr;struct cfg80211_registered_device *rdev =wiphy_to_rdev (wdev->wiphy);struct cfg80211_event *ev; +struct cfg80211_bss *bss;unsigned long flags;trace_cfg80211_ibss_joined (dev, bssid, channel);
@@ -69,13 +67,19 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,if (WARN_ON (!channel))return ; + bss =cfg80211_get_bss (wdev->wiphy, channel, bssid,NULL ,0 , +IEEE80211_BSS_TYPE_IBSS ,IEEE80211_PRIVACY_ANY ); +if (WARN_ON (!bss)) +return ; + ev =kzalloc_obj (*ev, gfp); -if (!ev) +if (!ev) { +cfg80211_put_bss (wdev->wiphy, bss);return ; + } ev->type =EVENT_IBSS_JOINED ; -memcpy (ev->ij.bssid, bssid,ETH_ALEN ); - ev->ij.channel = channel; + ev->ij.bss = bss;spin_lock_irqsave (&wdev->event_lock, flags);list_add_tail (&ev->list, &wdev->event_list);
net/wireless/util.c +1 -2
@@ -1184,8 +1184,7 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev) !ev->dc.locally_generated);break ;case EVENT_IBSS_JOINED : -__cfg80211_ibss_joined (wdev->netdev, ev->ij.bssid, - ev->ij.channel); +__cfg80211_ibss_joined (wdev->netdev, ev->ij.bss);break ;case EVENT_STOPPED :/*
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 68/438 wifi: cfg80211: fix NAN regulatory enforcement
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 17a5f8571d1d40c88b78cfc154a7da0d60f13f37 ]
reg_wdev_chan_valid() returns early for any wdev that has no netdev, which is fine for P2P originally (and later PD still), but NAN has no netdev and yet enforcement code was added and is needed, but is dead code right now.
Use wdev_running() instead so that netdev-less wdevs aren't skipped. P2P/PD don't do anything in the later switch, but NAN code can now be reached.
--- net/wireless/reg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/wireless/reg.c +1 -1
@@ -2345,7 +2345,7 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev) iftype = wdev->iftype;/* make sure the interface is active */ -if (!wdev->netdev || !netif_running (wdev->netdev)) +if (!wdev_running (wdev))return true;/* NAN doesn't have links, handle it separately */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 69/438 wifi: mac80211: dont start a ROC while scanning
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 733f0fde95392ed5f61a4e36aee661ea8d0e8581 ]
The ROC work can be pending when a scan starts (which requires ROC list to be empty, but that's possible), and then a new ROC can be added to the list and the work will pick it up.
Avoid starting that ROC if a scan made it between things, as otherwise we'll hit a warning later:
WARNING: net/mac80211/offchannel.c:404 at ieee80211_start_next_roc+0x256/0x2d0 Workqueue: events_unbound cfg80211_wiphy_work Call Trace: __ieee80211_scan_completed+0x4fd/0xe40 net/mac80211/scan.c:537 ieee80211_scan_work+0x472/0x1ff0 net/mac80211/scan.c:1193 cfg80211_wiphy_work+0x410/0x570 net/wireless/core.c:513
--- net/mac80211/offchannel.c | 7 +++++++ 1 file changed, 7 insertions(+)
net/mac80211/offchannel.c +7 -0
@@ -460,6 +460,13 @@ static void __ieee80211_roc_work(struct ieee80211_local *local)return ;if (!roc->started) { +/* +* The work can be started by a previous ROC work, but a scan +* can get between things; scan finish will retrigger us. +*/ +if (local->scanning) +return ; +WARN_ON (!local->emulate_chanctx);_ieee80211_start_next_roc (local); }else {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 70/438 wifi: mac80211: dont warn when an IBSS has no channel to scan
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit a7491b7efbd9136b120a12ed72af9c12121dd134 ]
ieee80211_request_ibss_scan() warns when regulatory leaves no allowed channel, but that can happen as the regdomain can change while IBSS is operating, and it can continue to operate briefly during the 60s grace period until it's shut down.
Just remove the warning in this case.
--- net/mac80211/scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/mac80211/scan.c +1 -1
@@ -1242,7 +1242,7 @@ int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, } } -if (WARN_ON_ONCE (n_ch ==0 )) +if (n_ch ==0 )return -EINVAL ; local->int_scan_req->n_channels = n_ch;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 71/438 wifi: mac80211: dont offload TC setup on AP_VLAN interfaces
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 362bd5bce29ed0f6fd3d39a7065567777d70606e ]
AP_VLAN interfaces are purely virtual, so don't try to offload TC setup to drivers. We can't really use the AP interface either since we may not know it all the time, and it could technically even change.
Just reject the TC offload so things get done in software.
--- net/mac80211/iface.c | 3 +++ 1 file changed, 3 insertions(+)
net/mac80211/iface.c +3 -0
@@ -935,6 +935,9 @@ static int ieee80211_netdev_setup_tc(struct net_device *dev,struct ieee80211_sub_if_data *sdata =IEEE80211_DEV_TO_SUB_IF (dev);struct ieee80211_local *local = sdata->local; +if (sdata->vif.type ==NL80211_IFTYPE_AP_VLAN ) +return -EOPNOTSUPP ; +return drv_net_setup_tc (local, sdata, dev, type, type_data); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 72/438 wifi: mac80211: suppress chanctx warning for debugfs reset
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit bf29d085e0eba92388518719d044f4702a8c6644 ]
Before suspend all the channel contexts should removed, so the warning makes sense and should be there, but during reset the same code is called without first removing. Limit the check to the real suspend case.
--- net/mac80211/cfg.c | 2 +- net/mac80211/debugfs.c | 2 +- net/mac80211/ieee80211_i.h | 2 +- net/mac80211/pm.c | 8 +++++--- 4 files changed, 8 insertions(+), 6 deletions(-)
net/mac80211/cfg.c +1 -1
@@ -3475,7 +3475,7 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy,static int ieee80211_suspend (struct wiphy *wiphy,struct cfg80211_wowlan *wowlan) { -return __ieee80211_suspend (wiphy_priv (wiphy), wowlan); +return __ieee80211_suspend (wiphy_priv (wiphy), wowlan, false); }static int ieee80211_resume (struct wiphy *wiphy)
net/mac80211/debugfs.c +1 -1
@@ -388,7 +388,7 @@ static ssize_t reset_write(struct file *file, const char __user *user_buf,rtnl_lock ();wiphy_lock (local->hw.wiphy); -__ieee80211_suspend (&local->hw,NULL ); +__ieee80211_suspend (&local->hw,NULL , true); ret =__ieee80211_resume (&local->hw);wiphy_unlock (local->hw.wiphy);
net/mac80211/ieee80211_i.h +1 -1
@@ -2433,7 +2433,7 @@ int ieee80211_reconfig(struct ieee80211_local *local);void ieee80211_stop_device (struct ieee80211_local *local,bool suspend);int __ieee80211_suspend (struct ieee80211_hw *hw, -struct cfg80211_wowlan *wowlan); +struct cfg80211_wowlan *wowlan,bool reset);static inline int __ieee80211_resume (struct ieee80211_hw *hw) {
net/mac80211/pm.c +5 -3
@@ -18,7 +18,8 @@ static void ieee80211_sched_scan_cancel(struct ieee80211_local *local)cfg80211_sched_scan_stopped_locked (local->hw.wiphy,0 ); } -int __ieee80211_suspend (struct ieee80211_hw *hw,struct cfg80211_wowlan *wowlan) +int __ieee80211_suspend (struct ieee80211_hw *hw,struct cfg80211_wowlan *wowlan, +bool reset) {struct ieee80211_local *local =hw_to_local (hw);struct ieee80211_sub_if_data *sdata;
@@ -166,9 +167,10 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)/* * We disconnected on all interfaces before suspend, all channel -* contexts should be released. +* contexts should be released, but on 'reset' debugfs that's +* not true so don't check there. */ -WARN_ON (!list_empty (&local->chanctx_list)); +WARN_ON (!reset && !list_empty (&local->chanctx_list));/* stop hardware - this must stop RX */ ieee80211_stop_device (local, true);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 73/438 wifi: mac80211: abort chanswitch when leaving a mesh
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit ac7472a24bd433b81c06582835dd1d5547c10da9 ]
The code in ieee80211_stop_mesh() leaves CSA active, but leaving the mesh released the channel context, so the CSA finalize work crashes:
Oops: general protection fault, probably for non-canonical address
0xdffffc0000000003
KASAN: null-ptr-deref in range [0x0000000000000018-0x000000000000001f]
RIP: 0010:ieee80211_put_srates_elem+0x42/0x640 net/mac80211/util.c:3272
Call Trace:
ieee80211_mesh_build_beacon+0xa83/0x1b50 net/mac80211/mesh.c:1093
ieee80211_mesh_rebuild_beacon+0xc7/0x170 net/mac80211/mesh.c:1147
ieee80211_mesh_finish_csa+0x131/0x210 net/mac80211/mesh.c:1542
ieee80211_set_after_csa_beacon net/mac80211/cfg.c:4085 [inline]
__ieee80211_csa_finalize net/mac80211/cfg.c:4133 [inline]
ieee80211_csa_finalize+0x633/0x1150 net/mac80211/cfg.c:4155
cfg80211_wiphy_work+0x2ab/0x450 net/wireless/core.c:438Abort the channel switch properly.
--- net/mac80211/mesh.c | 4 ++++ 1 file changed, 4 insertions(+)
net/mac80211/mesh.c +4 -0
@@ -1204,6 +1204,10 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)netif_carrier_off (sdata->dev); +/* abort any running channel switch */ + sdata->vif.bss_conf.csa_active = false; +ieee80211_vif_unblock_queues_csa (sdata); +/* flush STAs and mpaths on this iface */ sta_info_flush (sdata,-1 );ieee80211_free_keys (sdata, true);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 74/438 wifi: mac80211: reset state when starting AP fails
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 3f28551d0241254a75626d868041c6340285088b ]
ieee80211_start_ap() can set enable_beacon (and beacon_int) and fail later, leaving it set forever. Scanning can then attempt to restore beaconing on such an interface, leading to:
Oops: divide error: 0000 [#1] SMP KASAN NOPTI RIP: 0010:mac80211_hwsim_link_info_changed+0xca7/0xf00 Call Trace: drv_link_info_changed+0x413/0x860 net/mac80211/driver-ops.c:495 ieee80211_link_info_change_notify+0x24b/0x3c0 net/mac80211/main.c:427 ieee80211_offchannel_return+0x381/0x580 net/mac80211/offchannel.c:160 __ieee80211_scan_completed+0x993/0xe30 net/mac80211/scan.c:519 ieee80211_scan_work+0x472/0x2010 net/mac80211/scan.c:1193 cfg80211_wiphy_work+0x2b7/0x550 net/wireless/core.c:538
in hwsim. Also, cfg80211 then allows changing the interface type, and the off-channel path getgs confused about beaconing as well, leading to another warning:
WARNING: net/mac80211/driver-ops.c:468 at drv_link_info_changed+0x583/0x880 ieee80211_link_info_change_notify+0x24b/0x3c0 net/mac80211/main.c:427 ieee80211_offchannel_stop_vifs+0x328/0x5c0 net/mac80211/offchannel.c:122 ieee80211_start_sw_scan net/mac80211/scan.c:583 [inline] __ieee80211_start_scan+0xfb6/0x1af0 net/mac80211/scan.c:882
Reset the state on failures to always have it correct.
--- net/mac80211/cfg.c | 3 +++ 1 file changed, 3 insertions(+)
net/mac80211/cfg.c +3 -0
@@ -1929,6 +1929,9 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,return 0 ; error: + link_conf->enable_beacon = false; + link_conf->beacon_int = prev_beacon_int; + sdata->vif.cfg.ssid_len =0 ;ieee80211_link_release_channel (link);return err;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 75/438 wifi: mac80211: reset the LED state when ifup fails
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 78183e8331958fda11cd2b6850bb424a9747c4b2 ]
When the first interface comes up, the radio LED is turned on. This can start the TPT trigger timer, which continues running.
But if bringing up the interface fails then the timer keeps running and won't be stopped by anything, eventually it can be freed:
ODEBUG: free active (active state 0) object: ffff888127e12130 object type: timer_list hint: tpt_trig_timer+0x0/0x300 net/mac80211/led.c:145
WARNING: CPU: 0 PID: 5923 at lib/debugobjects.c:612 debug_print_object+0x1a2/0x2b0 debug_check_no_obj_freed+0x4b7/0x600 lib/debugobjects.c:1129 kfree+0x436/0x670 mm/slub.c:6818 ieee80211_led_exit+0x162/0x1c0 net/mac80211/led.c:210 ieee80211_unregister_hw+0x27e/0x3a0 net/mac80211/main.c:1706 rt2x00lib_remove_dev+0x55b/0x670
Undo the LED state in the error path.
--- net/mac80211/iface.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
net/mac80211/iface.c +5 -1
@@ -1606,8 +1606,12 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) err_del_interface:drv_remove_interface (local, sdata); err_stop: -if (!local->open_count) +if (!local->open_count) { +ieee80211_led_radio (local, false); +ieee80211_mod_tpt_led_trig (local,0 , +IEEE80211_TPT_LEDTRIG_FL_RADIO );drv_stop (local, false); + }if (sdata->vif.type ==NL80211_IFTYPE_NAN_DATA )RCU_INIT_POINTER (sdata->u.nan_data.nmi,NULL );if (sdata->vif.type ==NL80211_IFTYPE_AP_VLAN )
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 76/438 wifi: mac80211: only operate on TDLS peers in the TDLS code
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 6f0a100df8539ce90f37c14e1945f396ca2410bc ]
ieee80211_tdls_oper() can operate on the AP station, which then yields various warnings when the AP station is removed then or at a later point in time after being confused for a TDLS peer.
Always check that the station is a TDLS peer.
--- net/mac80211/tdls.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-)
net/mac80211/tdls.c +9 -12
@@ -1142,6 +1142,7 @@ ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev,struct ieee80211_local *local = sdata->local;enum ieee80211_smps_mode smps_mode = sdata->deflink.u.mgd.driver_smps_mode; +struct sta_info *sta;int ret;/* don't support setup with forced SMPS mode that's not off */
@@ -1168,14 +1169,10 @@ ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev,* Allow error packets to be sent - sometimes we don't even add a STA * before failing the setup. */ -if (status_code ==0 ) { -rcu_read_lock (); -if (!sta_info_get (sdata, peer)) { -rcu_read_unlock (); - ret = -ENOLINK ; - goto out_unlock; - } -rcu_read_unlock (); + sta =sta_info_get (sdata, peer); +if ((status_code ==0 && !sta) || (sta && !sta->sta.tdls)) { + ret = -ENOLINK ; + goto out_unlock; }ieee80211_flush_queues (local, sdata, false);
@@ -1442,6 +1439,10 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,*/ tdls_dbg (sdata,"TDLS oper %d peer %pM\n" , oper, peer); + sta =sta_info_get (sdata, peer); +if (!sta || !sta->sta.tdls) +return -ENOLINK ; +switch (oper) {case NL80211_TDLS_ENABLE_LINK :if (sdata->vif.bss_conf.csa_active) {
@@ -1449,10 +1450,6 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,return -EBUSY ; } - sta =sta_info_get (sdata, peer); -if (!sta || !sta->sta.tdls) -return -ENOLINK ; -iee80211_tdls_recalc_chanctx (sdata, sta);iee80211_tdls_recalc_ht_protection (sdata, sta);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 77/438 wifi: cfg80211: restore netns_immutable on failures
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit eeee52cfd1d639774c9812e8890631404a057dd2 ]
Switching a wiphy's netns has to clear netns_immutable before moving interfaces, but then if any of the interfaces fails to move, it gets netns_immutable cleared forever. Then userspace can move it by itself, breaking the assumption that they all move together.
Fix the order here and always reset netns_immutable after attempting the move.
--- net/wireless/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/wireless/core.c +1 -1
@@ -167,9 +167,9 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,continue ; wdev->netdev->netns_immutable = false; err =dev_change_net_namespace (wdev->netdev, net,"wlan%d" ); + wdev->netdev->netns_immutable = true;if (err)break ; - wdev->netdev->netns_immutable = true; }if (err) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 78/438 wifi: cfg80211: undo netns switch if renaming the wiphy fails
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit a41bd1938a9bfe226d444172a7e20e4bd5097960 ]
Once all the interfaces have been moved, cfg80211_switch_netns() moves the wiphy itself by setting its network namespace and then renaming it, which makes sysfs move it. The rename can fail (but only on allocation failures), leaving things mixed up and hitting the warning there.
Ignoring it isn't great, undo the move and let the change fail in this case. If undo fails then WARN, then things would again be stuck in two different network namespaces.
--- net/wireless/core.c | 88 +++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 38 deletions(-)
net/wireless/core.c +50 -38
@@ -153,9 +153,25 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,return 0 ; } +static int cfg80211_switch_wdev_netns (struct wireless_dev *wdev, +struct net *net) +{ +int err; + +if (!wdev->netdev) +return 0 ; + + wdev->netdev->netns_immutable = false; + err =dev_change_net_namespace (wdev->netdev, net,"wlan%d" ); + wdev->netdev->netns_immutable = true; + +return err; +} +int cfg80211_switch_netns (struct cfg80211_registered_device *rdev,struct net *net) { +struct net *old_net =wiphy_net (&rdev->wiphy);struct wireless_dev *wdev;int err =0 ;
@@ -163,58 +179,54 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,return -EOPNOTSUPP ;list_for_each_entry (wdev, &rdev->wiphy.wdev_list, list) { -if (!wdev->netdev) -continue ; - wdev->netdev->netns_immutable = false; - err =dev_change_net_namespace (wdev->netdev, net,"wlan%d" ); - wdev->netdev->netns_immutable = true; + err =cfg80211_switch_wdev_netns (wdev, net);if (err) -break ; + goto undo; } -if (err) { -/* failed -- clean up to old netns */ - net =wiphy_net (&rdev->wiphy); - -list_for_each_entry_continue_reverse (wdev, - &rdev->wiphy.wdev_list, - list) { + scoped_guard(wiphy, &rdev->wiphy) { +list_for_each_entry (wdev, &rdev->wiphy.wdev_list, list) {if (!wdev->netdev)continue ; - wdev->netdev->netns_immutable = false; - err =dev_change_net_namespace (wdev->netdev, net, -"wlan%d" ); -WARN_ON (err); - wdev->netdev->netns_immutable = true; +nl80211_notify_iface (rdev, wdev, +NL80211_CMD_DEL_INTERFACE ); } -return err; - } +nl80211_notify_wiphy (rdev,NL80211_CMD_DEL_WIPHY ); -guard (wiphy)(&rdev->wiphy); +wiphy_net_set (&rdev->wiphy, net); -list_for_each_entry (wdev, &rdev->wiphy.wdev_list, list) { -if (!wdev->netdev) -continue ; -nl80211_notify_iface (rdev, wdev,NL80211_CMD_DEL_INTERFACE ); - } - -nl80211_notify_wiphy (rdev,NL80211_CMD_DEL_WIPHY ); +/* this only fails on allocation failure */ + err =device_rename (&rdev->wiphy.dev, +dev_name (&rdev->wiphy.dev)); +if (err) +wiphy_net_set (&rdev->wiphy, old_net); -wiphy_net_set (&rdev->wiphy, net); +nl80211_notify_wiphy (rdev,NL80211_CMD_NEW_WIPHY ); - err =device_rename (&rdev->wiphy.dev,dev_name (&rdev->wiphy.dev)); -WARN_ON (err); +list_for_each_entry (wdev, &rdev->wiphy.wdev_list, list) { +if (!wdev->netdev) +continue ; +nl80211_notify_iface (rdev, wdev, +NL80211_CMD_NEW_INTERFACE ); + } + } -nl80211_notify_wiphy (rdev,NL80211_CMD_NEW_WIPHY ); +if (!err) +return 0 ; -list_for_each_entry (wdev, &rdev->wiphy.wdev_list, list) { -if (!wdev->netdev) -continue ; -nl80211_notify_iface (rdev, wdev,NL80211_CMD_NEW_INTERFACE ); - } +/* set to the last one to undo all of them */ + wdev =list_entry (&rdev->wiphy.wdev_list,typeof (*wdev), list); +undo: +/* +* Move back everything, if this fails again (allocation failures) +* then things get stuck in different network namespaces. +*/ +list_for_each_entry_continue_reverse (wdev, &rdev->wiphy.wdev_list, + list) +WARN_ON (cfg80211_switch_wdev_netns (wdev, old_net)); -return 0 ; +return err; }static void cfg80211_rfkill_poll (struct rfkill *rfkill,void *data)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 79/438 wifi: mac80211: unlist vifs when their netdev is unregistered
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit eee2efd82867b623982ac51925b5a1812a74c50d ]
mac80211 only removes vifs from the local->interfaces list when an interface is removed via ieee80211_if_remove(), before it unregisters the netdev. However, it's possible for a netdev to be unregistered without going through that: When the netns that holds the wiphy is destroyed, the wiphy is supposed to move to the init_ns, but that can run into allocation failures.
Then, mac80211 has an interface listed that doesn't exist, and will eventually hit
BUG: failure at net/wireless/core.h:141/wiphy_to_rdev()! ... _cfg80211_unregister_wdev+0x24/0x36a [cfg80211] cfg80211_unregister_wdev+0x15/0x1d [cfg80211] ieee80211_remove_interfaces+0x1ff/0x257 [mac80211] ieee80211_unregister_hw+0x73/0x1d1 [mac80211] mac80211_hwsim_del_radio+0x114/0x166 [mac80211_hwsim]
Remove the interface from the list in ->ndo_uninit if it's still around to avoid this.
--- net/mac80211/iface.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-)
net/mac80211/iface.c +25 -1
@@ -924,9 +924,33 @@ static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata) } } +/* +* The netdev can be unregistered without mac80211 doing it, e.g. by the netdev +* core when cfg80211 couldn't move it out of a network namespace that's being +* destroyed. Drop it from the interface list either way. +*/ +static void ieee80211_unlist_sdata (struct ieee80211_sub_if_data *sdata) +{ +struct ieee80211_local *local = sdata->local; +struct ieee80211_sub_if_data *iter; + +ASSERT_RTNL (); + +list_for_each_entry (iter, &local->interfaces, list) { +if (iter != sdata) +continue ; +guard (mutex)(&local->iflist_mtx); +list_del_rcu (&sdata->list); +return ; + } +} +static void ieee80211_uninit (struct net_device *dev) { -ieee80211_teardown_sdata (IEEE80211_DEV_TO_SUB_IF (dev)); +struct ieee80211_sub_if_data *sdata =IEEE80211_DEV_TO_SUB_IF (dev); + +ieee80211_unlist_sdata (sdata); +ieee80211_teardown_sdata (sdata); } static int ieee80211_netdev_setup_tc(struct net_device *dev,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 80/438 wifi: cfg80211: get the wiphy out of a dying network namespace
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 4635b1a1c1d693178a537446a6e09963f0fdae52 ]
When a network namespace is destroyed, cfg80211_pernet_exit() moves any wiphy back to the initial namespace, and just warns if that fails. But moving an interface can fail (due to allocation failures), and then the wiphy is left behind with a garbage netns pointer:
Kernel mode fault at addr 0x30
genlmsg_multicast_netns.constprop.0+0x46/0xcf [cfg80211] nl80211_notify_wiphy+0xcd/0xe8 [cfg80211] wiphy_unregister+0x169/0x3fc [cfg80211]
Note that commit debac3a20dec ("net: Remove conflicting altnames for dying netns in __dev_change_net_namespace().") fixed another path that could reach it without allocation failures.
Remove interfaces that cannot be moved instead of failing the switch, so that the wiphy always ends up in the initial namespace. In this case the netdev core will unregister the interfaces anyway.
--- net/wireless/core.c | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-)
net/wireless/core.c +25 -12
@@ -168,20 +168,24 @@ static int cfg80211_switch_wdev_netns(struct wireless_dev *wdev,return err; } -int cfg80211_switch_netns (struct cfg80211_registered_device *rdev, -struct net *net) +static int __cfg80211_switch_netns (struct cfg80211_registered_device *rdev, +struct net *net,bool force) {struct net *old_net =wiphy_net (&rdev->wiphy); -struct wireless_dev *wdev; +struct wireless_dev *wdev, *tmp;int err =0 ; -if (!(rdev->wiphy.flags &WIPHY_FLAG_NETNS_OK )) -return -EOPNOTSUPP ; - -list_for_each_entry (wdev, &rdev->wiphy.wdev_list, list) { +list_for_each_entry_safe (wdev, tmp, &rdev->wiphy.wdev_list, list) { err =cfg80211_switch_wdev_netns (wdev, net); -if (err) +if (!err) +continue ; +if (!force) goto undo; +/* remove interfaces that fail to allow wiphy switching */ +dev_close (wdev->netdev); + scoped_guard(wiphy, &rdev->wiphy) +cfg80211_unregister_wdev (wdev); + err =0 ; } scoped_guard(wiphy, &rdev->wiphy) {
@@ -199,7 +203,7 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,/* this only fails on allocation failure */ err =device_rename (&rdev->wiphy.dev,dev_name (&rdev->wiphy.dev)); -if (err) +if (err && !force)wiphy_net_set (&rdev->wiphy, old_net);nl80211_notify_wiphy (rdev,NL80211_CMD_NEW_WIPHY );
@@ -212,8 +216,8 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, } } -if (!err) -return 0 ; +if (!err || force) +return err;/* set to the last one to undo all of them */ wdev =list_entry (&rdev->wiphy.wdev_list,typeof (*wdev), list);
@@ -229,6 +233,15 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,return err; } +int cfg80211_switch_netns (struct cfg80211_registered_device *rdev, +struct net *net) +{ +if (!(rdev->wiphy.flags &WIPHY_FLAG_NETNS_OK )) +return -EOPNOTSUPP ; + +return __cfg80211_switch_netns (rdev, net, false); +} +static void cfg80211_rfkill_poll (struct rfkill *rfkill,void *data) {struct cfg80211_registered_device *rdev = data;
@@ -1879,7 +1892,7 @@ static void __net_exit cfg80211_pernet_exit(struct net *net)rtnl_lock ();for_each_rdev (rdev) {if (net_eq (wiphy_net (&rdev->wiphy), net)) -WARN_ON (cfg80211_switch_netns (rdev, &init_net)); +WARN_ON (__cfg80211_switch_netns (rdev, &init_net, true)); }rtnl_unlock (); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 81/438 wifi: mac80211_hwsim: dont hand frames to mac80211 while stopping
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 87840d4a3a21b1c19b867a80e16ba69dff284de2 ]
The code checks ->started for frames coming from wmediumd, but the radio can be stopped after the check and before frame delivery, causing mac80211 to hit the WARN_ON(!local->started).
Expand the mutex for this case and synchronise against it when the radio is stopped to avoid being able to hit the warning with hwsim.
Drop the error print that would've complicated the error path, it only triggers for allocation failures (already noisy) and malformed frames anyway.
--- .../wireless/virtual/mac80211_hwsim_main.c | 39 ++++++++++++------- 1 file changed, 24 insertions(+), 15 deletions(-)
drivers/net/wireless/virtual/mac80211_hwsim_main.c +24 -15
@@ -2317,7 +2317,12 @@ static void mac80211_hwsim_stop(struct ieee80211_hw *hw, bool suspend)struct sk_buff *skb;int i; - data->started = false; +/* +* Serialise against wmediumd userspace, so no more frames +* can be handed to mac80211 after this returns. +*/ +scoped_guard (mutex, &data->mutex) + data->started = false;for (i =0 ; i <ARRAY_SIZE (data->link_data); i++)hrtimer_cancel (&data->link_data[i].beacon_timer);
@@ -6453,12 +6458,12 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,if (frame_data_len <sizeof (struct ieee80211_hdr_3addr ) || frame_data_len >IEEE80211_MAX_DATA_LEN ) - goto err; + goto out;/* Allocate new skb here */ skb =alloc_skb (frame_data_len,GFP_KERNEL );if (skb ==NULL ) - goto err; + goto out;/* Copy the data */ skb_put_data (skb, frame_data, frame_data_len);
@@ -6483,10 +6488,17 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, goto out; } +/* +* Serialise against mac80211_hwsim_stop() - mac80211 doesn't allow +* frames reported while the HW is down, hence the ->started check +* must be under mutex. +*/ +mutex_lock (&data2->mutex); +/* check if radio is configured properly */ if ((data2->idle && !data2->tmp_chan) || !data2->started) - goto out; + goto out_unlock;/* A frame is received from user space */ memset (&rx_status,0 ,sizeof (rx_status));
@@ -6505,22 +6517,18 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, iter_data.channel =ieee80211_get_channel (data2->hw->wiphy, rx_status.freq);if (!iter_data.channel) - goto out; + goto out_unlock; rx_status.band = iter_data.channel->band; -mutex_lock (&data2->mutex);if (!hwsim_chans_compat (iter_data.channel, channel)) {ieee80211_iterate_active_interfaces_atomic ( data2->hw,IEEE80211_IFACE_ITER_NORMAL , mac80211_hwsim_tx_iter, &iter_data); -if (!iter_data.receive) { -mutex_unlock (&data2->mutex); - goto out; - } +if (!iter_data.receive) + goto out_unlock; } -mutex_unlock (&data2->mutex); }else if (!channel) { - goto out; + goto out_unlock; }else { rx_status.freq = channel->center_freq; rx_status.band = channel->band;
@@ -6528,7 +6536,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, rx_status.rate_idx =nla_get_u32 (info->attrs[HWSIM_ATTR_RX_RATE ]);if (rx_status.rate_idx >= data2->hw->wiphy->bands[rx_status.band]->n_bitrates) - goto out; + goto out_unlock; rx_status.signal =nla_get_u32 (info->attrs[HWSIM_ATTR_SIGNAL ]); hdr = (void *)skb->data;
@@ -6538,10 +6546,11 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, rx_status.boottime_ns =ktime_get_boottime_ns ();mac80211_hwsim_rx (data2, &rx_status, skb); +mutex_unlock (&data2->mutex);return 0 ; -err: -pr_debug ("mac80211_hwsim: error occurred in %s\n" , __func__); +out_unlock: +mutex_unlock (&data2->mutex); out:dev_kfree_skb (skb);return -EINVAL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 82/438 wifi: mac80211: dont allow injecting frames wider than the chanctx
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit e14bf37bb2b3853012ff160131d1c6233f7a9cc9 ]
Frames injected on a monitor interface can carry a radiotap field requesting a bandwidth, which mac80211 passes down to the driver regardless of the the actual operational bandwidth.
If the bandwidth requested is too wide, that triggers a warning in hwsim:
WARN_ON(hwsim_get_chanwidth(bw) > hwsim_get_chanwidth(confbw))
Drop such frames entirely instead since they cannot be sent.
--- include/net/mac80211.h | 5 ++++- net/mac80211/iface.c | 2 +- net/mac80211/tx.c | 28 ++++++++++++++++++++++++++-- 3 files changed, 31 insertions(+), 4 deletions(-)
include/net/mac80211.h +4 -1
@@ -7615,11 +7615,14 @@ bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw,* * @skb: packet injected by userspace * @dev: the &struct device of this 802.11 device +* @chandef: the channel definition the frame will be transmitted on, or +* %NULL to skip the bandwidth checks * * Return: %true if the radiotap header was parsed, %false otherwise */ bool ieee80211_parse_tx_radiotap (struct sk_buff *skb, -struct net_device *dev); +struct net_device *dev, +const struct cfg80211_chan_def *chandef);/** * struct ieee80211_noa_data - holds temporary data for tracking P2P NoA state
net/mac80211/iface.c +1 -1
@@ -991,7 +991,7 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev,/* reset flags and info before parsing radiotap header */ memset (info,0 ,sizeof (*info)); -if (!ieee80211_parse_tx_radiotap (skb, dev)) +if (!ieee80211_parse_tx_radiotap (skb, dev,NULL ))return 0 ;/* doesn't matter, frame will be dropped */ len_rthdr =ieee80211_get_radiotap_len (skb->data);
net/mac80211/tx.c +26 -2
@@ -2096,8 +2096,29 @@ static bool ieee80211_validate_radiotap_len(struct sk_buff *skb)return true; } +static bool ieee80211_rate_bw_usable (u16 rate_flags, +const struct cfg80211_chan_def *chandef) +{ +int width; + +if (!chandef) +return true; + +if (rate_flags &IEEE80211_TX_RC_160_MHZ_WIDTH ) + width =160 ; +else if (rate_flags &IEEE80211_TX_RC_80_MHZ_WIDTH ) + width =80 ; +else if (rate_flags &IEEE80211_TX_RC_40_MHZ_WIDTH ) + width =40 ; +else +return true; + +return width <=cfg80211_chandef_get_width (chandef); +} +bool ieee80211_parse_tx_radiotap (struct sk_buff *skb, -struct net_device *dev) +struct net_device *dev, +const struct cfg80211_chan_def *chandef) {struct ieee80211_local *local =wdev_priv (dev->ieee80211_ptr);struct ieee80211_radiotap_iterator iterator;
@@ -2271,6 +2292,9 @@ bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,struct ieee80211_supported_band *sband = local->hw.wiphy->bands[info->band]; +if (!ieee80211_rate_bw_usable (rate_flags, chandef)) +return false; + info->control.flags |=IEEE80211_TX_CTRL_RATE_INJECT ;for (i =0 ; i <IEEE80211_TX_MAX_RATES ; i++) {
@@ -2470,7 +2494,7 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,* selected chandef above to accurately set injection rates and * retransmissions. */ -if (!ieee80211_parse_tx_radiotap (skb, dev)) +if (!ieee80211_parse_tx_radiotap (skb, dev, chandef)) goto fail_rcu;/* remove the injection radiotap header */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 83/438 wifi: mac80211: reset the AP_VLAN tailroom counter on ifdown
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 4504f3960dc4501c73be9f99eabda2e26e9db41e ]
On ifup, AP_VLAN interfaces get crypto_tx_tailroom_needed_cnt from the AP interface, but it's never decremented again unless the AP is also brought down. Thus, bringing the same AP_VLAN up again will increment the counter again and eventually hit the sanity check:
WARN_ON_ONCE(sdata->crypto_tx_tailroom_needed_cnt !=
master->crypto_tx_tailroom_needed_cnt);
Reset it on ifdown to avoid that.
--- net/mac80211/iface.c | 2 ++ 1 file changed, 2 insertions(+)
net/mac80211/iface.c +2 -0
@@ -616,6 +616,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_doRCU_INIT_POINTER (sdata->vif.bss_conf.chanctx_conf,NULL );/* see comment in the default case below */ ieee80211_free_keys (sdata, true); +/* increased by AP value on ifup, so reset on ifdown */ + sdata->crypto_tx_tailroom_needed_cnt =0 ;/* no need to tell driver */ break ;case NL80211_IFTYPE_MONITOR :
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 84/438 wifi: mac80211: require a peer station for TDLS setup confirm
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 038e1d126304fd25d507fd4e671232df57bd1799 ]
It's nonsense for the setup confirm to go to station that doesn't even exist, and it hits a warning when building the frame:
WARN_ON_ONCE(!sta || !ap_sta)
Only accept WLAN_TDLS_SETUP_CONFIRM when the station is already there as a TDLS station. Need to copy the call to ieee80211_tdls_prep_mgmt_packet() since the existing WLAN_TDLS_DISCOVERY_REQUEST already falls through to it.
--- net/mac80211/tdls.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-)
net/mac80211/tdls.c +18 -1
@@ -1281,6 +1281,24 @@ int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, peer_capability, initiator, extra_ies, extra_ies_len);break ; +case WLAN_TDLS_SETUP_CONFIRM : { +struct sta_info *sta; + + sta =sta_info_get (sdata, peer); +if (!sta || !sta->sta.tdls) { + ret = -ENOLINK ; +break ; + } + + ret =ieee80211_tdls_prep_mgmt_packet (wiphy, dev, peer, + link_id, action_code, + dialog_token, + status_code, + peer_capability, + initiator, extra_ies, + extra_ies_len,0 ,NULL ); +break ; + }case WLAN_TDLS_DISCOVERY_REQUEST :/* * Protect the discovery so we can hear the TDLS discovery
@@ -1289,7 +1307,6 @@ int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,*/ drv_mgd_protect_tdls_discover (sdata->local, sdata, link_id); fallthrough; -case WLAN_TDLS_SETUP_CONFIRM :case WLAN_PUB_ACTION_TDLS_DISCOVER_RES :/* no special handling */ ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 85/438 wifi: mac80211: dont allow link changes when iface is down
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 370872d30349d81dec519e15ea2949fd63511cf7 ]
ieee80211_set_active_links() only checks that the interface is running in the inner __ieee80211_set_active_links(), after drv_can_activate_links() was already called, so using active_links on an interface that's down triggers the check-sdata-in-driver warning.
Add the missing check in the debugfs file.
--- net/mac80211/debugfs_netdev.c | 3 +++ 1 file changed, 3 insertions(+)
net/mac80211/debugfs_netdev.c +3 -0
@@ -729,6 +729,9 @@ static ssize_t ieee80211_if_parse_active_links(struct ieee80211_sub_if_data *sdaif (kstrtou16 (buf,0 , &active_links) || !active_links)return -EINVAL ; +if (!ieee80211_sdata_running (sdata)) +return -ENETDOWN ; +return ieee80211_set_active_links (&sdata->vif, active_links) ?: buflen; }IEEE80211_IF_FILE_RW (active_links);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 86/438 wifi: mac80211: dont RCU-dereference the mesh CSA settings we just set
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit b481e64e4498e2c053d5954f546ee02338f6ab63 ]
In the error path of ieee80211_mesh_csa_beacon() the settings that were just assigned are read back with rcu_dereference(), which lockdep then complains about.
There's no need to read the pointer at all, tmp_csa_settings still is the right value anyway.
--- net/mac80211/mesh.c | 1 - 1 file changed, 1 deletion(-)
net/mac80211/mesh.c +0 -1
@@ -1559,7 +1559,6 @@ int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata, ret =ieee80211_mesh_rebuild_beacon (sdata);if (ret) { - tmp_csa_settings =rcu_dereference (ifmsh->csa);RCU_INIT_POINTER (ifmsh->csa,NULL );kfree_rcu (tmp_csa_settings, rcu_head);return ret;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 87/438 wifi: mac80211: dont access the TSF of a down interface
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 0b1de9feeb8651f7a3bb53ed7c9006e3b5298c01 ]
The tsf debugfs files call the driver even if the interface isn't up, tgriggering check-sdata-in-driver warnings.
Reject the access in that case.
--- net/mac80211/debugfs_netdev.c | 6 ++++++ 1 file changed, 6 insertions(+)
net/mac80211/debugfs_netdev.c +6 -0
@@ -657,6 +657,9 @@ static ssize_t ieee80211_if_fmt_tsf(struct ieee80211_local *local = sdata->local;u64 tsf; +if (!ieee80211_sdata_running ((struct ieee80211_sub_if_data *)sdata)) +return -ENETDOWN ; + tsf =drv_get_tsf (local, (struct ieee80211_sub_if_data *)sdata);return scnprintf (buf, buflen,"0x%016llx\n" , (unsigned long long ) tsf);
@@ -670,6 +673,9 @@ static ssize_t ieee80211_if_parse_tsf(int ret;int tsf_is_delta =0 ; +if (!ieee80211_sdata_running (sdata)) +return -ENETDOWN ; +if (strncmp (buf,"reset" ,5 ) ==0 ) {if (local->ops->reset_tsf) {drv_reset_tsf (local, sdata);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 88/438 wifi: mac80211: add HE 6 GHz capability in the scan elems len
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit cd54bf333f5631d3630bab0a832e9ae648f73515 ]
The HE 6 GHz Band Capability element is in the probe request for every band if 6 GHz is supported, so add the size to scan_ies_len.
Otherwise, building probe request elements can fail, triggering the WARN_ON in __ieee80211_start_scan().
--- net/mac80211/main.c | 4 ++++ 1 file changed, 4 insertions(+)
net/mac80211/main.c +4 -0
@@ -1454,6 +1454,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)sizeof (struct ieee80211_he_mcs_nss_supp ) +IEEE80211_HE_PPE_THRES_MAX_LEN ; +if (local->hw.wiphy->bands[NL80211_BAND_6GHZ ]) + local->scan_ies_len += +3 +sizeof (struct ieee80211_he_6ghz_capa ); +if (supp_eht) local->scan_ies_len += 3 + sizeof(struct ieee80211_eht_cap_elem) +
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 89/438 wifi: mac80211: mesh: reset the CSA state when leaving
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 860134b3af77970e006feab7e5decb8c84771c7f ]
ifmsh->csa is allocated in ieee80211_mesh_csa_beacon() and only freed in ieee80211_mesh_finish_csa(), i.e. when the channel switch completes. Leaving the mesh while a switch is still pending therefore leaks it.
Additionally, ifmsh->csa_role and ifmsh->chsw_ttl have their state leak in this case, so things can get mixed up in addition to the memory leak.
Refactor the reset and call it in ieee80211_stop_mesh() to fix it all.
--- net/mac80211/mesh.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-)
net/mac80211/mesh.c +18 -11
@@ -1196,6 +1196,21 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)return 0 ; } +static void ieee80211_mesh_reset_csa (struct ieee80211_sub_if_data *sdata) +{ +struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; +struct mesh_csa_settings *csa; + +/* Reset the TTL value and Initiator flag */ + ifmsh->csa_role =IEEE80211_MESH_CSA_ROLE_NONE ; + ifmsh->chsw_ttl =0 ; + +/* Remove the CSA and MCSP elements from the beacon */ + csa =sdata_dereference (ifmsh->csa, sdata); +RCU_INIT_POINTER (ifmsh->csa,NULL ); +kfree_rcu (csa, rcu_head); +} +void ieee80211_stop_mesh (struct ieee80211_sub_if_data *sdata) {struct ieee80211_local *local = sdata->local;
@@ -1206,6 +1221,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)/* abort any running channel switch */ sdata->vif.bss_conf.csa_active = false; +ieee80211_mesh_reset_csa (sdata);ieee80211_vif_unblock_queues_csa (sdata);/* flush STAs and mpaths on this iface */
@@ -1514,19 +1530,10 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,int ieee80211_mesh_finish_csa (struct ieee80211_sub_if_data *sdata,u64 *changed) { -struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; -struct mesh_csa_settings *tmp_csa_settings; -int ret =0 ; +int ret; -/* Reset the TTL value and Initiator flag */ - ifmsh->csa_role =IEEE80211_MESH_CSA_ROLE_NONE ; - ifmsh->chsw_ttl =0 ; +ieee80211_mesh_reset_csa (sdata); -/* Remove the CSA and MCSP elements from the beacon */ - tmp_csa_settings =sdata_dereference (ifmsh->csa, sdata); -RCU_INIT_POINTER (ifmsh->csa,NULL ); -if (tmp_csa_settings) -kfree_rcu (tmp_csa_settings, rcu_head); ret =ieee80211_mesh_rebuild_beacon (sdata);if (ret)return -EINVAL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 90/438 wifi: mac80211: mesh: release the channel if start fails
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit ae97fff6495a8764bc0ef281cfe5444f701e527f ]
ieee80211_join_mesh() acquires a channel context and then calls ieee80211_start_mesh(), which can fail. In that case, the chanctx isn't released then interface removal will attempt to unassign it after it's removed from the driver, hitting:
wlan0: Failed check-sdata-in-driver check, flags: 0x0
WARNING: net/mac80211/driver-ops.c:366 at drv_unassign_vif_chanctx ieee80211_assign_link_chanctx __ieee80211_link_release_channel ieee80211_link_release_channel ieee80211_teardown_sdata unregister_netdevice_many_notify _cfg80211_unregister_wdev ieee80211_remove_interfaces ieee80211_unregister_hw mac80211_hwsim_del_radio hwsim_exit_net
Correctly release the channel on start failures.
--- net/mac80211/cfg.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
net/mac80211/cfg.c +5 -1
@@ -3323,7 +3323,11 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev,if (err)return err; -return ieee80211_start_mesh (sdata); + err =ieee80211_start_mesh (sdata); +if (err) +ieee80211_link_release_channel (&sdata->deflink); + +return err; }static int ieee80211_leave_mesh (struct wiphy *wiphy,struct net_device *dev)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 91/438 wifi: mac80211: set up the TX info early to fix failure paths
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 50d3d79dc0743b616afb00d01a626c76758721f7 ]
The previous commit 2c51457d930f ("wifi: mac80211: free ack status frame on TX header build failure") cleaned up the leak, but still left the code a bit messy and the failed SKB didn't get reported to userspace.
Fix this up by initialising skb->cb[] earlier, which allows using ieee80211_free_txskb() and therefore reports it for the failure in ieee80211_build_hdr(), and unifies the ieee80211_skb_resize() failure path with it.
--- net/mac80211/tx.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-)
net/mac80211/tx.c +20 -18
@@ -2974,10 +2974,23 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,*/ skb =skb_share_check (skb,GFP_ATOMIC );if (unlikely (!skb)) { - ret = -ENOMEM ; - goto free; +/* skb_share_check() already freed the skb */ +if (info_id) +ieee80211_remove_ack_skb (local, info_id); +return ERR_PTR (-ENOMEM ); } +/* set this up so failure paths can clean up ack skb */ + info =IEEE80211_SKB_CB (skb); +memset (info,0 ,sizeof (*info)); + + info->flags = info_flags; +if (info_id) { + info->status_data = info_id; + info->status_data_idr =1 ; + } + info->band = band; + hdr.frame_control = fc; hdr.duration_id =0 ; hdr.seq_ctrl =0 ;
@@ -3016,10 +3029,8 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata, head_need += local->tx_headroom; head_need =max_t (int,0 , head_need);if (ieee80211_skb_resize (sdata, skb, head_need,ENCRYPT_DATA )) { -ieee80211_free_txskb (&local->hw, skb); - skb =NULL ; ret = -ENOMEM ; - goto free; + goto free_txskb; } }
@@ -3046,16 +3057,6 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,skb_reset_mac_header (skb); - info =IEEE80211_SKB_CB (skb); -memset (info,0 ,sizeof (*info)); - - info->flags = info_flags; -if (info_id) { - info->status_data = info_id; - info->status_data_idr =1 ; - } - info->band = band; -if (likely (!cookie)) { ctrl_flags |=u32_encode_bits (link_id,IEEE80211_TX_CTRL_MLO_LINK );
@@ -3079,16 +3080,17 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata, pre_conf_link_id, link_id);#endif ret = -EINVAL ; - goto free; + goto free_txskb; } } info->control.flags = ctrl_flags;return skb; + free_txskb: +ieee80211_free_txskb (&local->hw, skb); +return ERR_PTR (ret); free: -if (info_id) -ieee80211_remove_ack_skb (local, info_id);kfree_skb (skb);return ERR_PTR (ret); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 92/438 mm: memblock: show all region flags in debugfs
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Meijing Zhao <[email protected]>
[ Upstream commit e2d5b01f878d76bd1142e512a0b979a1d3cd0abf ]
Commit 493f349e38d0 ("memblock: Add flags and nid info in memblock debugfs") made memblock_debug_show() stop after finding the first set flag. A memblock region can carry multiple flags, so the remaining flags are hidden from debugfs.
Walk all bits in the region flags and print every set flag separated by "|". Keep walking beyond flagname[] so that a set flag without a known name is reported as UNKNOWN rather than silently ignored.
--- mm/memblock.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-)
mm/memblock.c +11 -7
@@ -2823,14 +2823,18 @@ static int memblock_debug_show(struct seq_file *m, void *private)else seq_printf (m,"%4c " ,'x' );if (reg->flags) { -for (j =0 ; j < count; j++) { -if (reg->flags & (1U << j)) { -seq_printf (m,"%s\n" , flagname[j]); -break ; - } +unsigned int flags = reg->flags; +bool first = true; + +for (j =0 ; flags; j++, flags >>=1 ) { +if (!(flags &1 )) +continue ; +if (!first) +seq_putc (m,'|' ); +seq_puts (m, j < count ? flagname[j] :"UNKNOWN" ); + first = false; } -if (j == count) -seq_printf (m,"%s\n" ,"UNKNOWN" ); +seq_putc (m,'\n' ); }else {seq_printf (m,"%s\n" ,"NONE" ); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 93/438 scsi: pm80xx: Fix the use_msix, use_tasklet and read_wwn parameter descriptions
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 264bf9655c3d067d775a46f05eb8c871c488a864 ]
The MODULE_PARM_DESC() lines of use_msix, use_tasklet and read_wwn all name a parameter zoned, which does not exist, and the use_tasklet one repeats the use_msix text. modinfo shows three "zoned" entries and no description for the real parameters.
Name the right parameters and describe use_tasklet.
--- drivers/scsi/pm8001/pm8001_init.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/scsi/pm8001/pm8001_init.c +3 -3
@@ -58,15 +58,15 @@ MODULE_PARM_DESC(link_rate, "Enable link rate.\n"bool pm8001_use_msix = true;module_param_named (use_msix, pm8001_use_msix, bool,0444 ); -MODULE_PARM_DESC (zoned,"Use MSIX interrupts. Default: true" ); +MODULE_PARM_DESC (use_msix,"Use MSIX interrupts. Default: true" );static bool pm8001_use_tasklet = true;module_param_named (use_tasklet, pm8001_use_tasklet, bool,0444 ); -MODULE_PARM_DESC (zoned,"Use MSIX interrupts. Default: true" ); +MODULE_PARM_DESC (use_tasklet,"Use tasklets for interrupt handling. Default: true" );static bool pm8001_read_wwn = true;module_param_named (read_wwn, pm8001_read_wwn, bool,0444 ); -MODULE_PARM_DESC (zoned,"Get WWN from the controller. Default: true" ); +MODULE_PARM_DESC (read_wwn,"Get WWN from the controller. Default: true" );uint pcs_event_log_severity =0x03 ;module_param (pcs_event_log_severity, int,0644 );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 94/438 scsi: qla2xxx: Fix the ql2xfc2target parameter description
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 779f202a92ef10a426efc07d0f4267918cb07ca3 ]
The module parameter is ql2xfc2target, but its MODULE_PARM_DESC() names qla2xfc2target, so modinfo describes a parameter that does not exist and shows no description for the real one.
Use the parameter name in the description.
--- drivers/scsi/qla2xxx/qla_os.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/qla2xxx/qla_os.c +1 -1
@@ -352,7 +352,7 @@ MODULE_PARM_DESC(ql2xnvme_queues,int ql2xfc2target =1 ;module_param (ql2xfc2target, int,0444 ); -MODULE_PARM_DESC (qla2xfc2target, +MODULE_PARM_DESC (ql2xfc2target,"Enables FC2 Target support. " "0 - FC2 Target support is disabled. " "1 - FC2 Target support is enabled (default)." );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 95/438 dmaengine: xilinx_dma: Fix hardware buffer descriptor reuse order
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Bereza <[email protected]>
[ Upstream commit cee9c863ee68cb27d66745eb03f60e357f4f8ad2 ]
xilinx_dma_alloc_chan_resources() builds a static ring of hardware buffer descriptors once and the driver uses this ring throughout the lifetime of a channel. This requires the allocation order of hardware buffer descriptors from chan->free_seg_list to stay in sync with the hardware buffer descriptor ring built at channel allocation time by returning oldest descriptors to chan->free_seg_list first.
When chan->pending_list is not empty e.g. during xilinx_dma_terminate_all() the chan->free_seg_list and the order of the static hardware buffer descriptor ring get out of sync. Descriptors age in this order: pending -> active -> done. So freeing pending_list first returns the newest buffer descriptors to the chan->free_seg_list first and thus breaks the order required by the static hardware buffer descriptor ring. Then when the channel is reused, after a wrap around of the free_seg_list the DMA will find a hardware buffer descriptor with a length field that is still zeroed and stop with something like this:
xilinx-vdma 86000000.dma: Channel 000000003a21d7b8 has errors 10, cdr 6de4c000 tdr 6de4c000
After this no more descriptors are completed and a consumer potentially blocks and waits forever. The only way to get out of this error state is to rebuild the static hardware buffer descriptor ring and the free_seg_list by releasing and re-acquiring the channel.
Fix the order in which hardware buffer descriptors are returned to free_seg_list to ensure the mentioned requirement holds.
--- drivers/dma/xilinx/xilinx_dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/dma/xilinx/xilinx_dma.c +1 -1
@@ -920,9 +920,9 @@ static void xilinx_dma_free_descriptors(struct xilinx_dma_chan *chan)spin_lock_irqsave (&chan->lock, flags); -xilinx_dma_free_desc_list (chan, &chan->pending_list);xilinx_dma_free_desc_list (chan, &chan->done_list);xilinx_dma_free_desc_list (chan, &chan->active_list); +xilinx_dma_free_desc_list (chan, &chan->pending_list);spin_unlock_irqrestore (&chan->lock, flags); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 96/438 dmaengine: pxa: fix double counting of the hw descriptors
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sascha Hauer <[email protected]>
[ Upstream commit f6504be006aa4bb4bd26285f410a885c17920d65 ]
pxad_alloc_desc() was converted from
kzalloc(struct_size(sw_desc, hw_desc, nb_hw_desc), GFP_NOWAIT)
to kzalloc_flex(), which sets the __counted_by() counter sw_desc->nb_desc itself - but only where the compiler has __builtin_counted_by_ref(), so from gcc 15.1 or clang 22.1 on. The loop below it still increments nb_desc, which makes it come out doubled there and correct elsewhere.
nb_desc is what pxad_free_desc() iterates over and what set_updater_desc() indexes from, so set it explicitly and drop the increment. The error path has to lower it to the number of descriptors allocated so far, otherwise pxad_free_desc() would free entries that were never allocated.
--- drivers/dma/pxa_dma.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/dma/pxa_dma.c +2 -1
@@ -744,6 +744,7 @@ pxad_alloc_desc(struct pxad_chan *chan, unsigned int nb_hw_desc) sw_desc =kzalloc_flex (*sw_desc, hw_desc, nb_hw_desc,GFP_NOWAIT );if (!sw_desc)return NULL ; + sw_desc->nb_desc = nb_hw_desc; sw_desc->desc_pool = chan->desc_pool;for (i =0 ; i < nb_hw_desc; i++) {
@@ -752,10 +753,10 @@ pxad_alloc_desc(struct pxad_chan *chan, unsigned int nb_hw_desc)dev_err (&chan->vc.chan.dev->device,"%s(): Couldn't allocate the %dth hw_desc from dma_pool %p\n" , __func__, i, sw_desc->desc_pool); + sw_desc->nb_desc = i; goto err; } - sw_desc->nb_desc++; sw_desc->hw_desc[i] = desc;if (i ==0 )
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 97/438 dmaengine: xilinx_dma: Fix hardware buffer descriptor chain after cyclic DMA
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Bereza <[email protected]>
[ Upstream commit 7ed1e3070c9b4bbd67d5519e14711038dd53ab13 ]
Using the DMA in cyclic mode modifies the hardware buffer descriptor chain in xilinx_dma_prep_dma_cyclic so that the last descriptor used by the cyclic transfer points back to the first descriptor, but it never restores the original descriptor ring. This breaks using non-cyclic mode after cyclic mode with an error like:
xilinx-vdma 86000000.dma: Channel 00000000354d5c8d has errors 100, cdr 6de40000 tdr 6de40400
The only way to get out of this error state is to rebuild the hardware buffer descriptor ring by releasing and re-acquiring the channel.
Fix using non-cyclic mode after cyclic mode by always restoring the original buffer descriptor ring in the same manner as it is set up by xilinx_dma_alloc_chan_resources().
--- drivers/dma/xilinx/xilinx_dma.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-)
drivers/dma/xilinx/xilinx_dma.c +17 -7
@@ -756,15 +756,25 @@ xilinx_aximcdma_alloc_tx_segment(struct xilinx_dma_chan *chan)return segment; } -static void xilinx_dma_clean_hw_desc (struct xilinx_axidma_desc_hw *hw) +static void xilinx_dma_clean_hw_desc (struct xilinx_dma_chan *chan, +struct xilinx_axidma_tx_segment *segment) { -u32 next_desc = hw->next_desc; -u32 next_desc_msb = hw->next_desc_msb; +dma_addr_t next; +u32 i; -memset (hw,0 ,sizeof (struct xilinx_axidma_desc_hw )); +/* +* Restore the buffer descriptor's next descriptor pointer to the value +* set up in xilinx_dma_alloc_chan_resources(). Otherwise using the DMA +* in cyclic mode leaves the next descriptor pointer altered and +* prevents subsequent non-cyclic transfers. +*/ + i = segment - chan->seg_v; + next = chan->seg_p + +sizeof (*chan->seg_v) * ((i +1 ) %XILINX_DMA_NUM_DESCS ); - hw->next_desc = next_desc; - hw->next_desc_msb = next_desc_msb; +memset (&segment->hw,0 ,sizeof (segment->hw)); + segment->hw.next_desc =lower_32_bits (next); + segment->hw.next_desc_msb =upper_32_bits (next); }static void xilinx_mcdma_clean_hw_desc (struct xilinx_aximcdma_desc_hw *hw)
@@ -786,7 +796,7 @@ static void xilinx_mcdma_clean_hw_desc(struct xilinx_aximcdma_desc_hw *hw)static void xilinx_dma_free_tx_segment (struct xilinx_dma_chan *chan,struct xilinx_axidma_tx_segment *segment) { -xilinx_dma_clean_hw_desc (&segment->hw); +xilinx_dma_clean_hw_desc (chan, segment);list_add_tail (&segment->node, &chan->free_seg_list); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 98/438 RDMA/efa: Keep admin queues alive while IRQ is registered
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit e08aca85c02ff290f785f07acae758f0daf5f49e ]
The management IRQ handler accesses both the admin completion queue and the async event queue. The driver registered the IRQ before constructing these queues and destroyed them before freeing the IRQ, so the handler's lifetime was not contained by the resources it accesses.
Initialize the queues with interrupts masked, request the IRQ, and then switch to interrupt mode. On removal, reset the device and free the IRQ before destroying the queues. Also reset the device before destroying the queues if IRQ registration fails, because the device already has their DMA addresses.
--- drivers/infiniband/hw/efa/efa_com.c | 4 +--- drivers/infiniband/hw/efa/efa_main.c | 15 +++++++++------ 2 files changed, 10 insertions(+), 9 deletions(-)
drivers/infiniband/hw/efa/efa_com.c +1 -3
@@ -786,7 +786,7 @@ int efa_com_admin_init(struct efa_com_dev *edev, aq->dmadev = edev->dmadev; aq->efa_dev = edev->efa_dev; -set_bit (EFA_AQ_STATE_POLLING_BIT , &aq->state); +efa_com_set_admin_polling_mode (edev, true);sema_init (&aq->avail_cmds, aq->depth);
@@ -804,8 +804,6 @@ int efa_com_admin_init(struct efa_com_dev *edev,if (err) goto err_destroy_sq; -efa_com_set_admin_polling_mode (edev, false); - err =efa_com_admin_init_aenq (edev, aenq_handlers);if (err) goto err_destroy_cq;
drivers/infiniband/hw/efa/efa_main.c +9 -6
@@ -611,18 +611,21 @@ static struct efa_dev *efa_probe_device(struct pci_dev *pdev) edev->aq.msix_vector_idx = dev->admin_msix_vector_idx; edev->aenq.msix_vector_idx = dev->admin_msix_vector_idx; - err =efa_set_mgmnt_irq (dev); + err =efa_com_admin_init (edev, &aenq_handlers);if (err) goto err_disable_msix; - err =efa_com_admin_init (edev, &aenq_handlers); + err =efa_set_mgmnt_irq (dev);if (err) - goto err_free_mgmnt_irq; + goto err_destroy_admin; + +efa_com_set_admin_polling_mode (edev, false);return dev; -err_free_mgmnt_irq: -efa_free_irq (dev, &dev->admin_irq); +err_destroy_admin: +efa_com_dev_reset (edev,EFA_REGS_RESET_INIT_ERR ); +efa_com_admin_destroy (edev); err_disable_msix:efa_disable_msix (dev); err_reg_read_destroy:
@@ -646,8 +649,8 @@ static void efa_remove_device(struct pci_dev *pdev, edev = &dev->edev;efa_com_dev_reset (edev, reset_reason); -efa_com_admin_destroy (edev);efa_free_irq (dev, &dev->admin_irq); +efa_com_admin_destroy (edev);efa_disable_msix (dev);efa_com_mmio_reg_read_destroy (edev);devm_iounmap (&pdev->dev, edev->reg_bar);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 99/438 RDMA/efa: Keep EQ resources alive while IRQ is registered
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit e22a3627b7151754f07f90ea3d1ab6e85f5d93f4 ]
The completion IRQ handler accesses the EQ state and DMA buffer. Its IRQ was registered before that state was initialized, while teardown released the buffer before free_irq() synchronized the handler.
Initialize the EQ without arming it, register the IRQ, and then arm it. Reverse the resource order during teardown by freeing the IRQ before destroying the EQ.
--- drivers/infiniband/hw/efa/efa_com.c | 3 +-- drivers/infiniband/hw/efa/efa_com.h | 1 + drivers/infiniband/hw/efa/efa_main.c | 18 ++++++++++-------- 3 files changed, 12 insertions(+), 10 deletions(-)
drivers/infiniband/hw/efa/efa_com.c +1 -2
@@ -1192,7 +1192,7 @@ static void efa_com_destroy_eq(struct efa_com_dev *edev, err); } -static void efa_com_arm_eq (struct efa_com_dev *edev,struct efa_com_eq *eeq) +void efa_com_arm_eq (struct efa_com_dev *edev,struct efa_com_eq *eeq) {u32 val =0 ;
@@ -1281,7 +1281,6 @@ int efa_com_eq_init(struct efa_com_dev *edev, struct efa_com_eq *eeq, eeq->phase =1 ; eeq->depth = params.depth; eeq->cb = cb; -efa_com_arm_eq (edev, eeq);return 0 ;
drivers/infiniband/hw/efa/efa_com.h +1 -0
@@ -159,6 +159,7 @@ int efa_com_admin_init(struct efa_com_dev *edev,void efa_com_admin_destroy (struct efa_com_dev *edev);int efa_com_eq_init (struct efa_com_dev *edev,struct efa_com_eq *eeq,efa_eqe_handler cb,u16 depth,u8 msix_vec); +void efa_com_arm_eq (struct efa_com_dev *edev,struct efa_com_eq *eeq);void efa_com_eq_destroy (struct efa_com_dev *edev,struct efa_com_eq *eeq);int efa_com_dev_reset (struct efa_com_dev *edev,enum efa_regs_reset_reason_types reset_reason);
drivers/infiniband/hw/efa/efa_main.c +10 -8
@@ -300,28 +300,30 @@ static void efa_set_host_info(struct efa_dev *dev)static void efa_destroy_eq (struct efa_dev *dev,struct efa_eq *eq) { -efa_com_eq_destroy (&dev->edev, &eq->eeq);efa_free_irq (dev, &eq->irq); +efa_com_eq_destroy (&dev->edev, &eq->eeq); }static int efa_create_eq (struct efa_dev *dev,struct efa_eq *eq,u32 msix_vec) {int err; -efa_setup_comp_irq (dev, eq, msix_vec); - err =efa_request_irq (dev, &eq->irq); + err =efa_com_eq_init (&dev->edev, &eq->eeq, efa_process_eqe, + dev->dev_attr.max_eq_depth, msix_vec);if (err)return err; - err =efa_com_eq_init (&dev->edev, &eq->eeq, efa_process_eqe, - dev->dev_attr.max_eq_depth, msix_vec); +efa_setup_comp_irq (dev, eq, msix_vec); + err =efa_request_irq (dev, &eq->irq);if (err) - goto err_free_comp_irq; + goto err_destroy_eq; + +efa_com_arm_eq (&dev->edev, &eq->eeq);return 0 ; -err_free_comp_irq: -efa_free_irq (dev, &eq->irq); +err_destroy_eq: +efa_com_eq_destroy (&dev->edev, &eq->eeq);return err; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 100/438 RDMA/siw: Bound fragmented header copies by the remaining length
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 9ff797e516dbc1ecb73701ec4c24055712d44411 ]
siw_get_hdr() can receive an extended DDP/RDMAP header across more than one TCP callback. The first callback may receive most of the header, while the next one still limits the copy to hdrlen - MIN_DDP_HDR instead of the number of missing bytes. This makes the destination move past the end of the header and overwrite the receive state, including fpdu_part_rcvd. A later callback can then use a negative fpdu_part_rcvd value as a copy offset, which creates an OOB write.
Use the number of header bytes already received when calculating the next copy length.
--- drivers/infiniband/sw/siw/siw_qp_rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/sw/siw/siw_qp_rx.c +1 -1
@@ -1079,7 +1079,7 @@ static int siw_get_hdr(struct siw_rx_stream *srx)if (iwarp_pktinfo[opcode].hdr_len >sizeof (struct iwarp_ctrl_tagged )) {int hdrlen = iwarp_pktinfo[opcode].hdr_len; - bytes =min_t (int, hdrlen -MIN_DDP_HDR , srx->skb_new); + bytes =min_t (int, hdrlen - srx->fpdu_part_rcvd, srx->skb_new);skb_copy_bits (skb, srx->skb_offset, (char *)c_hdr + srx->fpdu_part_rcvd, bytes);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 101/438 x86/div64: Fix addition of large constants in mul_u64_add_u64_div_u64()
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Laight <[email protected]>
[ Upstream commit f65d38155aef069c897a64643a03db237dd1e0c8 ]
Adding constants over 2^31 fails to compile because the ADD instruction only supports 32bit signed immediates.
Replace the "irm" constraint with "erm" so that the compiler loads large constants into a register.
Found by a patch to drivers/iio/frequency/ad9910.c
[ bp: Massage commit message. ]
--- arch/x86/include/asm/div64.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/include/asm/div64.h +1 -1
@@ -111,7 +111,7 @@ static inline u64 mul_u64_add_u64_div_u64(u64 rax, u64 mul, u64 add, u64 div)if (!statically_true (!add)) asm ("addq %[add], %[lo]; adcq $0, %[hi]" : - [lo]"+r" (rax), [hi]"+r" (rdx) : [add]"irm" (add)); + [lo]"+r" (rax), [hi]"+r" (rdx) : [add]"erm" (add)); asm ("divq %[div]" :"+a" (rax),"+d" (rdx) : [div]"rm" (div));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 102/438 drm/msm: Fix the separate_gpu_kms parameter description
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 adf5967331318bcb436fc80069915231ec039352 ]
The module parameter is separate_gpu_kms, but its MODULE_PARM_DESC() names separate_gpu_drm, so modinfo describes a parameter that does not exist and shows no description for the real one.
Use the parameter name in the description.
Patchwork: https://patchwork.freedesktop.org/patch/751407/
Message-ID: <[email protected]>
--- drivers/gpu/drm/msm/msm_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/msm/msm_drv.c +1 -1
@@ -55,7 +55,7 @@ MODULE_PARM_DESC(modeset, "Use kernel modesetting [KMS] (1=on (default), 0=disabmodule_param (modeset, bool,0600 );static bool separate_gpu_kms; -MODULE_PARM_DESC (separate_gpu_drm,"Use separate DRM device for the GPU (0=single DRM device for both GPU and display (default), 1=two DRM devices)" ); +MODULE_PARM_DESC (separate_gpu_kms,"Use separate DRM device for the GPU (0=single DRM device for both GPU and display (default), 1=two DRM devices)" );module_param (separate_gpu_kms, bool,0400 );DECLARE_FAULT_ATTR (fail_gem_alloc);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 103/438 drm/msm/adreno: Fix the skip_gpu parameter description
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 8061ee61b9426fe38350fa9eead2d9c50b03deb6 ]
The module parameter is skip_gpu, but its MODULE_PARM_DESC() names no_gpu, so modinfo describes a parameter that does not exist and shows no description for the real one.
Use the parameter name in the description.
Patchwork: https://patchwork.freedesktop.org/patch/751406/
Message-ID: <[email protected]>
--- drivers/gpu/drm/msm/adreno/adreno_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/msm/adreno/adreno_device.c +1 -1
@@ -25,7 +25,7 @@ MODULE_PARM_DESC(disable_acd, "Forcefully disable GPU ACD");module_param_unsafe (disable_acd, bool,0400 );static bool skip_gpu; -MODULE_PARM_DESC (no_gpu,"Disable GPU driver register (0=enable GPU driver register (default), 1=skip GPU driver register" ); +MODULE_PARM_DESC (skip_gpu,"Disable GPU driver register (0=enable GPU driver register (default), 1=skip GPU driver register" );module_param (skip_gpu, bool,0400 );extern const struct adreno_gpulist a2xx_gpulist;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 104/438 dma-buf: Make DMABUF_DEBUG default to y on DEBUG_KERNEL kernels
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 143755bdabaa96776c24f878014608e9cb44f930 ]
Commit 646013f513f3 ("dma-buf: enable DMABUF_DEBUG by default on DEBUG kernels") changed the default of DMABUF_DEBUG to "y if DEBUG", but no Kconfig symbol DEBUG exists, so the option has had no default since.
Use DEBUG_KERNEL, the Kconfig symbol for a debug kernel.
--- drivers/dma-buf/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/dma-buf/Kconfig +1 -1
@@ -43,7 +43,7 @@ config UDMABUF config DMABUF_DEBUG bool "DMA-BUF debug checks" depends on DMA_SHARED_BUFFER - default y if DEBUG + default y if DEBUG_KERNEL help This option enables additional checks for DMA-BUF importers and exporters. Specifically it validates that importers do not peek at the
Signature · 1 line
2.53.0
Re: [PATCH 7.2 104/438] dma-buf: Make DMABUF_DEBUG default to y on DEBUG_KERNEL kernels
I object to including this patch in 7.2.8. I authored the upstream patch, but did not tag it for stable. It corrects a Kconfig default and thereby enables the DMA-BUF importer checks in configurations that take the DEBUG_KERNEL default.
Jianfeng has now reported a drm/msm hardware video decode regression from the upstream change:
https://lore.kernel.org/r/[email protected]/
The impact of enabling this by default for stable needs further discussion.
Thanks,
Karl
Sasha Levin
maintainerRe: [PATCH 7.2 104/438] dma-buf: Make DMABUF_DEBUG default to y on DEBUG_KERNEL kernels
Quoted 4 lines · Karl Mehltretter
I object to including this patch in 7.2.8. I authored the upstream patch, but did not tag it for stable. It corrects a
Kconfigdefault and thereby enables the DMA-BUF importer checks in configurations that take theDEBUG_KERNELdefault.
Dropped from the 7.2 queue, so it won't be in 7.2.8.
Signature · 2 lines
Thanks, Sasha
Re: [PATCH 7.2 104/438] dma-buf: Make DMABUF_DEBUG default to y on DEBUG_KERNEL kernels
Quoted 8 lines · Sasha Levin
Quoted 4 lines · Karl Mehltretter
I object to including this patch in 7.2.8. I authored the upstream patch, but did not tag it for stable. It corrects a
Kconfigdefault and thereby enables the DMA-BUF importer checks in configurations that take theDEBUG_KERNELdefault.Dropped from the 7.2 queue, so it won't be in 7.2.8.
Thanks for catching this Karl and I agree completely.
That config option is for phasing out a broken approach in some DRM drivers, but not meant to be added to any stable kernel.
Regards,
Christian.
Greg Kroah-Hartman
maintainerPATCH 105/438 netfilter: nft_nat: fully initialise new_addr in netmap setup
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Theodor Arsenij Larionov Trichkine <[email protected]>
[ Upstream commit d313499df66159b4b7971d760d16729598ab7e5a ]
nft_nat_setup_netmap() builds the mapped address in an on-stack union nf_inet_addr. For an IPv4 mapping it writes only the 4-byte .ip member and the loop runs a single 32-bit iteration, but it then copies the whole 16-byte union into range->min_addr and range->max_addr, so the upper 12 bytes reach nf_nat_setup_info() uninitialised.
KMSAN reports an uninit-value in nf_nat_setup_info() reached from nft_nat_eval(). The IPv6 path fills all 16 bytes and is not affected.
Zero-initialise new_addr.
--- net/netfilter/nft_nat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/netfilter/nft_nat.c +1 -1
@@ -64,8 +64,8 @@ static void nft_nat_setup_netmap(struct nf_nat_range2 *range,const struct nft_pktinfo *pkt, const struct nft_nat *priv) { + union nf_inet_addr new_addr = {};struct sk_buff *skb = pkt->skb; -union nf_inet_addr new_addr;__be32 netmask;int i, len =0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 106/438 netfilter: nf_tables: fix device name and prefix match in hook lookup
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fernando Fernandez Mancera <[email protected]>
[ Upstream commit 444e4c88c9c62a3d823069006563513fe7d5aa66 ]
Currently, a netdev chain or flowtable hooked to a device prefix can be unintentionally deleted by a control-plane request targeting an exact device name or even a shorter one due to the usage of min() to calculate the length to match.
Fix this by making sure an exact device match never matches a prefix and that both the target and the candidate have the same length during delete operation. The add and update paths retain the existing overlap matching to prevent a single device from matching multiple hooks.
--- net/netfilter/nf_tables_api.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-)
net/netfilter/nf_tables_api.c +13 -9
@@ -2435,11 +2435,14 @@ static struct nft_hook *nft_netdev_hook_alloc(struct net *net, }static struct nft_hook *nft_hook_list_find (struct list_head *hook_list, -const struct nft_hook *this) +const struct nft_hook *this, +bool strict) {struct nft_hook *hook;list_for_each_entry (hook, hook_list, list) { +if (strict && hook->ifnamelen != this->ifnamelen) +continue ;if (!strncmp (hook->ifname, this->ifname,min (hook->ifnamelen, this->ifnamelen))) {if (hook->flags &NFT_HOOK_REMOVE )
@@ -2481,7 +2484,7 @@ static int nf_tables_parse_netdev_hooks(struct net *net, err =PTR_ERR (hook); goto err_hook; } -if (nft_hook_list_find (hook_list, hook)) { +if (nft_hook_list_find (hook_list, hook, false)) {NL_SET_BAD_ATTR (extack, tmp);nft_netdev_hook_free (hook); err = -EEXIST ;
@@ -2938,7 +2941,7 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy, ops->hook = basechain->ops.hook; } -if (nft_hook_list_find (&basechain->hook_list, h)) { +if (nft_hook_list_find (&basechain->hook_list, h, false)) {list_del (&h->list);nft_netdev_hook_free (h);continue ;
@@ -2951,7 +2954,8 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy, !nft_trans_chain_update(trans))continue ; -if (nft_hook_list_find (&nft_trans_chain_hooks (trans), h)) { +if (nft_hook_list_find (&nft_trans_chain_hooks (trans), + h, false)) {nft_chain_release_hook (&hook);return -EEXIST ; }
@@ -3252,7 +3256,7 @@ static int nft_delchain_hook(struct nft_ctx *ctx,return err;list_for_each_entry (this, &chain_hook.list, list) { - hook =nft_hook_list_find (&basechain->hook_list, this); + hook =nft_hook_list_find (&basechain->hook_list, this, true);if (!hook) { err = -ENOENT ; goto err_chain_del_hook;
@@ -9031,7 +9035,7 @@ static int nft_register_flowtable_net_hooks(struct net *net,if (!nft_is_active_next (net, ft))continue ; -if (nft_hook_list_find (&ft->hook_list, hook)) { +if (nft_hook_list_find (&ft->hook_list, hook, false)) { err = -EEXIST ; goto err_unregister_net_hooks; }
@@ -9108,7 +9112,7 @@ static int nft_flowtable_update(struct nft_ctx *ctx, const struct nlmsghdr *nlh,return err;list_for_each_entry_safe (hook, next, &flowtable_hook.list, list) { -if (nft_hook_list_find (&flowtable->hook_list, hook)) { +if (nft_hook_list_find (&flowtable->hook_list, hook, false)) {list_del (&hook->list);nft_netdev_hook_free (hook);continue ;
@@ -9121,7 +9125,7 @@ static int nft_flowtable_update(struct nft_ctx *ctx, const struct nlmsghdr *nlh, !nft_trans_flowtable_update(trans))continue ; -if (nft_hook_list_find (&nft_trans_flowtable_hooks (trans), hook)) { +if (nft_hook_list_find (&nft_trans_flowtable_hooks (trans), hook, false)) { err = -EEXIST ; goto err_flowtable_update_hook; }
@@ -9341,7 +9345,7 @@ static int nft_delflowtable_hook(struct nft_ctx *ctx,return err;list_for_each_entry (this, &flowtable_hook.list, list) { - hook =nft_hook_list_find (&flowtable->hook_list, this); + hook =nft_hook_list_find (&flowtable->hook_list, this, true);if (!hook) { err = -ENOENT ; goto err_flowtable_del_hook;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 107/438 netfilter: nf_nat: unregister and release hooks on error
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit cbdd39ce42530a193c56beb206a3356cb6d01016 ]
If nf_hook_entries_insert_raw() fails, the NAT hooks get never released, resulting in a memleak.
Postpone setting nat_proto_net->nat_hook_ops when the hooks are registered to simplify the error path to decide whether the nat hooks need unwinding.
--- net/netfilter/nf_nat_core.c | 46 ++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 16 deletions(-)
net/netfilter/nf_nat_core.c +30 -16
@@ -1230,31 +1230,45 @@ int nf_nat_register_fn(struct net *net, u8 pf, const struct nf_hook_ops *ops, } ret =nf_register_net_hooks (net, nat_ops, ops_count); -if (ret <0 ) { -mutex_unlock (&nf_nat_proto_mutex); -for (i =0 ; i < ops_count; i++) { - priv = nat_ops[i].priv; -kfree_rcu (priv, rcu_head); - } -kfree_rcu (nat_ops, rcu); -return ret; - } - - nat_proto_net->nat_hook_ops = nat_ops; +if (ret <0 ) + goto err_free_hooks; + }else { + nat_ops = nat_proto_net->nat_hook_ops; } - nat_ops = nat_proto_net->nat_hook_ops; priv = nat_ops[hooknum].priv;if (WARN_ON_ONCE (!priv)) { -mutex_unlock (&nf_nat_proto_mutex); -return -EOPNOTSUPP ; + ret = -EOPNOTSUPP ; + goto err_unregister_hooks; } ret =nf_hook_entries_insert_raw (&priv->entries, ops); -if (ret ==0 ) - nat_proto_net->users++; +if (ret) + goto err_unregister_hooks; + +if (!nat_proto_net->nat_hook_ops) + nat_proto_net->nat_hook_ops = nat_ops; + + nat_proto_net->users++;mutex_unlock (&nf_nat_proto_mutex); + +return 0 ; + +err_unregister_hooks: +if (nat_proto_net->nat_hook_ops) { +mutex_unlock (&nf_nat_proto_mutex); +return ret; + } +nf_unregister_net_hooks (net, nat_ops, ops_count); +err_free_hooks: +mutex_unlock (&nf_nat_proto_mutex); +for (i =0 ; i < ops_count; i++) { + priv = nat_ops[i].priv; +kfree_rcu (priv, rcu_head); + } +kfree_rcu (nat_ops, rcu); +return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 108/438 netfilter: flowtable: hold reference on ct until flow is released
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit e75a9fa1d44bcbd66ea02e8781bcca6ea4076e0d ]
nf_ct_put() releases the ct->ext area inmediately, the rcu typesafe semantics also allow to refer to the wrong conntrack from the flowtable datapath. Hold reference on ct until flow is released after rcu grace period.
Add rcu_barrier() on module exit path, to ensure pending flow entries are release before module goes away.
--- net/netfilter/nf_flow_table_core.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
net/netfilter/nf_flow_table_core.c +10 -2
@@ -258,6 +258,14 @@ static void flow_offload_route_release(struct flow_offload *flow)nft_flow_dst_release (flow,FLOW_OFFLOAD_DIR_REPLY ); } +static void flow_offload_free_rcu (struct rcu_head *rcu_head) +{ + struct flow_offload *flow = container_of(rcu_head, struct flow_offload, rcu_head); + +nf_ct_put (flow->ct); +kfree (flow); +} +void flow_offload_free (struct flow_offload *flow) {switch (flow->type) {
@@ -267,8 +275,7 @@ void flow_offload_free(struct flow_offload *flow)default :break ; } -nf_ct_put (flow->ct); -kfree_rcu (flow, rcu_head); +call_rcu (&flow->rcu_head, flow_offload_free_rcu); }EXPORT_SYMBOL_GPL (flow_offload_free);
@@ -852,6 +859,7 @@ static int __init nf_flow_table_module_init(void) static void __exit nf_flow_table_module_exit(void) { +rcu_barrier ();nf_flow_table_offload_exit ();unregister_pernet_subsys (&nf_flow_table_net_ops);kmem_cache_destroy (flow_offload_cachep);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 109/438 perf/arm-cmn: Fix wp_dev_sel2 setting for multi-DTM configurations
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shouping Wang <[email protected]>
[ Upstream commit 49daa3d668b69a5454b5aba0078848a479f79f1c ]
When MXP_MULTIPLE_DTM_EN is TRUE, each DTM will monitor at most two device ports. In this case, {wp_dev_sel2, wp_dev_sel} will only use values 2'b00 and 2'b01 per DTM.
Previously the setting allowed values beyond the supported range per DTM, which could cause each DTM to select invalid ports when MXP_MULTIPLE_DTM_EN is TRUE.
Fix this by only setting CMN_DTM_WPn_CONFIG_WP_DEV_SEL2 when !multi_dtm.
--- drivers/perf/arm-cmn.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
drivers/perf/arm-cmn.c +7 -3
@@ -1393,13 +1393,14 @@ static void arm_cmn_claim_wp_idx(struct arm_cmn_dtm *dtm,static u32 arm_cmn_wp_config (struct perf_event *event,int wp_idx) { +struct arm_cmn *cmn =to_cmn (event->pmu);u32 config;u32 dev =CMN_EVENT_WP_DEV_SEL (event);u32 chn =CMN_EVENT_WP_CHN_SEL (event);u32 grp =CMN_EVENT_WP_GRP (event);u32 exc =CMN_EVENT_WP_EXCLUSIVE (event);u32 combine =CMN_EVENT_WP_COMBINE (event); -bool is_cmn600 =to_cmn (event->pmu)->part ==PART_CMN600 ; +bool is_cmn600 = cmn->part ==PART_CMN600 ;/* CMN-600 supports only primary and secondary matching groups */ if (is_cmn600)
@@ -1407,8 +1408,11 @@ static u32 arm_cmn_wp_config(struct perf_event *event, int wp_idx) config =FIELD_PREP (CMN_DTM_WPn_CONFIG_WP_DEV_SEL, dev) |FIELD_PREP (CMN_DTM_WPn_CONFIG_WP_CHN_SEL, chn) | -FIELD_PREP (CMN_DTM_WPn_CONFIG_WP_GRP, grp) | -FIELD_PREP (CMN_DTM_WPn_CONFIG_WP_DEV_SEL2, dev >>1 ); +FIELD_PREP (CMN_DTM_WPn_CONFIG_WP_GRP, grp); + +if (!cmn->multi_dtm) + config |=FIELD_PREP (CMN_DTM_WPn_CONFIG_WP_DEV_SEL2, dev >>1 ); +if (exc) config |= is_cmn600 ? CMN600_WPn_CONFIG_WP_EXCLUSIVE : CMN_DTM_WPn_CONFIG_WP_EXCLUSIVE;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 110/438 arm64: hibernate: clone only the linear map that exists at runtime
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Breno Leitao <[email protected]>
[ Upstream commit e4a6f57d22e079e23fafac51057fad534160b269 ]
This is similar to commit 1537e55728ec2 ("arm64: trans_pgd: clone only the linear map that exists at runtime"), but in a different place.
swsusp_arch_resume() clones the kernel linear map with trans_pgd_create_copy(..., PAGE_OFFSET, PAGE_END). PAGE_OFFSET comes from the compile-time VA_BITS, so a CONFIG_ARM64_VA_BITS_52 kernel booting on hardware without LPA2 -- vabits_actual is 48 and the fifth level is folded -- hands the walk a 3.9PB window while its linear map only spans the top 128TB.
On a VA_BITS_52 4k kernel with CONFIG_KASAN_GENERIC in a 4GB VM, I see:
swapper/0: page allocation failure: order:0, mode:0x920(GFP_ATOMIC|__GFP_ZERO)
hibernate_page_alloc+0x10/0x1c swsusp_arch_resume+0x70/0x320 hibernation_restore+0xa4/0x138 software_resume+0x15c/0x270 PM: hibernation: Failed to load image, recovering. PM: hibernation: resume failed (-12)
Fix it by copying the linear map that is the actual one, not the compiled one.
--- arch/arm64/kernel/hibernate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm64/kernel/hibernate.c +2 -2
@@ -423,8 +423,8 @@ int __nocfi swsusp_arch_resume(void)* Create a second copy of just the linear map, and use this when * restoring. */ - rc =trans_pgd_create_copy (&trans_info, &tmp_pg_dir,PAGE_OFFSET , -PAGE_END ); + rc =trans_pgd_create_copy (&trans_info, &tmp_pg_dir, +_PAGE_OFFSET (vabits_actual),PAGE_END );if (rc)return rc;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 111/438 arm64: mte: Fix PTRACE_{PEEK,POKE}MTETAGS error documentation
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Catalin Marinas <[email protected]>
[ Upstream commit fdb9ebc7fb7788b8371fbef6c17dc5c8291e1429 ]
PTRACE_{PEEK,POKE}MTETAGS return -EIO rather than -EOPNOTSUPP (as documented) when no tags are copied from/to a mapping without PROT_MTE. This has been the behaviour since the interface was introduced, though the original intent was to distinguish between address not being accessible and mapped as untagged.
Update the documentation to match the implementation (de-facto ABI). Since -EOPNOTSUPP was never returned, change the error assignment to -EIO as well to avoid confusion.
--- Documentation/arch/arm64/memory-tagging-extension.rst | 5 ++--- arch/arm64/kernel/mte.c | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-)
Documentation/arch/arm64/memory-tagging-extension.rst +2 -3
@@ -208,11 +208,10 @@ will use the corresponding aligned address. tracer's space cannot be accessed or does not have valid tags. - ``-EPERM`` - the specified process cannot be traced. - ``-EIO`` - the tracee's address range cannot be accessed (e.g. invalid - address) and no tags copied. ``iov_len`` not updated. + address) or does not have valid tags (not mapped with the ``PROT_MTE`` + flag) and no tags copied. ``iov_len`` not updated. - ``-EFAULT`` - fault on accessing the tracer's memory (``struct iovec`` or ``iov_base`` buffer) and no tags copied. ``iov_len`` not updated. -- ``-EOPNOTSUPP`` - the tracee's address does not have valid tags (never - mapped with the ``PROT_MTE`` flag). ``iov_len`` not updated. **Note**: There are no transient errors for the requests above, so user programs should not retry in case of a non-zero system call return.
arch/arm64/kernel/mte.c +1 -1
@@ -476,7 +476,7 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr,* was never mapped with PROT_MTE. */ if (!(vma->vm_flags &VM_MTE )) { - err = -EOPNOTSUPP ; + err = -EIO ;put_page (page);break ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 112/438 drm: Fix drm_pending_vblank_event leak in error path for out_fence_ptr
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thadeu Lima de Souza Cascardo <[email protected]>
[ Upstream commit 9eb1a393c89a79c4210230d23e7d88d239c61d7b ]
When an out_fence_ptr is provided but DRM_MODE_PAGE_FLIP_EVENT is not set, a drm_pending_vblank_event will be allocated. If later, there is an allocation failure or another failure at setup_out_fence(), that event will not have base.fence set and it will not be released at complete_signaling().
Release the event and set crtc_state->event to NULL just like in the DRM_MODE_PAGE_FLIP_EVENT case when there is a failure at drm_event_reserve_init(). That is, prepare_signaling() releases the event and there is nothing to be done at complete_signaling(). Use drm_event_cancel_free() as that will also undo drm_event_reserve_init() in case it has been called.
--- drivers/gpu/drm/drm_atomic_uapi.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
drivers/gpu/drm/drm_atomic_uapi.c +10 -3
@@ -1461,10 +1461,12 @@ static int prepare_signaling(struct drm_device *dev,struct dma_fence *fence;struct drm_out_fence_state *f; + ret = -ENOMEM ; + f =krealloc (*fence_state,sizeof (**fence_state) * (*num_fences +1 ),GFP_KERNEL );if (!f) -return -ENOMEM ; + goto err_free_event;memset (&f[*num_fences],0 ,sizeof (*f));
@@ -1473,12 +1475,12 @@ static int prepare_signaling(struct drm_device *dev, fence =drm_crtc_create_fence (crtc);if (!fence) -return -ENOMEM ; + goto err_free_event; ret =setup_out_fence (&f[(*num_fences)++], fence);if (ret) {dma_fence_put (fence); -return ret; + goto err_free_event; } crtc_state->event->base.fence = fence;
@@ -1534,6 +1536,11 @@ static int prepare_signaling(struct drm_device *dev, }return 0 ; + +err_free_event: +drm_event_cancel_free (dev, &crtc_state->event->base); + crtc_state->event =NULL ; +return ret; } static void complete_signaling(struct drm_device *dev,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 113/438 smb: client: validate absolute native symlink targets before NT fixups
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 23c240d9509e15f72e4112fc95f0160ab32ec430 ]
With symlinkroot unset, an absolute target is copied without conversion to an NT drive path. Later code still assumes an NT prefix is present when modifying the target and calculating the print name length.
For "/ab", this causes two failures: sym[5] and path[5] are written past their allocations, and plen -= 2 * poff subtracts an assumed 8-byte prefix from a 6-byte UTF-16 target, wrapping u16 plen to 65534. That underflow causes another overflow: memcpy() copies 65534 bytes into a 24-byte buffer. A user with write access to a mounted share can trigger these bugs with default settings.
Validate the NT drive prefix, including an ASCII drive letter, before accessing fixed offsets or subtracting the prefix length.
--- fs/smb/client/reparse.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-)
fs/smb/client/reparse.c +17 -7
@@ -3,6 +3,7 @@* Copyright (c) 2024 Paulo Alcantara <[email protected]> */ +#include <linux/ctype.h> #include <linux/fs.h> #include <linux/stat.h> #include <linux/slab.h>
@@ -159,15 +160,24 @@ static int create_native_symlink(const unsigned int xid, struct inode *inode,convert_delimiter (sym, sep);/* -* For absolute NT symlinks it is required to pass also leading -* backslash and to not mangle NT object prefix "\\??\\" and not to -* mangle colon in drive letter. But cifs_convert_path_to_utf16() -* removes leading backslash and replaces '?' and ':'. So temporary -* mask these characters in NT object prefix by '_' and then change -* them back. +* Absolute NT symlinks must retain the leading backslash, "\\??\\" +* prefix and drive-letter colon. cifs_convert_path_to_utf16() strips +* the leading backslash and maps '?' and ':', so temporarily mask +* these characters with '_' and restore them after conversion. +* +* When symlinkroot is unset, sym comes directly from the caller. +* Validate the complete "\\??\\X:" prefix before using fixed offsets +* or subtracting the NT prefix length below. Require an ASCII drive +* letter so the prefix occupies six characters in UTF-16 too. */ -if (!(sbflags &CIFS_MOUNT_POSIX_PATHS ) && symname[0 ] =='/' ) +if (!(sbflags &CIFS_MOUNT_POSIX_PATHS ) && symname[0 ] =='/' ) { +if (!strstarts (sym,"\\??\\" ) || !isascii (sym[4 ]) || + !isalpha (sym[4 ]) || sym[5 ] !=':' ) { + rc = -EINVAL ; + goto out; + } sym[0 ] = sym[1 ] = sym[2 ] = sym[5 ] ='_' ; + }/* * On a POSIX paths mount the symlink target is stored verbatim, so
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 114/438 keys: fix lost wakeup when reaping a dead key type
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 2725ab3f5ad1c5f375c7c9fee4af02a9b138f701 ]
clear_bit() is atomic with respect to the word it modifies, but it is an unordered operation: it implies no memory barrier on either side (Documentation/atomic_bitops.txt).
key_garbage_collector() clears KEY_GC_REAPING_KEYTYPE with clear_bit() and calls wake_up_bit() after reaping a dead key type. wake_up_bit() uses a lockless waitqueue check and requires a full barrier after the clear.
The existing smp_mb() is before clear_bit(), so nothing orders the clear against that check. The GC can see an empty waitqueue while unregister_key_type() still sees the bit set. The final wakeup is then lost, leaving module unload stuck in wait_on_bit().
Use clear_and_wake_up_bit(). Its clear_bit_unlock() has RELEASE semantics, so the completed GC work stays ordered before the clear, and its smp_mb__after_atomic() orders the clear before the waitqueue check.
--- security/keys/gc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
security/keys/gc.c +1 -3
@@ -318,9 +318,7 @@ static void key_garbage_collector(struct work_struct *work)if (unlikely (gc_state &KEY_GC_REAPING_DEAD_3 )) {kdebug ("dead wake" ); -smp_mb (); -clear_bit (KEY_GC_REAPING_KEYTYPE , &key_gc_flags); -wake_up_bit (&key_gc_flags,KEY_GC_REAPING_KEYTYPE ); +clear_and_wake_up_bit (KEY_GC_REAPING_KEYTYPE , &key_gc_flags); }if (gc_state &KEY_GC_REAP_AGAIN )
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 115/438 neighbour: Add missing RCU annotation for neightbl_dump_info().
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 764dcebb033764633700a036c7351a7c6350eec6 ]
neightbl_dump_info() fetches the first non-default neigh_parms with list_next_entry(&tbl->parms, ...) and iterates through the list with list_for_each_entry_from_rcu().
However, list_next_entry() does not use RCU helper.
Let's use list_for_each_entry_rcu() and skip the default parms.
--- net/core/neighbour.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
net/core/neighbour.c +5 -2
@@ -2611,11 +2611,14 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)break ; nidx =0 ; - p =list_next_entry (&tbl->parms, list); -list_for_each_entry_from_rcu (p, &tbl->parms_list, list) { + +list_for_each_entry_rcu (p, &tbl->parms_list, list) {if (!net_eq (neigh_parms_net (p), net))continue ; +if (!p->dev) +continue ; +if (nidx < neigh_skip) goto next;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 116/438 neighbour: Enforce min/max to NDTPA_INTERVAL_PROBE_TIME_MS.
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 6d79b223ec44ada58ad37db42f539b60985a7722 ]
NDTPA_INTERVAL_PROBE_TIME_MS sets .type and .min but misses .validation_type, so no validation is applied:
# ynl --family rt-neigh --do setneightbl \
--json '{"name": "arp_cache", "parms": {"interval-probe-time-ms": 0}}' # ynl --family rt-neigh --dump getneightbl --output-json | \
jq '.[] | select(.name == "arp_cache" and has("config"))
| .parms["interval-probe-time-ms"]'
0Moreover, nla_get_msecs() uses msecs_to_jiffies(), and u64 is silently cast to u32, so a larger value can bypass the min check:
e.g. 4294967296 == 0x100000000
# ynl --family rt-neigh --do setneightbl \
--json '{"name": "arp_cache", "parms": {"interval-probe-time-ms": 4294967296}}' # ynl --family rt-neigh --dump getneightbl --output-json | \
jq '.[] | select(.name == "arp_cache" and has("config"))
| .parms["interval-probe-time-ms"]'
0msecs_to_jiffies() returns MAX_JIFFY_OFFSET if the value is larger than INT_MAX. Also, INT_MAX ms overflows int NEIGH_VAR() when HZ > 1000 (Alpha, MIPS), and passing a negative integer to queue_delayed_work(unsigned long delay) causes sign extension, which wraps around the expiry time to the past, resulting in it being handled as 0 delay in the timer wheel.
Let's use NLA_POLICY_FULL_RANGE() and limit the max to 1 day.
The same max check is applied to sysctl as well.
Note that this controls the probe interval for NTF_MANAGED entries, so the max of 1 day is unlikely to break any deployments.
--- Documentation/netlink/specs/rt-neigh.yaml | 3 +++ Documentation/networking/ip-sysctl.rst | 2 +- net/core/neighbour.c | 17 +++++++++++++---- 3 files changed, 17 insertions(+), 5 deletions(-)
Documentation/netlink/specs/rt-neigh.yaml +3 -0
@@ -341,6 +341,9 @@ attribute-sets: - name: interval-probe-time-ms type: u64 + checks: + min: 1 + max: 86400000 operations: enum-model: directional
Documentation/networking/ip-sysctl.rst +1 -1
@@ -248,7 +248,7 @@ neigh/default/unres_qlen - INTEGER neigh/default/interval_probe_time_ms - INTEGER The probe interval for neighbor entries with NTF_MANAGED flag, - the min value is 1. + the min value is 1, and the max value is 86400000 (1 day). Default: 5000
net/core/neighbour.c +13 -4
@@ -2359,6 +2359,13 @@ static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = { [NDTA_PARMS] = { .type = NLA_NESTED }, }; +#define NTBL_PARM_MS_MAX (24 * 60 * 60 * MSEC_PER_SEC) + +static const struct netlink_range_validation nl_ntbl_parm_ms_range = { + .min =1 , + .max =NTBL_PARM_MS_MAX , +}; +static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX +1 ] = { [NDTPA_IFINDEX ] = { .type =NLA_U32 }, [NDTPA_QUEUE_LEN ] = { .type =NLA_U32 },
@@ -2375,7 +2382,8 @@ static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = { [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 }, [NDTPA_PROXY_DELAY] = { .type = NLA_U64 }, [NDTPA_LOCKTIME] = { .type = NLA_U64 }, - [NDTPA_INTERVAL_PROBE_TIME_MS] = { .type = NLA_U64, .min = 1 }, + [NDTPA_INTERVAL_PROBE_TIME_MS ] =NLA_POLICY_FULL_RANGE (NLA_U64 , + &nl_ntbl_parm_ms_range), }; static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -3672,12 +3680,13 @@ static int neigh_proc_dointvec_ms_jiffies_positive(const struct ctl_table *ctl, void *buffer, size_t *lenp, loff_t *ppos) { struct ctl_table tmp = *ctl; -int ret; +int ret, min, max; -int min =msecs_to_jiffies (1 ); + min =msecs_to_jiffies (1 ); + max =msecs_to_jiffies (NTBL_PARM_MS_MAX ); tmp.extra1 = &min; - tmp.extra2 =NULL ; + tmp.extra2 = &max; ret =proc_dointvec_ms_jiffies_minmax (&tmp, write, buffer, lenp, ppos);neigh_proc_update (ctl, write);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 117/438 neighbour: Dont render blackhole_netdev via RTM_GETNEIGHTBL.
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 7b430fcfc972f61b09cc19ca95997586af4a147d ]
The cited commits started to initialise blackhole_netdev with neigh_parms_alloc().
This is visible in init_net as the ifindex==0 entries via RTM_GETNEIGHTBL:
# ynl --family rt-neigh --dump getneightbl --output-json \
| jq '.[] | select(.parms.ifindex == 0)
| {name: .name, ifindex: .parms.ifindex}'
{
"name": "arp_cache",
"ifindex": 0
}
{
"name": "ndisc_cache",
"ifindex": 0
}For RTM_SETNEIGHTBL, ifindex being 0 means wildcard.
Let's skip blackhole_netdev's parms in neightbl_dump_info().
Note that lookup_neigh_parms() does not need the same change because the default parms is always the first entry and matches with ifindex == 0.
--- net/core/neighbour.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/core/neighbour.c +1 -1
@@ -2624,7 +2624,7 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)if (!net_eq (neigh_parms_net (p), net))continue ; -if (!p->dev) +if (!p->dev || p->dev == blackhole_netdev)continue ;if (nidx < neigh_skip)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 118/438 neighbour: Skip default parms when resumed in neightbl_dump_info().
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 979aabdad8dd03394467ee484a1a70f3d40b19ba ]
neightbl_dump_info() calls neightbl_fill_info() in each loop to render the default parms.
If there are many devices and neightbl_fill_param_info() failed, neightbl_fill_info() is called again when the dump resumes:
# ynl --family rt-neigh --dump getneightbl --output-json |
jq '.[] | {name: .name, ifindex: .parms.ifindex}'
...
{
"name": "ndisc_cache",
"ifindex": null
}
...
{
"name": "ndisc_cache",
"ifindex": 6
}
{
"name": "ndisc_cache",
"ifindex": null
}
{
"name": "ndisc_cache",
"ifindex": 5
}Let's skip neightbl_fill_info() if it is already called in neightbl_dump_info().
Note that we cannot use !neigh_skip instead of !default_skip because default_skip == 1 && neigh_skip == 0 could be true if the first neightbl_fill_param_info() fails.
Also, nidx must be cleared at the end of each table loop; otherwise, if neightbl_fill_info() for a subsequent table fails, the leftover nidx from the previous table would be saved in cb->args[1], resulting in erroneously skipping parms of the subsequent table in the next dump.
--- net/core/neighbour.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
net/core/neighbour.c +8 -3
@@ -2587,9 +2587,10 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb) {const struct nlmsghdr *nlh = cb->nlh;struct net *net =sock_net (skb->sk); +int default_skip = cb->args[2 ]; +int neigh_skip = cb->args[1 ];int family, tidx, nidx =0 ;int tbl_skip = cb->args[0 ]; -int neigh_skip = cb->args[1 ];struct neigh_table *tbl;if (cb->strict_check) {
@@ -2613,12 +2614,13 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)if (tidx < tbl_skip || (family && tbl->family != family))continue ; -if (neightbl_fill_info (skb, tbl,NETLINK_CB (cb->skb).portid, +if (!default_skip && +neightbl_fill_info (skb, tbl,NETLINK_CB (cb->skb).portid, nlh->nlmsg_seq,RTM_NEWNEIGHTBL ,NLM_F_MULTI ) <0 )break ; - nidx =0 ; + default_skip =1 ;list_for_each_entry_rcu (p, &tbl->parms_list, list) {if (!net_eq (neigh_parms_net (p), net))
@@ -2641,12 +2643,15 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb) } neigh_skip =0 ; + nidx =0 ; + default_skip =0 ; } out:rcu_read_unlock (); cb->args[0 ] = tidx; cb->args[1 ] = nidx; + cb->args[2 ] = default_skip;return skb->len; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 119/438 ALSA: bcd2000: Fix race between rawmidi and disconnect
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 221253723dc58bb901c3f27a7659823e63fc598c ]
Although we tried to fix the potential UAF issues at USB disconnect on bcd2000 driver, there is still an overlooked case -- namely, when a rawmidi trigger callback has been already running at USB disconnect handling, the in-flight function (e.g. bcd2000_midi_send()) could still access the URB, because the previous URB NULL-check & clearance was considered only for the URB complete callbacks, but not about the parallel rawmidi operations.
For addressing the race, this patch introduced a new spinlock that covers each rawmidi operation as well as the rawmidi handling in the complete callback. The URB is cleared with the lock, so it guarantees that the pending rawmidi task already finished or a NULL check is effective.
--- sound/usb/bcd2000/bcd2000.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-)
sound/usb/bcd2000/bcd2000.c +26 -7
@@ -43,6 +43,7 @@ struct bcd2000 {struct usb_interface *intf;int card_index; +spinlock_t midi_lock;int midi_out_active;struct snd_rawmidi *rmidi;struct snd_rawmidi_substream *midi_receive_substream;
@@ -90,6 +91,8 @@ static void bcd2000_midi_input_trigger(struct snd_rawmidi_substream *substream, int up) {struct bcd2000 *bcd2k = substream->rmidi->private_data; + +guard (spinlock_irqsave)(&bcd2k->midi_lock); bcd2k->midi_receive_substream = up ? substream :NULL ; }
@@ -195,6 +198,8 @@ static void bcd2000_midi_output_trigger(struct snd_rawmidi_substream *substream, {struct bcd2000 *bcd2k = substream->rmidi->private_data; +guard (spinlock_irqsave)(&bcd2k->midi_lock); +if (up) { bcd2k->midi_out_substream = substream;/* check if there is data userspace wants to send */
@@ -219,6 +224,7 @@ static void bcd2000_output_complete(struct urb *urb)return ;/* check if there is more data userspace wants to send */ +guard (spinlock_irqsave)(&bcd2k->midi_lock);bcd2000_midi_send (bcd2k); }
@@ -234,6 +240,8 @@ static void bcd2000_input_complete(struct urb *urb)if (!bcd2k || urb->status == -ESHUTDOWN )return ; +guard (spinlock_irqsave)(&bcd2k->midi_lock); +if (urb->actual_length >0 )bcd2000_midi_handle_input (bcd2k, urb->transfer_buffer, urb->actual_length);
@@ -348,16 +356,26 @@ static int bcd2000_init_midi(struct bcd2000 *bcd2k)return 0 ; } +static void bcd2000_midi_free (struct bcd2000 *bcd2k, +struct urb **urb_p) +{ +struct urb *urb = *urb_p; + +if (!urb) +return ; + +usb_poison_urb (urb); +scoped_guard (spinlock_irq, &bcd2k->midi_lock) + *urb_p =NULL ; + +usb_free_urb (urb); +} +static void bcd2000_free_usb_related_resources (struct bcd2000 *bcd2k,struct usb_interface *interface) { -usb_poison_urb (bcd2k->midi_out_urb); -usb_poison_urb (bcd2k->midi_in_urb); - -usb_free_urb (bcd2k->midi_out_urb); -usb_free_urb (bcd2k->midi_in_urb); - bcd2k->midi_out_urb =NULL ; - bcd2k->midi_in_urb =NULL ; +bcd2000_midi_free (bcd2k, &bcd2k->midi_out_urb); +bcd2000_midi_free (bcd2k, &bcd2k->midi_in_urb);if (bcd2k->intf) {usb_set_intfdata (bcd2k->intf,NULL );
@@ -393,6 +411,7 @@ static int bcd2000_probe(struct usb_interface *interface, bcd2k->card = card; bcd2k->card_index = card_index; bcd2k->intf = interface; +spin_lock_init (&bcd2k->midi_lock);snd_card_set_dev (card, &interface->dev);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 120/438 ntfs: use dynamic MFT tail reservation
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namjae Jeon <[email protected]>
[ Upstream commit 6d8c197c9992659a65525a07de4368c8401fdda7 ]
The ntfs MFT allocator historically treated records below 64 as a permanent extension area and stopped searching for $MFT extent records after record 400. Windows and ntfs3 do not maintain that on-disk layout, so an NTFS volume can have free MFT records while ntfs returns -ENOSPC when $MFT:$DATA needs another mapping-pairs extent.
Use record 24 as the first normal record and maintain an in-memory tail reserve of up to four initialized records. Normal allocations skip the reserve, while $MFT metadata extent allocations consume it. When a new tail is initialized, allocate at least two records and reserve the following records to avoid recursive allocation during MFT extension. Existing free runs can seed the reserve on volumes mounted without one.
For $MFT/$DATA, constrain an extent record to a record whose byte offset is below the new extent lowest VCN byte offset. This preserves bootstrap reachability without an arbitrary record 400 limit. If no safe record is available, validate and use reserved records 15, 12, 13, and 14 as bootstrap candidates while keeping their MFT bitmap entries in use.
This allows existing Windows volumes to extend $MFT using their actual free records and prevents normal file allocation from consuming the metadata reserve.
--- fs/ntfs/attrib.c | 11 +- fs/ntfs/mft.c | 420 +++++++++++++++++++++++++++++++++++++---------- fs/ntfs/mft.h | 2 +- fs/ntfs/namei.c | 2 +- fs/ntfs/volume.h | 6 + 5 files changed, 349 insertions(+), 92 deletions(-)
fs/ntfs/attrib.c +7 -4
@@ -2912,7 +2912,7 @@ int ntfs_attr_add(struct ntfs_inode *ni, __le32 type, attr_ni =NULL ;/* Allocate new extent. */ - err =ntfs_mft_record_alloc (ni->vol,0 , &attr_ni, ni,NULL ); + err =ntfs_mft_record_alloc (ni->vol,0 , &attr_ni, ni,NULL ,-1 );if (err) {ntfs_error (sb,"Failed to allocate extent record" ); goto err_out;
@@ -3545,7 +3545,7 @@ int ntfs_attr_record_move_away(struct ntfs_attr_search_ctx *ctx, int extra)* new extent and move attribute to it. */ ni =NULL ; - err =ntfs_mft_record_alloc (base_ni->vol,0 , &ni, base_ni,NULL ); + err =ntfs_mft_record_alloc (base_ni->vol,0 , &ni, base_ni,NULL ,-1 );if (err) {ntfs_error (sb,"Couldn't allocate MFT record, err : %d" , err);return err;
@@ -3971,7 +3971,10 @@ int ntfs_attr_update_mapping_pairs(struct ntfs_inode *ni, s64 from_vcn)unsigned int de_cnt =0 ;/* Allocate new mft record. */ - err =ntfs_mft_record_alloc (ni->vol,0 , &ext_ni, base_ni,NULL ); + err =ntfs_mft_record_alloc (ni->vol,0 , &ext_ni, base_ni,NULL , + base_ni->mft_no ==FILE_MFT && + ni->type ==AT_DATA && + ni->name ==AT_UNNAMED ? stop_vcn :-1 );if (err) {ntfs_error (sb,"Failed to allocate extent record" ); goto put_err_out;
@@ -4831,7 +4834,7 @@ static int ntfs_resident_attr_resize(struct ntfs_inode *attr_ni, const s64 newsi }/* Allocate new mft record. */ - err =ntfs_mft_record_alloc (base_ni->vol,0 , &ext_ni, base_ni,NULL ); + err =ntfs_mft_record_alloc (base_ni->vol,0 , &ext_ni, base_ni,NULL ,-1 );if (err) {ntfs_error (sb,"Couldn't allocate MFT record" ); goto put_err_out;
fs/ntfs/mft.c +334 -86
631 lines not on this page · raw message
fs/ntfs/mft.h +1 -1
@@ -78,7 +78,7 @@ static inline int write_mft_record(struct ntfs_inode *ni, struct mft_record *m,int ntfs_mft_record_alloc (struct ntfs_volume *vol,const int mode,struct ntfs_inode **ni,struct ntfs_inode *base_ni, -struct mft_record **ni_mrec); +struct mft_record **ni_mrec,const s64 mft_data_vcn);int ntfs_mft_record_free (struct ntfs_volume *vol,struct ntfs_inode *ni);int ntfs_mft_records_write (const struct ntfs_volume *vol,const u64 mref,const s64 count,struct mft_record *b);
fs/ntfs/namei.c +1 -1
@@ -480,7 +480,7 @@ static struct ntfs_inode *__ntfs_create(struct mnt_idmap *idmap, struct inode *dmark_inode_dirty (dir); err =ntfs_mft_record_alloc (dir_ni->vol, mode, &ni,NULL , - &ni_mrec); + &ni_mrec,-1 );if (err) {iput (vi);return ERR_PTR (err);
fs/ntfs/volume.h +6 -0
@@ -55,6 +55,10 @@* @attrdef_size: Size of the attribute definition table in bytes. * @attrdef: Table of attribute definitions. Obtained from FILE_AttrDef. * @mft_data_pos: Mft record number at which to allocate the next mft record. +* @mft_record_reserve_pos: First record in the in-memory MFT metadata reserve +* (protected by mftbmp_lock). +* @mft_record_reserve_end: First record beyond the MFT metadata reserve +* (protected by mftbmp_lock). * @mft_zone_start: First cluster of the mft zone. * @mft_zone_end: First cluster beyond the mft zone. * @mft_zone_pos: Current position in the mft zone.
@@ -119,6 +123,8 @@ struct ntfs_volume {s32 attrdef_size;struct attr_def *attrdef;s64 mft_data_pos; +s64 mft_record_reserve_pos; +s64 mft_record_reserve_end;s64 mft_zone_start;s64 mft_zone_end;s64 mft_zone_pos;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 121/438 ntfs: repack $MFT/$ATTRIBUTE LIST
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namjae Jeon <[email protected]>
[ Upstream commit b1d732e62a5b3942546e4edaab8976258e779287 ]
Repack the non-resident $MFT/$ATTRIBUTE_LIST into a contiguous run when its mapping pairs no longer fit in the base MFT record. Propagate allocation and writeback errors, and check synchronous replacement writes.
--- fs/ntfs/attrib.c | 47 ++++++++--- fs/ntfs/attrlist.c | 202 ++++++++++++++++++++++++++++++++++++++++++--- fs/ntfs/inode.c | 10 ++- 3 files changed, 236 insertions(+), 23 deletions(-)
fs/ntfs/attrib.c +37 -10
@@ -3839,13 +3839,13 @@ int ntfs_attr_update_mapping_pairs(struct ntfs_inode *ni, s64 from_vcn)*/ if (ni->type ==AT_ATTRIBUTE_LIST ) {ntfs_attr_put_search_ctx (ctx); -if (ntfs_inode_free_space (base_ni, mp_size - - cur_max_mp_size)) { -ntfs_debug ("Attribute list is too big. Defragment the volume\n" ); -return -ENOSPC ; - } -if (ntfs_attrlist_update (base_ni)) -return -EIO ; + err =ntfs_inode_free_space (base_ni, mp_size - + cur_max_mp_size); +if (err) +return err; + err =ntfs_attrlist_update (base_ni); +if (err) +return err; goto retry; }
@@ -4517,13 +4517,39 @@ static int ntfs_non_resident_attr_expand(struct ntfs_inode *ni, const s64 newsizntfs_bytes_to_cluster (vol, ni->allocated_size), first_free_vcn -ntfs_bytes_to_cluster (vol, ni->allocated_size), - lcn_seek_from, DATA_ZONE, false, false, false); + lcn_seek_from,DATA_ZONE , false, + ni->type == AT_ATTRIBUTE_LIST, false);if (IS_ERR (rl)) {ntfs_debug ("Cluster allocation failed (%lld)" , (long long )first_free_vcn -ntfs_bytes_to_cluster (vol, ni->allocated_size));return PTR_ERR (rl); } +/* +* A contiguous ATTRIBUTE_LIST allocation keeps its mapping +* pairs small enough to fit in the base MFT record. The +* allocator can return a short run when contiguity was +* requested, so discard it and retry normally if necessary. +*/ +if (ni->type ==AT_ATTRIBUTE_LIST && + (rl->vcn !=ntfs_bytes_to_cluster (vol, + ni->allocated_size) || + rl->length != first_free_vcn - +ntfs_bytes_to_cluster (vol, ni->allocated_size) || + rl[1 ].length)) { +ntfs_cluster_free_from_rl (vol, rl); +kvfree (rl); + rl =ntfs_cluster_alloc (vol, +ntfs_bytes_to_cluster (vol, + ni->allocated_size), + first_free_vcn - +ntfs_bytes_to_cluster (vol, + ni->allocated_size), + lcn_seek_from,DATA_ZONE , false, + false, false); +if (IS_ERR (rl)) +return PTR_ERR (rl); + } }if (!NInoCompressed (ni)) {
@@ -4916,7 +4942,8 @@ int ntfs_attr_expand(struct ntfs_inode *ni, const s64 newsize, const s64 preallontfs_debug ("Entering for inode 0x%llx, attr 0x%x, size %lld\n" , (unsigned long long )ni->mft_no, ni->type, newsize); -if (ni->data_size == newsize) { +if (ni->data_size == newsize && + (!prealloc_size || prealloc_size <= ni->allocated_size)) {ntfs_debug ("Size is already ok\n" );return 0 ; }
@@ -4931,7 +4958,7 @@ int ntfs_attr_expand(struct ntfs_inode *ni, const s64 newsize, const s64 preallo }if (NInoNonResident (ni)) { -if (newsize > ni->data_size) +if (newsize > ni->data_size || prealloc_size > ni->allocated_size) err =ntfs_non_resident_attr_expand (ni, newsize, prealloc_size,NVolDisableSparse (ni->vol) ?HOLES_NO :HOLES_OK , true);
fs/ntfs/attrlist.c +190 -12
242 lines not on this page · raw message
fs/ntfs/inode.c +9 -1
@@ -3745,6 +3745,7 @@ static s64 __ntfs_inode_non_resident_attr_pwrite(struct inode *vi,u64 rl_length =0 ;s64 vcn;struct runlist_element *rl; +int bio_err; lcn_count =max_t (s64,1 ,ntfs_bytes_to_cluster (vol, attr_len)); vcn =ntfs_pidx_to_cluster (vol, folio->index);
@@ -3788,8 +3789,15 @@ static s64 __ntfs_inode_non_resident_attr_pwrite(struct inode *vi, goto err_unlock_folio; } -submit_bio_wait (bio); + bio_err =submit_bio_wait (bio);bio_put (bio); +if (bio_err) { +ntfs_error (vi->i_sb, +"Synchronous attribute write failed (%d)" , + bio_err); + ret = bio_err; + goto err_unlock_folio; + } vcn += rl_length; offset += length; }while (lcn_count !=0 );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 122/438 ntfs: account for MFT records added during allocation
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namjae Jeon <[email protected]>
[ Upstream commit 631946431ddc66a472c5cc629cd654e62dfa1f88 ]
When no free MFT record is available in the initialized $MFT/$BITMAP, ntfs_mft_record_alloc() extends $MFT/$DATA and formats the requested record together with a dynamically sized tail reserve. Those records become visible through the $MFT file size before charging the requested record to the free-record counter.
Account for all newly visible records before releasing the MFT allocation lock, then subtract the one record being allocated. Keep MFT counter updates independent of the asynchronous free-cluster scan and update the counter when a record is successfully cleared in the MFT bitmap.
Store the clamped result of the MFT bitmap scan and keep statfs from exposing an invalid cached count if an accounting error occurs.
--- fs/ntfs/mft.c | 11 ++++++++--- fs/ntfs/super.c | 12 +++++++++--- fs/ntfs/volume.h | 6 ------ 3 files changed, 17 insertions(+), 12 deletions(-)
fs/ntfs/mft.c +8 -3
@@ -1539,7 +1539,6 @@ static int ntfs_mft_bitmap_extend_initialized_nolock(struct ntfs_volume *vol) ret =ntfs_attr_set (mftbmp_ni, old_initialized_size,8 ,0 );if (likely (!ret)) {ntfs_debug ("Done. (Wrote eight initialized bytes to mft bitmap." ); -ntfs_inc_free_mft_records (vol,8 *8 );return 0 ; }ntfs_error (vol->sb,"Failed to write to mft bitmap." );
@@ -2135,6 +2134,7 @@ int ntfs_mft_record_alloc(struct ntfs_volume *vol, const int mode, struct mft_record **ni_mrec, const s64 mft_data_vcn) { s64 ll, bit, old_data_initialized, old_data_size; +s64 nr_new_mft_records =0 ;s64 max_mft_no =-1 , reserve_start =-1 , reserve_end =-1 ;s64 candidate_reserve_end =-1 ;s64 *reserve_endp;
@@ -2501,8 +2501,13 @@ int ntfs_mft_record_alloc(struct ntfs_volume *vol, const int mode, mft_ni->initialized_size);WARN_ON (i_size_read (vol->mft_ino) > mft_ni->allocated_size);WARN_ON (mft_ni->initialized_size >i_size_read (vol->mft_ino)); + nr_new_mft_records = (i_size_read (vol->mft_ino) - old_data_size) >> + vol->mft_record_size_bits;read_unlock_irqrestore (&mft_ni->size_lock, flags); mft_rec_already_initialized: +/* Account for newly visible MFT records before dropping the lock. */ +if (nr_new_mft_records >0 ) +ntfs_inc_free_mft_records (vol, nr_new_mft_records);/* * We can finally drop the mft bitmap lock as the mft data attribute * has been fully updated. The only disparity left is that the
@@ -2814,6 +2819,8 @@ int ntfs_mft_record_free(struct ntfs_volume *vol, struct ntfs_inode *ni)if (base_ni->mft_no !=FILE_MFT )down_write (&vol->mftbmp_lock); err =ntfs_bitmap_clear_bit (vol->mftbmp_ino, mft_no); +if (!err) +ntfs_inc_free_mft_records (vol,1 );if (!err && base_ni->mft_no ==FILE_MFT && mft_no +1 == vol->mft_record_reserve_pos && mft_no < vol->mft_record_reserve_end)
@@ -2823,9 +2830,7 @@ int ntfs_mft_record_free(struct ntfs_volume *vol, struct ntfs_inode *ni)memalloc_nofs_restore (memalloc_flags);if (err) goto bitmap_rollback; -unmap_mft_record (ni); -ntfs_inc_free_mft_records (vol,1 );return 0 ;/* Rollback what we did... */
fs/ntfs/super.c +9 -3
@@ -2064,8 +2064,7 @@ static unsigned long __get_nr_free_mft_records(struct ntfs_volume *vol,/* If errors occurred we may well have gone below zero, fix this. */ if (nr_free <0 ) nr_free =0 ; -else -atomic64_set (&vol->free_mft_records, nr_free); +atomic64_set (&vol->free_mft_records, nr_free);ntfs_debug ("Exiting." );return nr_free;
@@ -2131,7 +2130,14 @@ static int ntfs_statfs(struct dentry *dentry, struct kstatfs *sfs)read_unlock_irqrestore (&mft_ni->size_lock, flags);/* Free inodes in fs (based on current total count). */ - sfs->f_ffree =atomic64_read (&vol->free_mft_records); + size =atomic64_read (&vol->free_mft_records); +if (unlikely (size <0 || size > (s64 )sfs->f_files)) +ntfs_warning (vol->sb,"Invalid free MFT record count %lld." , size); +if (size <0 ) + size =0 ; +else if (size > (s64 )sfs->f_files) + size = sfs->f_files; + sfs->f_ffree = size;/* * File system id. This is extremely *nix flavour dependent and even
fs/ntfs/volume.h +0 -6
@@ -258,17 +258,11 @@ static inline void ntfs_dec_free_clusters(struct ntfs_volume *vol, s64 nr)static inline void ntfs_inc_free_mft_records (struct ntfs_volume *vol,s64 nr) { -if (!NVolFreeClusterKnown (vol)) -return ; -atomic64_add (nr, &vol->free_mft_records); }static inline void ntfs_dec_free_mft_records (struct ntfs_volume *vol,s64 nr) { -if (!NVolFreeClusterKnown (vol)) -return ; -atomic64_sub (nr, &vol->free_mft_records); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 123/438 ntfs: protect runlist updates with the runlist lock
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namjae Jeon <[email protected]>
[ Upstream commit 91709ba5d6d709b2b663287b7e871e2c6b480502 ]
ntfs_non_resident_attr_shrink() calls runlist helpers that require the runlist write lock, but did not hold it while freeing clusters and truncating the runlist. Serialize those operations and the resident conversion with the runlist lock.
ntfs_attr_map_cluster() can merge a newly allocated run before updating mapping pairs. If the update fails, free the clusters and restore both the in-memory runlist and on-disk mapping pairs from a saved runlist. Mark the volume in error if either rollback step fails.
--- fs/ntfs/attrib.c | 205 +++++++++++++++++++++++++++++++++++---------- fs/ntfs/attrib.h | 9 ++ fs/ntfs/attrlist.c | 46 ++++++---- fs/ntfs/attrlist.h | 2 + fs/ntfs/compress.c | 2 +- fs/ntfs/file.c | 3 +- fs/ntfs/inode.c | 2 +- fs/ntfs/mft.c | 13 +-- 8 files changed, 216 insertions(+), 66 deletions(-)
fs/ntfs/attrib.c +161 -44
@@ -3569,7 +3569,8 @@ int ntfs_attr_record_move_away(struct ntfs_attr_search_ctx *ctx, int extra)* update allocated and compressed size. */ static int ntfs_attr_update_meta (struct attr_record *a,struct ntfs_inode *ni, -struct mft_record *m,struct ntfs_attr_search_ctx *ctx) +struct mft_record *m,struct ntfs_attr_search_ctx *ctx, +struct ntfs_inode *locked_ni,bool defer_attrlist) {int sparse, err =0 ;struct ntfs_inode *base_ni;
@@ -3605,6 +3606,8 @@ static int ntfs_attr_update_meta(struct attr_record *a, struct ntfs_inode *ni, le16_to_cpu(a->data.non_resident.mapping_pairs_offset) == 8) && !(le32_to_cpu(m->bytes_allocated) - le32_to_cpu(m->bytes_in_use))) { +if (defer_attrlist) +return -ENOSPC ;if (!NInoAttrList (base_ni)) { err =ntfs_inode_add_attrlist (base_ni);if (err)
@@ -3618,7 +3621,7 @@ static int ntfs_attr_update_meta(struct attr_record *a, struct ntfs_inode *ni, goto out; } - err =ntfs_attrlist_update (base_ni); + err =ntfs_attrlist_update_locked (base_ni, locked_ni);if (err) goto out; err = -EAGAIN ;
@@ -3698,6 +3701,8 @@ static int ntfs_attr_update_meta(struct attr_record *a, struct ntfs_inode *ni,* ntfs_attr_update_mapping_pairs - update mapping pairs for ntfs attribute * @ni: non-resident ntfs inode for which we need update * @from_vcn: update runlist starting this VCN +* @locked_ni: inode whose runlist write lock is already held +* @defer_attrlist: return -ENOSPC instead of updating an attribute list * * Build mapping pairs from @na->rl and write them to the disk. Also, this * function updates sparse bit, allocated and compressed size (allocates/frees
@@ -3707,7 +3712,10 @@ static int ntfs_attr_update_meta(struct attr_record *a, struct ntfs_inode *ni,* call to this function. Vice-versa @na->compressed_size will be calculated and * set to correct value during this function. */ -int ntfs_attr_update_mapping_pairs (struct ntfs_inode *ni,s64 from_vcn) +static int __ntfs_attr_update_mapping_pairs (struct ntfs_inode *ni, +s64 from_vcn, +struct ntfs_inode *locked_ni, +bool defer_attrlist) {struct ntfs_attr_search_ctx *ctx;struct ntfs_inode *base_ni;
@@ -3799,7 +3807,8 @@ int ntfs_attr_update_mapping_pairs(struct ntfs_inode *ni, s64 from_vcn)continue ; } - err =ntfs_attr_update_meta (a, ni, m, ctx); + err =ntfs_attr_update_meta (a, ni, m, ctx, locked_ni, + defer_attrlist);if (err <0 ) {if (err == -EAGAIN ) {ntfs_attr_put_search_ctx (ctx);
@@ -3839,11 +3848,17 @@ int ntfs_attr_update_mapping_pairs(struct ntfs_inode *ni, s64 from_vcn)*/ if (ni->type ==AT_ATTRIBUTE_LIST ) {ntfs_attr_put_search_ctx (ctx); + ctx =NULL ; +if (locked_ni == ni || defer_attrlist) { + err = -ENOSPC ; + goto put_err_out; + } err =ntfs_inode_free_space (base_ni, mp_size - cur_max_mp_size);if (err)return err; - err =ntfs_attrlist_update (base_ni); + err =ntfs_attrlist_update_locked ( + base_ni, locked_ni);if (err)return err; goto retry;
@@ -3851,6 +3866,10 @@ int ntfs_attr_update_mapping_pairs(struct ntfs_inode *ni, s64 from_vcn)/* Add attribute list if it isn't present, and retry. */ if (!NInoAttrList (base_ni)) { +if (defer_attrlist) { + err = -ENOSPC ; + goto put_err_out; + }ntfs_attr_put_search_ctx (ctx);if (ntfs_inode_add_attrlist (base_ni)) {ntfs_error (sb,"Can not add attrlist" );
@@ -3878,13 +3897,21 @@ int ntfs_attr_update_mapping_pairs(struct ntfs_inode *ni, s64 from_vcn) } } +if (defer_attrlist && + (ctx->ntfs_ino->nr_extents ==-1 || +NInoAttrList (ctx->ntfs_ino)) && + ctx->attr->type !=AT_ATTRIBUTE_LIST ) { + err = -ENOSPC ; + goto put_err_out; + } +/* Update lowest vcn. */ a->data.non_resident.lowest_vcn =cpu_to_le64 (stop_vcn);mark_mft_record_dirty (ctx->ntfs_ino);if ((ctx->ntfs_ino->nr_extents ==-1 ||NInoAttrList (ctx->ntfs_ino)) && ctx->attr->type !=AT_ATTRIBUTE_LIST ) { ctx->al_entry->lowest_vcn =cpu_to_le64 (stop_vcn); - err =ntfs_attrlist_update (base_ni); + err =ntfs_attrlist_update_locked (base_ni, locked_ni);if (err) goto put_err_out; }
@@ -4059,6 +4086,19 @@ int ntfs_attr_update_mapping_pairs(struct ntfs_inode *ni, s64 from_vcn)return err; } +int ntfs_attr_update_mapping_pairs_locked (struct ntfs_inode *ni, +s64 from_vcn, +struct ntfs_inode *locked_ni) +{ +return __ntfs_attr_update_mapping_pairs (ni, from_vcn, locked_ni, + false); +} + +int ntfs_attr_update_mapping_pairs (struct ntfs_inode *ni,s64 from_vcn) +{ +return ntfs_attr_update_mapping_pairs_locked (ni, from_vcn,NULL ); +} +/* * ntfs_attr_make_resident - convert a non-resident to a resident attribute * @ni: open ntfs attribute to make resident
@@ -4192,7 +4232,9 @@ static int ntfs_attr_make_resident(struct ntfs_inode *ni, struct ntfs_attr_searc* * Reduce the size of a non-resident, open ntfs attribute @na to @newsize bytes. */ -static int ntfs_non_resident_attr_shrink (struct ntfs_inode *ni,const s64 newsize) +static int ntfs_non_resident_attr_shrink (struct ntfs_inode *ni, +const s64 newsize, +struct ntfs_inode *locked_ni) {struct ntfs_volume *vol;struct ntfs_attr_search_ctx *ctx;
@@ -4200,6 +4242,7 @@ static int ntfs_non_resident_attr_shrink(struct ntfs_inode *ni, const s64 newsizs64 nr_freed_clusters;int err;struct ntfs_inode *base_ni; +bool runlist_locked = locked_ni == ni;ntfs_debug ("Inode 0x%llx attr 0x%x new size %lld\n" , (unsigned long long )ni->mft_no, ni->type, (long long )newsize);
@@ -4245,18 +4288,24 @@ static int ntfs_non_resident_attr_shrink(struct ntfs_inode *ni, const s64 newsiz* clusters if there is a change. */ if (ntfs_bytes_to_cluster (vol, ni->allocated_size) != first_free_vcn) { -struct ntfs_attr_search_ctx *ctx; +/* +* ntfs_cluster_free() and ntfs_rl_truncate_nolock() +* both require this lock. +*/ +if (!runlist_locked) +down_write (&ni->runlist.lock); err =ntfs_attr_map_whole_runlist (ni);if (err) {ntfs_debug ("Eeek! ntfs_attr_map_whole_runlist failed.\n" ); -return err; + goto unlock_runlist; } ctx =ntfs_attr_get_search_ctx (ni,NULL );if (!ctx) {ntfs_error (vol->sb,"%s: Failed to get search context" , __func__); -return -ENOMEM ; + err = -ENOMEM ; + goto unlock_runlist; }/* Deallocate all clusters starting with the first free one. */
@@ -4264,7 +4313,8 @@ static int ntfs_non_resident_attr_shrink(struct ntfs_inode *ni, const s64 newsizif (nr_freed_clusters <0 ) {ntfs_debug ("Eeek! Freeing of clusters failed. Aborting...\n" );ntfs_attr_put_search_ctx (ctx); -return (int )nr_freed_clusters; + err = (int )nr_freed_clusters; + goto unlock_runlist; }ntfs_attr_put_search_ctx (ctx);
@@ -4277,7 +4327,8 @@ static int ntfs_non_resident_attr_shrink(struct ntfs_inode *ni, const s64 newsizkvfree (ni->runlist.rl); ni->runlist.rl =NULL ;ntfs_error (vol->sb,"Eeek! Run list truncation failed.\n" ); -return -EIO ; + err = -EIO ; + goto unlock_runlist; }/* Prepare to mapping pairs update. */
@@ -4293,11 +4344,13 @@ static int ntfs_non_resident_attr_shrink(struct ntfs_inode *ni, const s64 newsizVFS_I (base_ni)->i_blocks = ni->allocated_size >>9 ;/* Write mapping pairs for new runlist. */ - err =ntfs_attr_update_mapping_pairs (ni,0 /*first_free_vcn*/ ); + err =ntfs_attr_update_mapping_pairs_locked (ni,0 , ni);if (err) {ntfs_debug ("Eeek! Mapping pairs update failed. Leaving inconstant metadata. Run chkdsk.\n" ); -return err; + goto unlock_runlist; } +if (!runlist_locked) +up_write (&ni->runlist.lock); }/* Get the first attribute record. */
@@ -4339,7 +4392,11 @@ static int ntfs_non_resident_attr_shrink(struct ntfs_inode *ni, const s64 newsiz/* If the attribute now has zero size, make it resident. */ if (!newsize && !NInoEncrypted (ni) && !NInoCompressed (ni)) { +if (!runlist_locked) +down_write (&ni->runlist.lock); err =ntfs_attr_make_resident (ni, ctx); +if (!runlist_locked) +up_write (&ni->runlist.lock);if (err) {/* If couldn't make resident, just continue. */ if (err != -EPERM )
@@ -4356,6 +4413,11 @@ static int ntfs_non_resident_attr_shrink(struct ntfs_inode *ni, const s64 newsiz put_err_out:ntfs_attr_put_search_ctx (ctx);return err; + +unlock_runlist: +if (!runlist_locked) +up_write (&ni->runlist.lock); +return err; }/*
@@ -4364,13 +4426,14 @@ static int ntfs_non_resident_attr_shrink(struct ntfs_inode *ni, const s64 newsiz* @prealloc_size: preallocation size (in bytes) to which to expand the attribute * @newsize: new size (in bytes) to which to expand the attribute * @holes: how to create a hole if expanding -* @need_lock: whether mrec lock is needed or not +* @locked_ni: inode whose runlist lock is already held * * Expand the size of a non-resident, open ntfs attribute @na to @newsize bytes, * by allocating new clusters. */ static int ntfs_non_resident_attr_expand (struct ntfs_inode *ni,const s64 newsize, -const s64 prealloc_size,unsigned int holes,bool need_lock) +const s64 prealloc_size,unsigned int holes, +struct ntfs_inode *locked_ni) {s64 lcn_seek_from;s64 first_free_vcn;
@@ -4568,7 +4631,8 @@ static int ntfs_non_resident_attr_expand(struct ntfs_inode *ni, const s64 newsiz/* Prepare to mapping pairs update. */ ni->allocated_size =ntfs_cluster_to_bytes (vol, first_free_vcn); - err =ntfs_attr_update_mapping_pairs (ni,0 ); + err =ntfs_attr_update_mapping_pairs_locked ( + ni,0 , locked_ni);if (err) {ntfs_debug ("Mapping pairs update failed" ); goto rollback;
@@ -4612,11 +4676,11 @@ static int ntfs_non_resident_attr_expand(struct ntfs_inode *ni, const s64 newsizntfs_debug ("Leaking clusters" );/* Now, truncate the runlist itself. */ -if (need_lock) +if (ni != locked_ni)down_write (&ni->runlist.lock); err2 =ntfs_rl_truncate_nolock (vol, &ni->runlist,ntfs_bytes_to_cluster (vol, org_alloc_size)); -if (need_lock) +if (ni != locked_ni)up_write (&ni->runlist.lock);if (err2) {/*
@@ -4630,11 +4694,11 @@ static int ntfs_non_resident_attr_expand(struct ntfs_inode *ni, const s64 newsiz/* Prepare to mapping pairs update. */ ni->allocated_size = org_alloc_size;/* Restore mapping pairs. */ -if (need_lock) +if (ni != locked_ni)down_read (&ni->runlist.lock); -if (ntfs_attr_update_mapping_pairs (ni,0 )) +if (__ntfs_attr_update_mapping_pairs (ni,0 , locked_ni, true))ntfs_error (sb,"Failed to restore old mapping pairs" ); -if (need_lock) +if (ni != locked_ni)up_read (&ni->runlist.lock);if (NInoSparse (ni) ||NInoCompressed (ni)) {
@@ -4739,7 +4803,8 @@ static int ntfs_resident_attr_resize(struct ntfs_inode *attr_ni, const s64 newsimark_mft_record_dirty (ctx->ntfs_ino);ntfs_attr_put_search_ctx (ctx);/* Resize non-resident attribute */ -return ntfs_non_resident_attr_expand (attr_ni, newsize, prealloc_size, holes, true); +return ntfs_non_resident_attr_expand ( + attr_ni, newsize, prealloc_size, holes,NULL ); }else if (err != -ENOSPC && err != -EPERM ) {ntfs_error (sb,"Failed to make attribute non-resident" ); goto put_err_out;
@@ -4914,13 +4979,14 @@ int __ntfs_attr_truncate_vfs(struct ntfs_inode *ni, const s64 newsize,if (NInoNonResident (ni)) {if (newsize > i_size) {down_write (&ni->runlist.lock); - err =ntfs_non_resident_attr_expand (ni, newsize,0 , -NVolDisableSparse (ni->vol) ? -HOLES_NO :HOLES_OK , - false); + err =ntfs_non_resident_attr_expand ( + ni, newsize,0 , +NVolDisableSparse (ni->vol) ? +HOLES_NO :HOLES_OK , ni);up_write (&ni->runlist.lock); }else - err =ntfs_non_resident_attr_shrink (ni, newsize); + err =ntfs_non_resident_attr_shrink ( + ni, newsize,NULL ); }else err = ntfs_resident_attr_resize(ni, newsize, 0, NVolDisableSparse(ni->vol) ?
@@ -4929,7 +4995,9 @@ int __ntfs_attr_truncate_vfs(struct ntfs_inode *ni, const s64 newsize,return err; } -int ntfs_attr_expand (struct ntfs_inode *ni,const s64 newsize,const s64 prealloc_size) +int ntfs_attr_expand_locked (struct ntfs_inode *ni,const s64 newsize, +const s64 prealloc_size, +struct ntfs_inode *locked_ni) {int err =0 ;
@@ -4959,9 +5027,10 @@ int ntfs_attr_expand(struct ntfs_inode *ni, const s64 newsize, const s64 prealloif (NInoNonResident (ni)) {if (newsize > ni->data_size || prealloc_size > ni->allocated_size) - err =ntfs_non_resident_attr_expand (ni, newsize, prealloc_size, -NVolDisableSparse (ni->vol) ? -HOLES_NO :HOLES_OK , true); + err =ntfs_non_resident_attr_expand ( + ni, newsize, prealloc_size, +NVolDisableSparse (ni->vol) ? +HOLES_NO :HOLES_OK , locked_ni); }else err = ntfs_resident_attr_resize(ni, newsize, prealloc_size, NVolDisableSparse(ni->vol) ?
@@ -4972,6 +5041,12 @@ int ntfs_attr_expand(struct ntfs_inode *ni, const s64 newsize, const s64 prealloreturn err; } +int ntfs_attr_expand (struct ntfs_inode *ni,const s64 newsize, +const s64 prealloc_size) +{ +return ntfs_attr_expand_locked (ni, newsize, prealloc_size,NULL ); +} +/* * ntfs_attr_truncate_i - resize an ntfs attribute * @ni: open ntfs inode to resize
@@ -4984,7 +5059,9 @@ int ntfs_attr_expand(struct ntfs_inode *ni, const s64 newsize, const s64 preallo* newly allocated space is marked as not initialised and no real allocation * on disk is performed. */ -int ntfs_attr_truncate_i (struct ntfs_inode *ni,const s64 newsize,unsigned int holes) +int ntfs_attr_truncate_i_locked (struct ntfs_inode *ni,const s64 newsize, +unsigned int holes, +struct ntfs_inode *locked_ni) {int err;
@@ -5018,15 +5095,23 @@ int ntfs_attr_truncate_i(struct ntfs_inode *ni, const s64 newsize, unsigned intif (NInoNonResident (ni)) {if (newsize > ni->data_size) - err =ntfs_non_resident_attr_expand (ni, newsize,0 , holes, true); + err =ntfs_non_resident_attr_expand ( + ni, newsize,0 , holes, locked_ni);else - err =ntfs_non_resident_attr_shrink (ni, newsize); + err =ntfs_non_resident_attr_shrink ( + ni, newsize, locked_ni); }else err =ntfs_resident_attr_resize (ni, newsize,0 , holes);ntfs_debug ("Return status %d\n" , err);return err; } +int ntfs_attr_truncate_i (struct ntfs_inode *ni,const s64 newsize, +unsigned int holes) +{ +return ntfs_attr_truncate_i_locked (ni, newsize, holes,NULL ); +} +/* * Resize an attribute, creating a hole if relevant */
@@ -5044,10 +5129,11 @@ int ntfs_attr_map_cluster(struct ntfs_inode *ni, s64 vcn_start, s64 *lcn_start,struct ntfs_volume *vol = ni->vol;struct ntfs_attr_search_ctx *ctx;struct runlist_element *rl, *rlc; +struct runlist_element *old_rl =NULL ;s64 vcn = vcn_start, lcn, clu_count;s64 lcn_seek_from =-1 ;int err =0 ; -size_t new_rl_count; +size_t new_rl_count, old_rl_count; err =ntfs_attr_map_whole_runlist (ni);if (err)
@@ -5140,6 +5226,19 @@ int ntfs_attr_map_cluster(struct ntfs_inode *ni, s64 vcn_start, s64 *lcn_start,WARN_ON (rlc->vcn != vcn); lcn = rlc->lcn; clu_count = rlc->length; + old_rl_count = ni->runlist.count; + old_rl =kmemdup (ni->runlist.rl, + old_rl_count *sizeof (*old_rl),GFP_NOFS ); +if (!old_rl) { + err = -ENOMEM ; +if (ntfs_cluster_free_from_rl (vol, rlc)) { +ntfs_error (vol->sb, +"Failed to free cluster allocation after runlist backup failure." ); +NVolSetErrors (vol); + } +kvfree (rlc); + goto out; + } rl =ntfs_runlists_merge (&ni->runlist, rlc,0 , &new_rl_count);if (IS_ERR (rl)) {
@@ -5163,15 +5262,32 @@ int ntfs_attr_map_cluster(struct ntfs_inode *ni, s64 vcn_start, s64 *lcn_start,if (update_mp) {ntfs_attr_reinit_search_ctx (ctx); - err =ntfs_attr_update_mapping_pairs (ni,0 ); + err =ntfs_attr_update_mapping_pairs_locked (ni,0 , ni);if (err) {int err2; err2 =ntfs_cluster_free (ni, vcn, clu_count, ctx); -if (err2 <0 ) +if (err2 <0 || err2 != clu_count) {ntfs_error (vol->sb, -"Failed to free cluster allocation. Leaving inconstant metadata.\n" ); - goto out; +"Failed to free cluster allocation. Leaving inconsistent metadata.\n" ); +NVolSetErrors (vol); + goto out; + } + +/* +* Restore the runlist before repairing the on-disk +* mapping pairs. +*/ +kvfree (ni->runlist.rl); + ni->runlist.rl = old_rl; + ni->runlist.count = old_rl_count; + old_rl =NULL ; +if (ntfs_attr_update_mapping_pairs_locked ( + ni,0 , ni)) { +ntfs_error (vol->sb, +"Failed to restore mapping pairs after allocation rollback.\n" ); +NVolSetErrors (vol); + } } }else {VFS_I (ni)->i_blocks += clu_count << (vol->cluster_size_bits -9 );
@@ -5183,6 +5299,7 @@ int ntfs_attr_map_cluster(struct ntfs_inode *ni, s64 vcn_start, s64 *lcn_start, *lcn_count = clu_count; *balloc = true; out: +kvfree (old_rl);ntfs_attr_put_search_ctx (ctx);return err; }
@@ -5420,7 +5537,7 @@ int ntfs_non_resident_attr_insert_range(struct ntfs_inode *ni, s64 start_vcn, s6 ni->data_size +=ntfs_cluster_to_bytes (vol, len);if (ntfs_cluster_to_bytes (vol, start_vcn) < ni->initialized_size) ni->initialized_size +=ntfs_cluster_to_bytes (vol, len); - ret =ntfs_attr_update_mapping_pairs (ni,0 ); + ret =ntfs_attr_update_mapping_pairs_locked (ni,0 , ni);up_write (&ni->runlist.lock);if (ret)return ret;
@@ -5505,7 +5622,7 @@ int ntfs_non_resident_attr_collapse_range(struct ntfs_inode *ni, s64 start_vcn, }if (ni->allocated_size >0 ) { - ret =ntfs_attr_update_mapping_pairs (ni,0 ); + ret =ntfs_attr_update_mapping_pairs_locked (ni,0 , ni);if (ret) {up_write (&ni->runlist.lock); goto out_rl;
@@ -5583,7 +5700,7 @@ int ntfs_non_resident_attr_punch_hole(struct ntfs_inode *ni, s64 start_vcn, s64 ni->runlist.rl = rl; ni->runlist.count = new_rl_count; - ret =ntfs_attr_update_mapping_pairs (ni,0 ); + ret =ntfs_attr_update_mapping_pairs_locked (ni,0 , ni);up_write (&ni->runlist.lock);if (ret) {kvfree (punch_rl);
@@ -5759,7 +5876,7 @@ int ntfs_attr_fallocate(struct ntfs_inode *ni, loff_t start, loff_t byte_len, boif (NInoRunlistDirty (ni)) {mutex_lock_nested (&ni->mrec_lock,NTFS_INODE_MUTEX_NORMAL );down_write (&ni->runlist.lock); - err =ntfs_attr_update_mapping_pairs (ni,0 ); + err =ntfs_attr_update_mapping_pairs_locked (ni,0 , ni);if (err)ntfs_error (ni->vol->sb,"Updating mapping pairs failed" );else
fs/ntfs/attrib.h +9 -0
@@ -112,7 +112,13 @@ int ntfs_non_resident_attr_punch_hole(struct ntfs_inode *ni, s64 start_vcn, s64int __ntfs_attr_truncate_vfs (struct ntfs_inode *ni,const s64 newsize,const s64 i_size);int ntfs_attr_expand (struct ntfs_inode *ni,const s64 newsize,const s64 prealloc_size); +int ntfs_attr_expand_locked (struct ntfs_inode *ni,const s64 newsize, +const s64 prealloc_size, +struct ntfs_inode *locked_ni);int ntfs_attr_truncate_i (struct ntfs_inode *ni,const s64 newsize,unsigned int holes); +int ntfs_attr_truncate_i_locked (struct ntfs_inode *ni,const s64 newsize, +unsigned int holes, +struct ntfs_inode *locked_ni);int ntfs_attr_truncate (struct ntfs_inode *ni,const s64 newsize);int ntfs_attr_rm (struct ntfs_inode *ni); int ntfs_attr_exist(struct ntfs_inode *ni, const __le32 type, __le16 *name,
@@ -133,6 +139,9 @@ int ntfs_resident_attr_record_add(struct ntfs_inode *ni, __le32 type, __le16 *name, u8 name_len, u8 *val, u32 size, __le16 flags);int ntfs_attr_update_mapping_pairs (struct ntfs_inode *ni,s64 from_vcn); +int ntfs_attr_update_mapping_pairs_locked (struct ntfs_inode *ni, +s64 from_vcn, +struct ntfs_inode *locked_ni);struct runlist_element *ntfs_attr_vcn_to_rl (struct ntfs_inode *ni,s64 vcn,s64 *lcn);/*
fs/ntfs/attrlist.c +32 -14
114 lines not on this page · raw message
fs/ntfs/attrlist.h +2 -0
@@ -16,5 +16,7 @@ int ntfs_attrlist_need(struct ntfs_inode *ni);int ntfs_attrlist_entry_add (struct ntfs_inode *ni,struct attr_record *attr);int ntfs_attrlist_entry_rm (struct ntfs_attr_search_ctx *ctx);int ntfs_attrlist_update (struct ntfs_inode *base_ni); +int ntfs_attrlist_update_locked (struct ntfs_inode *base_ni, +struct ntfs_inode *locked_ni);#endif /* defined _NTFS_ATTRLIST_H */
fs/ntfs/compress.c +1 -1
@@ -1390,7 +1390,7 @@ static int ntfs_write_cb(struct ntfs_inode *ni, loff_t pos, struct page **pages, ni->runlist.count = new_rl_count; ni->runlist.rl = rl; - err =ntfs_attr_update_mapping_pairs (ni,0 ); + err =ntfs_attr_update_mapping_pairs_locked (ni,0 , ni);up_write (&ni->runlist.lock);if (err) { err = -EIO ;
fs/ntfs/file.c +2 -1
@@ -111,7 +111,8 @@ static int ntfs_trim_prealloc(struct inode *vi)ntfs_error (vol->sb,"Preallocated block rollback failed" ); }else { ni->allocated_size =ntfs_cluster_to_bytes (vol, vcn_tr); - err =ntfs_attr_update_mapping_pairs (ni,0 ); + err =ntfs_attr_update_mapping_pairs_locked ( + ni,0 , ni);if (err)ntfs_error (vol->sb,"Failed to rollback mapping pairs for prealloc" );
fs/ntfs/inode.c +1 -1
@@ -2772,7 +2772,7 @@ int __ntfs_write_inode(struct inode *vi, int sync)if (NInoNonResident (ni) &&NInoRunlistDirty (ni)) {down_write (&ni->runlist.lock); - err =ntfs_attr_update_mapping_pairs (ni,0 ); + err =ntfs_attr_update_mapping_pairs_locked (ni,0 , ni);if (!err)NInoClearRunlistDirty (ni);up_write (&ni->runlist.lock);
fs/ntfs/mft.c +8 -5
@@ -1131,7 +1131,8 @@ static s64 mft_bitmap_alloc_free_rec(struct ntfs_volume *vol,return ll; } -static int ntfs_mft_attr_extend (struct ntfs_inode *ni) +static int ntfs_mft_attr_extend (struct ntfs_inode *ni, +struct ntfs_inode *locked_ni) {int ret =0 ;struct ntfs_inode *base_ni;
@@ -1152,7 +1153,7 @@ static int ntfs_mft_attr_extend(struct ntfs_inode *ni) } } - ret =ntfs_attr_update_mapping_pairs (ni,0 ); + ret =ntfs_attr_update_mapping_pairs_locked (ni,0 , locked_ni);if (ret)pr_err ("MP update failed\n" );
@@ -1340,7 +1341,7 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(struct ntfs_volume *vol) ret =ntfs_attr_record_resize (ctx->mrec, a, mp_size +le16_to_cpu (a->data.non_resident.mapping_pairs_offset));if (unlikely (ret)) { - ret =ntfs_mft_attr_extend (mftbmp_ni); + ret =ntfs_mft_attr_extend (mftbmp_ni, mftbmp_ni);if (!ret) goto extended_ok;if (ret != -EAGAIN )
@@ -1451,7 +1452,9 @@ static int ntfs_mft_bitmap_extend_allocation_nolock(struct ntfs_volume *vol)NVolSetErrors (vol); }mark_mft_record_dirty (ctx->ntfs_ino); - }else if (status.mp_extended &&ntfs_attr_update_mapping_pairs (mftbmp_ni,0 )) { + }else if (status.mp_extended && +ntfs_attr_update_mapping_pairs_locked (mftbmp_ni,0 , + mftbmp_ni)) {ntfs_error (vol->sb,"Failed to restore mapping pairs.%s" , es);NVolSetErrors (vol); }
@@ -1776,7 +1779,7 @@ static int ntfs_mft_data_extend_allocation_nolock(struct ntfs_volume *vol) ret =ntfs_attr_record_resize (ctx->mrec, a, mp_size +le16_to_cpu (a->data.non_resident.mapping_pairs_offset));if (unlikely (ret)) { - ret =ntfs_mft_attr_extend (mft_ni); + ret =ntfs_mft_attr_extend (mft_ni,NULL );if (!ret) goto extended_ok;if (ret != -EAGAIN )
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 124/438 ntfs: propagate folio errors
In reply to Greg Kroah-Hartman7.2-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namjae Jeon <[email protected]>
[ Upstream commit 1923eeffa63edeff427d76fc302bc5eb835771ce ]
Return the error from __filemap_get_folio() instead of replacing it with -ENOMEM.
--- fs/ntfs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ntfs/inode.c +1 -1
@@ -3713,7 +3713,7 @@ static s64 __ntfs_inode_non_resident_attr_pwrite(struct inode *vi,FGP_CREAT |FGP_LOCK , mapping_gfp_mask(mapping));if (IS_ERR (folio)) { - ret = -ENOMEM ; + ret =PTR_ERR (folio);break ; } }else {
Signature · 1 line
2.53.0